This is an automated email from the ASF dual-hosted git repository.
sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-release.git
The following commit(s) were added to refs/heads/main by this push:
new 642450c Fix the order of functions in several modules
642450c is described below
commit 642450c76c16b82756a662f9b39f4c87771afbc7
Author: Sean B. Palmer <[email protected]>
AuthorDate: Mon Apr 14 20:27:52 2025 +0100
Fix the order of functions in several modules
---
atr/config.py | 14 ++++-----
atr/metadata.py | 8 ++---
atr/server.py | 76 +++++++++++++++++++++++-----------------------
atr/ssh.py | 54 ++++++++++++++++----------------
atr/user.py | 8 ++---
atr/util.py | 12 ++++----
atr/worker.py | 36 +++++++++++-----------
scripts/interface_order.py | 19 +++++++++---
8 files changed, 118 insertions(+), 109 deletions(-)
diff --git a/atr/config.py b/atr/config.py
index 4fa9464..5cb2d5b 100644
--- a/atr/config.py
+++ b/atr/config.py
@@ -90,6 +90,13 @@ _CONFIG_DICT: Final = {
}
+def get() -> type[AppConfig]:
+ try:
+ return _CONFIG_DICT[get_mode()]
+ except KeyError:
+ exit("Error: Invalid <mode>. Expected values [Debug, Production,
Profiling].")
+
+
def get_mode() -> Mode:
global _global_mode
@@ -102,10 +109,3 @@ def get_mode() -> Mode:
_global_mode = Mode.Debug
return _global_mode
-
-
-def get() -> type[AppConfig]:
- try:
- return _CONFIG_DICT[get_mode()]
- except KeyError:
- exit("Error: Invalid <mode>. Expected values [Debug, Production,
Profiling].")
diff --git a/atr/metadata.py b/atr/metadata.py
index a262ebf..8833679 100644
--- a/atr/metadata.py
+++ b/atr/metadata.py
@@ -16,6 +16,10 @@
# under the License.
+def _get_undefined() -> tuple[str, str]:
+ return "undefined", "undefined"
+
+
def _get_version_from_git() -> tuple[str, str] | None:
"""Returns the version when within a development environment."""
@@ -62,10 +66,6 @@ def _get_version_from_version_module() -> tuple[str, str] |
None:
return None
-def _get_undefined() -> tuple[str, str]:
- return "undefined", "undefined"
-
-
# Try to determine the version from a development environment first.
# If this fails, try to get it from environment variables that are set when
building a docker image.
# We don't use __version__ and __commit__ as these are not reserved words in
Python
diff --git a/atr/server.py b/atr/server.py
index a87e45b..f49ce1e 100644
--- a/atr/server.py
+++ b/atr/server.py
@@ -60,35 +60,13 @@ class ApiOnlyOpenAPIProvider(quart_schema.OpenAPIProvider):
yield rule
-def register_routes(app: base.QuartApp) -> ModuleType:
- # NOTE: These imports are for their side effects only
- import atr.routes.modules as modules
-
- # Add a global error handler to show helpful error messages with tracebacks
- @app.errorhandler(Exception)
- async def handle_any_exception(error: Exception) -> Any:
- import traceback
-
- # Required to give to the error.html template
- tb = traceback.format_exc()
- app.logger.exception("Unhandled exception")
- return await quart.render_template("error.html", error=str(error),
traceback=tb, status_code=500), 500
-
- @app.errorhandler(base.ASFQuartException)
- async def handle_asfquart_exception(error: base.ASFQuartException) -> Any:
- # TODO: Figure out why pyright doesn't know about this attribute
- if not hasattr(error, "errorcode"):
- errorcode = 500
- else:
- errorcode = getattr(error, "errorcode")
- return await quart.render_template("error.html", error=str(error),
status_code=errorcode), errorcode
-
- # Add a global error handler in case a page does not exist.
- @app.errorhandler(404)
- async def handle_not_found(error: Exception) -> Any:
- return await quart.render_template("notfound.html", error="404 Not
Found", traceback="", status_code=404), 404
-
- return modules
+def app_create_base(app_config: type[config.AppConfig]) -> base.QuartApp:
+ """Create the base Quart application."""
+ if asfquart.construct is ...:
+ raise ValueError("asfquart.construct is not set")
+ app = asfquart.construct(__name__)
+ app.config.from_object(app_config)
+ return app
def app_dirs_setup(app_config: type[config.AppConfig]) -> None:
@@ -103,15 +81,6 @@ def app_dirs_setup(app_config: type[config.AppConfig]) ->
None:
util.get_release_dir().mkdir(parents=True, exist_ok=True)
-def app_create_base(app_config: type[config.AppConfig]) -> base.QuartApp:
- """Create the base Quart application."""
- if asfquart.construct is ...:
- raise ValueError("asfquart.construct is not set")
- app = asfquart.construct(__name__)
- app.config.from_object(app_config)
- return app
-
-
def app_setup_api_docs(app: base.QuartApp) -> None:
"""Configure OpenAPI documentation."""
import quart_schema
@@ -253,6 +222,37 @@ def main() -> None:
app.run(port=8080, ssl_keyfile="key.pem", ssl_certfile="cert.pem")
+def register_routes(app: base.QuartApp) -> ModuleType:
+ # NOTE: These imports are for their side effects only
+ import atr.routes.modules as modules
+
+ # Add a global error handler to show helpful error messages with tracebacks
+ @app.errorhandler(Exception)
+ async def handle_any_exception(error: Exception) -> Any:
+ import traceback
+
+ # Required to give to the error.html template
+ tb = traceback.format_exc()
+ app.logger.exception("Unhandled exception")
+ return await quart.render_template("error.html", error=str(error),
traceback=tb, status_code=500), 500
+
+ @app.errorhandler(base.ASFQuartException)
+ async def handle_asfquart_exception(error: base.ASFQuartException) -> Any:
+ # TODO: Figure out why pyright doesn't know about this attribute
+ if not hasattr(error, "errorcode"):
+ errorcode = 500
+ else:
+ errorcode = getattr(error, "errorcode")
+ return await quart.render_template("error.html", error=str(error),
status_code=errorcode), errorcode
+
+ # Add a global error handler in case a page does not exist.
+ @app.errorhandler(404)
+ async def handle_not_found(error: Exception) -> Any:
+ return await quart.render_template("notfound.html", error="404 Not
Found", traceback="", status_code=404), 404
+
+ return modules
+
+
# FIXME: when running in SSL mode, you will receive these exceptions upon
termination at times:
# ssl.SSLError: [SSL: APPLICATION_DATA_AFTER_CLOSE_NOTIFY] application
data after close notify (_ssl.c:2706)
# related ticket: https://github.com/pgjones/hypercorn/issues/261
diff --git a/atr/ssh.py b/atr/ssh.py
index 2d7c769..8f7f8bd 100644
--- a/atr/ssh.py
+++ b/atr/ssh.py
@@ -294,6 +294,33 @@ def _fail(proc: asyncssh.SSHServerProcess, message: str,
return_value: T) -> T:
return return_value
+async def _handle_client(process: asyncssh.SSHServerProcess) -> None:
+ """Process client command by executing it and redirecting I/O."""
+ asf_uid = process.get_extra_info("username")
+ _LOGGER.info(f"Handling command for authenticated user: {asf_uid}")
+
+ if not process.command:
+ process.stderr.write(b"ATR SSH error: No command specified\n")
+ process.exit(1)
+ return
+
+ _LOGGER.info(f"Command received: {process.command}")
+ argv = process.command.split()
+
+ simple_validation_error, path_index = _command_simple_validate(argv)
+ if simple_validation_error:
+ process.stderr.write(f"ATR SSH error:
{simple_validation_error}\nCommand: {process.command}\n".encode())
+ process.exit(1)
+ return
+
+ validation_results = await _command_validate(process, argv, path_index)
+ if not validation_results:
+ return
+ project_name, version_name = validation_results
+
+ await _process_validated_rsync(process, argv, path_index, project_name,
version_name)
+
+
async def _process_validated_rsync(
process: asyncssh.SSHServerProcess,
argv: list[str],
@@ -337,30 +364,3 @@ async def _process_validated_rsync(
_fail(process, f"Internal error processing revision: {e}", None)
if not process.is_closing():
process.exit(1)
-
-
-async def _handle_client(process: asyncssh.SSHServerProcess) -> None:
- """Process client command by executing it and redirecting I/O."""
- asf_uid = process.get_extra_info("username")
- _LOGGER.info(f"Handling command for authenticated user: {asf_uid}")
-
- if not process.command:
- process.stderr.write(b"ATR SSH error: No command specified\n")
- process.exit(1)
- return
-
- _LOGGER.info(f"Command received: {process.command}")
- argv = process.command.split()
-
- simple_validation_error, path_index = _command_simple_validate(argv)
- if simple_validation_error:
- process.stderr.write(f"ATR SSH error:
{simple_validation_error}\nCommand: {process.command}\n".encode())
- process.exit(1)
- return
-
- validation_results = await _command_validate(process, argv, path_index)
- if not validation_results:
- return
- project_name, version_name = validation_results
-
- await _process_validated_rsync(process, argv, path_index, project_name,
version_name)
diff --git a/atr/user.py b/atr/user.py
index 5cc163f..333fd62 100644
--- a/atr/user.py
+++ b/atr/user.py
@@ -47,16 +47,16 @@ def is_admin(user_id: str | None) -> bool:
return user_id in get_admin_users()
-def is_committer(committee: models.Committee | None, uid: str) -> bool:
+def is_committee_member(committee: models.Committee | None, uid: str) -> bool:
if committee is None:
return False
- return any((committer_uid == uid) for committer_uid in
committee.committers)
+ return any((member_uid == uid) for member_uid in
committee.committee_members)
-def is_committee_member(committee: models.Committee | None, uid: str) -> bool:
+def is_committer(committee: models.Committee | None, uid: str) -> bool:
if committee is None:
return False
- return any((member_uid == uid) for member_uid in
committee.committee_members)
+ return any((committer_uid == uid) for committer_uid in
committee.committers)
async def projects(uid: str, committee_only: bool = False) ->
list[models.Project]:
diff --git a/atr/util.py b/atr/util.py
index ffc0403..6f5b178 100644
--- a/atr/util.py
+++ b/atr/util.py
@@ -236,22 +236,22 @@ def get_phase_dir() -> pathlib.Path:
return pathlib.Path(config.get().PHASE_STORAGE_DIR)
-def get_release_candidate_draft_dir() -> pathlib.Path:
- return pathlib.Path(config.get().PHASE_STORAGE_DIR) /
"release-candidate-draft"
-
-
def get_release_candidate_dir() -> pathlib.Path:
return pathlib.Path(config.get().PHASE_STORAGE_DIR) / "release-candidate"
-def get_release_preview_dir() -> pathlib.Path:
- return pathlib.Path(config.get().PHASE_STORAGE_DIR) / "release-preview"
+def get_release_candidate_draft_dir() -> pathlib.Path:
+ return pathlib.Path(config.get().PHASE_STORAGE_DIR) /
"release-candidate-draft"
def get_release_dir() -> pathlib.Path:
return pathlib.Path(config.get().PHASE_STORAGE_DIR) / "release"
+def get_release_preview_dir() -> pathlib.Path:
+ return pathlib.Path(config.get().PHASE_STORAGE_DIR) / "release-preview"
+
+
def is_user_viewing_as_admin(uid: str | None) -> bool:
"""Check whether a user is currently viewing the site with active admin
privileges."""
if not user.is_admin(uid):
diff --git a/atr/worker.py b/atr/worker.py
index 4cc55e9..24a2d05 100644
--- a/atr/worker.py
+++ b/atr/worker.py
@@ -174,24 +174,6 @@ async def _task_next_claim() -> tuple[int, str, list[str]
| dict[str, Any]] | No
return None
-async def _task_result_process(
- task_id: int, task_results: tuple[Any, ...], status: models.TaskStatus,
error: str | None = None
-) -> None:
- """Process and store task results in the database."""
- async with db.session() as data:
- async with data.begin():
- # Find the task by ID
- task_obj = await data.task(id=task_id).get()
- if task_obj:
- # Update task properties
- task_obj.status = status
- task_obj.completed = datetime.datetime.now(datetime.UTC)
- task_obj.result = task_results
-
- if (status == task.FAILED) and error:
- task_obj.error = error
-
-
async def _task_process(task_id: int, task_type: str, task_args: list[str] |
dict[str, Any]) -> None:
"""Process a claimed task."""
_LOGGER.info(f"Processing task {task_id} ({task_type}) with raw args
{task_args}")
@@ -261,6 +243,24 @@ async def _task_process(task_id: int, task_type: str,
task_args: list[str] | dic
await _task_result_process(task_id, task_results, status, error)
+async def _task_result_process(
+ task_id: int, task_results: tuple[Any, ...], status: models.TaskStatus,
error: str | None = None
+) -> None:
+ """Process and store task results in the database."""
+ async with db.session() as data:
+ async with data.begin():
+ # Find the task by ID
+ task_obj = await data.task(id=task_id).get()
+ if task_obj:
+ # Update task properties
+ task_obj.status = status
+ task_obj.completed = datetime.datetime.now(datetime.UTC)
+ task_obj.result = task_results
+
+ if (status == task.FAILED) and error:
+ task_obj.error = error
+
+
# Worker functions
diff --git a/scripts/interface_order.py b/scripts/interface_order.py
index 332bab4..c288847 100644
--- a/scripts/interface_order.py
+++ b/scripts/interface_order.py
@@ -16,8 +16,8 @@ class ExitCode(enum.IntEnum):
def _extract_top_level_function_names(tree: ast.Module) -> list[str]:
function_names: list[str] = []
for node in tree.body:
- if isinstance(node, ast.FunctionDef):
- function_names.append(node.name)
+ if isinstance(node, ast.AsyncFunctionDef) or isinstance(node,
ast.FunctionDef):
+ function_names.append(_toggle_sortability(node.name))
return function_names
@@ -40,6 +40,13 @@ def _read_file_content(file_path: pathlib.Path) -> str |
None:
return None
+def _toggle_sortability(name: str) -> str:
+ if name.startswith("_"):
+ return name[1:]
+ else:
+ return "_" + name
+
+
def _verify_names_are_sorted(names: Sequence[str], filename: str) -> bool:
is_sorted = all(names[i] <= names[i + 1] for i in range(len(names) - 1))
if is_sorted:
@@ -47,8 +54,10 @@ def _verify_names_are_sorted(names: Sequence[str], filename:
str) -> bool:
for i in range(len(names) - 1):
if names[i] > names[i + 1]:
+ a = _toggle_sortability(names[i])
+ b = _toggle_sortability(names[i + 1])
print(
- f"Error: Function '{names[i + 1]}' in {filename} is not
ordered correctly relative to '{names[i]}'",
+ f"Error: Function '{b}' in {filename} is not ordered correctly
relative to '{a}'",
file=sys.stderr,
)
return False
@@ -72,11 +81,11 @@ def main() -> None:
function_names = _extract_top_level_function_names(tree)
if not function_names:
- print(f"No top-level functions found in {file_path}. Nothing to check")
+ print(f"No top level functions found in {file_path}. Nothing to check")
sys.exit(ExitCode.SUCCESS)
if _verify_names_are_sorted(function_names, str(file_path)):
- print(f"Top-level functions in {file_path} are alphabetically ordered")
+ print(f"Top level functions in {file_path} are alphabetically ordered")
sys.exit(ExitCode.SUCCESS)
else:
sys.exit(ExitCode.FAILURE)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]