Skip to content

Commit 4623101

Browse files
Chore/maintenance 251206 (#320)
* sec(install): bash and ensure ssl * chore(deps): bump * refactor(various): given issues identified by SonarQube * chore(audit): allow Zope Public License for audit
1 parent cd6d34a commit 4623101

File tree

12 files changed

+7400
-10405
lines changed

12 files changed

+7400
-10405
lines changed

.github/workflows/_install_dev_tools.bash

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ set -o pipefail # Return value of a pipeline is the value of the last command t
66
# Log function for better debugging
77
log() {
88
echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')] $*"
9+
return 0
910
}
1011

1112
log "Starting installation of development tools..."
@@ -14,13 +15,16 @@ log "Starting installation of development tools..."
1415
sudo rm -f /var/lib/man-db/auto-update
1516

1617
# Install APT packages
17-
wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
18-
echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list
18+
# Use signed-by to add GPG key securely (apt-key is deprecated)
19+
mkdir -p /etc/apt/keyrings
20+
wget --secure-protocol=TLSv1_2 --max-redirect=0 -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | gpg --dearmor | sudo tee /etc/apt/keyrings/trivy.gpg > /dev/null
21+
echo "deb [signed-by=/etc/apt/keyrings/trivy.gpg] https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/trivy.list
1922
sudo apt-get update
2023
sudo apt-get install --no-install-recommends -y curl gnupg2 jq trivy xsltproc
2124

2225
# Install further tools not project specific
23-
curl -sL https://sentry.io/get-cli/ | SENTRY_CLI_VERSION="2.57.0" sh
26+
# Download Sentry CLI securely: enforce HTTPS, disable redirects
27+
wget --secure-protocol=TLSv1_2 --max-redirect=0 -qO - https://sentry.io/get-cli/ | SENTRY_CLI_VERSION="2.57.0" sh
2428

2529
# Install project specific tools
2630
.github/workflows/_install_dev_tools_project.bash

.license-types-allowed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ UNKNOWN
2121
Unlicense
2222

2323
# Additions for aignostics
24+
Zope Public License

ATTRIBUTIONS.md

Lines changed: 7134 additions & 10174 deletions
Large diffs are not rendered by default.

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ act audit bump dist docs lint lint_fix setup test update_from_template:
5454

5555
## Install development dependencies and pre-commit hooks
5656
install:
57-
sh install.sh
57+
bash install.bash
5858
uv run pre-commit install
5959

6060
## Run default tests, i.e. unit, then integration, then e2e tests, no (very_)long_running tests, single Python version

install.sh renamed to install.bash

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ ENV="local"
66

77
# Parse command line arguments
88
i=0
9-
while [ $i -lt $# ]; do
9+
while [[ $i -lt $# ]]; do
1010
i=$((i + 1))
1111
arg="${!i}"
1212

@@ -16,7 +16,7 @@ while [ $i -lt $# ]; do
1616
;;
1717
--env)
1818
i=$((i + 1))
19-
if [ $i -le $# ]; then
19+
if [[ $i -le $# ]]; then
2020
ENV="${!i}"
2121
fi
2222
;;
@@ -76,14 +76,14 @@ should_install_in_env() {
7676
local environments=$1
7777

7878
# If environments is empty, install in all environments
79-
if [ -z "$environments" ]; then
79+
if [[ -z "$environments" ]]; then
8080
return 0 # true
8181
fi
8282

8383
# Check if the current environment is in the list
8484
IFS=',' read -ra ENV_LIST <<< "$environments"
8585
for e in "${ENV_LIST[@]}"; do
86-
if [ "$e" = "$ENV" ]; then
86+
if [[ "$e" = "$ENV" ]]; then
8787
return 0 # true
8888
fi
8989
done
@@ -172,13 +172,13 @@ fi
172172
# Install/update Homebrew itself
173173
if ! command -v brew &> /dev/null; then
174174
# Check if we should install Homebrew in this environment
175-
if [ "$ENV" = "local" ]; then
175+
if [[ "$ENV" = "local" ]]; then
176176
echo "Installing Homebrew... # https://brew.sh/"
177-
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
177+
/bin/bash -c "$(curl --proto "=https" -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
178178
else
179179
echo "Skipping Homebrew installation (not needed in $ENV environment)"
180180
fi
181-
elif [ "$ENV" = "local" ]; then
181+
elif [[ "$ENV" = "local" ]]; then
182182
echo "Homebrew already installed at $(command -v brew), updating..."
183183
brew update
184184
fi

noxfile.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
CLI_MODULE = "cli"
2424
API_VERSIONS = ["v1"]
2525
UTF8 = "utf-8"
26+
LOG_STDERR_DISABLED = "AIGNOSTICS_LOG_STDERR_ENABLED=false"
2627

2728

2829
def _read_python_version() -> str:
@@ -420,8 +421,8 @@ def _generate_openapi_schemas(session: nox.Session) -> None:
420421
Path("docs/source/_static").mkdir(parents=True, exist_ok=True)
421422

422423
formats = {
423-
"yaml": {"ext": "yaml", "args": ["--output-format=yaml", "--env", "AIGNOSTICS_LOG_STDERR_ENABLED=false"]},
424-
"json": {"ext": "json", "args": ["--output-format=json", "--env", "AIGNOSTICS_LOG_STDERR_ENABLED=false"]},
424+
"yaml": {"ext": "yaml", "args": ["--output-format=yaml", "--env", LOG_STDERR_DISABLED]},
425+
"json": {"ext": "json", "args": ["--output-format=json", "--env", LOG_STDERR_DISABLED]},
425426
}
426427

427428
for version in API_VERSIONS:
@@ -455,7 +456,7 @@ def _generate_sdk_metadata_schema(session: nox.Session, schema_type: str) -> Non
455456
f"{schema_type}-metadata-schema",
456457
"--no-pretty",
457458
"--env",
458-
"AIGNOSTICS_LOG_STDERR_ENABLED=false",
459+
LOG_STDERR_DISABLED,
459460
stdout=f,
460461
external=True,
461462
)

pyproject.toml

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -74,26 +74,26 @@ requires-python = ">=3.11, <3.14"
7474

7575
dependencies = [
7676
# From Template
77-
"fastapi[all,standard]>=0.123.8",
77+
"fastapi[all,standard]>=0.123.10",
7878
"humanize>=4.14.0,<5",
7979
"nicegui[native]>=3.1.0,<3.2.0", # Regression in 3.2.0
8080
"packaging>=25.0,<26",
81-
"platformdirs>=4.5.0,<5",
81+
"platformdirs>=4.5.1,<5",
8282
"psutil>=7.1.3,<8",
8383
"pydantic-settings>=2.12.0,<3",
8484
"pywin32>=310,<311 ; sys_platform == 'win32'",
8585
"pyyaml>=6.0.3,<7",
86-
"sentry-sdk>=2.45.0,<3",
86+
"sentry-sdk>=2.47.0,<3",
8787
"typer>=0.20.0,<1",
8888
"uptime>=3.0.1,<4",
8989
# Custom
9090
"boto3>=1.42.4,<2",
91-
"certifi>=2025.11.12,<2026",
91+
"certifi>=2025.11.12",
9292
"defusedxml>=0.7.1",
9393
"dicom-validator>=0.7.3,<1",
9494
"dicomweb-client[gcp]>=0.59.3,<1",
9595
"duckdb>=0.10.0,<=1.4.1",
96-
"fastparquet>=2024.11.0,<2025",
96+
"fastparquet>=2024.11.0",
9797
"google-cloud-storage>=3.6.0,<4",
9898
"google-crc32c>=1.7.1,<2",
9999
"highdicom>=0.26.1,<1",
@@ -103,11 +103,11 @@ dependencies = [
103103
"ijson>=3.4.0.post0,<4",
104104
"jsf>=0.11.2,<1",
105105
"jsonschema[format-nongpl]>=4.25.1,<5",
106-
"loguru>=0.7.3",
107-
"openslide-bin>=4.0.0.8,<5",
108-
"openslide-python>=1.4.2,<2",
106+
"loguru>=0.7.3,<1",
107+
"openslide-bin>=4.0.0.10,<5",
108+
"openslide-python>=1.4.3,<2",
109109
"pandas>=2.3.3,<3",
110-
"platformdirs>=4.3.8,<5",
110+
"platformdirs>=4.3.2,<5",
111111
"procrastinate>=3.5.3",
112112
"pyjwt[crypto]>=2.10.1,<3",
113113
"python-dateutil>=2.9.0.post0,<3",
@@ -129,8 +129,8 @@ pyinstaller = ["pyinstaller>=6.14.0,<7"]
129129
jupyter = ["jupyter>=1.1.1,<2"]
130130
marimo = [
131131
"cloudpathlib>=0.23.0,<1",
132-
"ipython>=9.7.0,<10",
133-
"marimo>=0.17.8,<1",
132+
"ipython>=9.8.0,<10",
133+
"marimo>=0.18.3,<1",
134134
"matplotlib>=3.10.7,<4",
135135
"shapely>=2.1.0,<3",
136136
]
@@ -142,15 +142,15 @@ dev = [
142142
"cyclonedx-py>=1.0.1,<2",
143143
"detect-secrets>=1.5.0,<2",
144144
"enum-tools>=0.13.0,<1",
145-
"furo>=2025.9.25,<2026",
145+
"furo>=2025.9.25",
146146
"git-cliff>=2.10.1,<3",
147-
"mypy>=1.18.2,<2",
148-
"nox[uv]>=2025.11.12,<2026",
149-
"pip-audit>=2.9.0,<3",
147+
"mypy>=1.19.0,<2",
148+
"nox[uv]>=2025.11.12",
149+
"pip-audit>=2.10.0,<3",
150150
"pip-licenses @ git+https://github.com/neXenio/pip-licenses.git@master", # https://github.com/raimon49/pip-licenses/pull/224
151-
"pre-commit>=4.4.0,<5",
151+
"pre-commit>=4.5.0,<5",
152152
"pyright>=1.1.406,<1.1.407", # Regression in 1.1.407, see https://github.com/microsoft/pyright/issues/11060
153-
"pytest>=8.4.2,<9",
153+
"pytest>=9.0.1,<10",
154154
"pytest-asyncio>=1.3.0,<2",
155155
"pytest-cov>=7.0.0,<8",
156156
"pytest-docker>=3.2.5,<4",
@@ -164,19 +164,19 @@ dev = [
164164
"pytest-timeout>=2.4.0,<3",
165165
"pytest-watcher>=0.4.3,<1",
166166
"pytest-xdist[psutil]>=3.8.0,<4",
167-
"ruff>=0.14.5,<1",
167+
"ruff>=0.14.8,<1",
168168
"scalene>=1.5.55,<2",
169169
"sphinx>=8.2.3,<9",
170170
"sphinx-autobuild>=2025.8.25,<2026",
171-
"sphinx-click>=6.1.0,<7",
171+
"sphinx-click>=6.2.0,<7",
172172
"sphinx-copybutton>=0.5.2,<1",
173173
"sphinx-inline-tabs>=2023.4.21,<2024",
174174
"sphinx-mdinclude>=0.6.2,<1",
175175
"sphinx-rtd-theme>=3.0.2,<4",
176176
"sphinx_selective_exclude>=1.0.3,<2",
177-
"sphinx-toolbox>=4.0.0,<5",
177+
"sphinx-toolbox>=4.1.0,<5",
178178
"sphinxext.opengraph>=0.9.1,<1",
179-
"swagger-plugin-for-sphinx>=6.0.0,<7",
179+
"swagger-plugin-for-sphinx>=6.1.0,<7",
180180
"tomli>=2.3.0,<3",
181181
"types-pyyaml>=6.0.12.20250915,<7",
182182
"types-requests>=2.32.4.20250913,<3",
@@ -201,6 +201,7 @@ override-dependencies = [ # https://github.com/astral-sh/uv/issues/4422
201201
"fonttools>=4.60.2", # CVE-2025-66034 (GHSA-768j-98cg-p3fv), dep of matplotlib
202202
"pyjpegls; sys_platform == 'never'", # Python 3.14
203203
"urllib3>=2.6.0", # CVE-2025-66471 (GHSA-2xpw-w6gg-jr37), dep of boto3, dicomweb-client and others
204+
"pytest>=9.0.1", # pytest-md-report depends on pytest<9 unnecessarily
204205
]
205206

206207
[tool.uv.sources]

setup.sh

Lines changed: 0 additions & 35 deletions
This file was deleted.

src/aignostics/application/_cli.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
)
3838

3939
MESSAGE_NOT_YET_IMPLEMENTED = "NOT YET IMPLEMENTED"
40+
PROGRESS_TASK_DESCRIPTION = "[progress.description]{task.description}"
4041

4142

4243
ApplicationVersionOption = Annotated[
@@ -219,7 +220,7 @@ def application_dump_schemata( # noqa: C901
219220
resolve_path=True,
220221
show_default="<current-working-directory>",
221222
),
222-
] = Path().cwd(), # noqa: B008,
223+
] = Path().cwd(), # noqa: B008
223224
zip: Annotated[ # noqa: A002
224225
bool,
225226
typer.Option(
@@ -236,7 +237,7 @@ def application_dump_schemata( # noqa: C901
236237
logger.warning(message)
237238
console.print(f"[warning]Warning:[/warning] {message}")
238239
sys.exit(2)
239-
except (Exception, RuntimeError) as e:
240+
except Exception as e:
240241
message = f"Failed to load application version with ID '{id}': {e!s}."
241242
logger.exception(message)
242243
console.print(f"[warning]Error:[/warning] {message}")
@@ -670,7 +671,7 @@ def run_upload(
670671
FileSizeColumn(),
671672
TotalFileSizeColumn(),
672673
TransferSpeedColumn(),
673-
TextColumn("[progress.description]{task.description}"),
674+
TextColumn(PROGRESS_TASK_DESCRIPTION),
674675
) as progress:
675676
task = progress.add_task(f"Uploading to {upload_prefix}/...", total=total_bytes)
676677

@@ -761,7 +762,7 @@ def run_submit( # noqa: PLR0913, PLR0917
761762
f"(version: {application_version})': {e}"
762763
)
763764
sys.exit(2)
764-
except (Exception, RuntimeError) as e:
765+
except Exception as e:
765766
message = (
766767
f"Failed to load application version '{application_version}' for application '{application_id}': {e!s}."
767768
)
@@ -1308,15 +1309,15 @@ def result_download( # noqa: C901, PLR0913, PLR0915, PLR0917
13081309
main_download_progress_ui = Progress(
13091310
BarColumn(),
13101311
TaskProgressColumn(),
1311-
TextColumn("[progress.description]{task.description}"),
1312+
TextColumn(PROGRESS_TASK_DESCRIPTION),
13121313
TimeElapsedColumn(),
13131314
TimeRemainingColumn(),
13141315
TextColumn("{task.fields[extra_description]}"),
13151316
)
13161317
artifact_download_progress_ui = Progress(
13171318
BarColumn(),
13181319
TaskProgressColumn(),
1319-
TextColumn("[progress.description]{task.description}"),
1320+
TextColumn(PROGRESS_TASK_DESCRIPTION),
13201321
TimeElapsedColumn(),
13211322
TimeRemainingColumn(),
13221323
FileSizeColumn(),

src/aignostics/application/_gui/_page_application_describe.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
CLASS_SUBSECTION_HEADER = "text-h6 mb-0 pb-0"
4040
CLASS_WIDTH_ONE_THIRD = "w-1/3"
4141
CLASS_WIDTH_ONE_HALF = "w-1/2"
42+
DATETIME_MASK = "YYYY-MM-DD HH:mm"
4243

4344

4445
@binding.bindable_dataclass
@@ -645,13 +646,13 @@ class ThumbnailRenderer {
645646
with ui.row().classes("full-width"):
646647
ui.label("")
647648
due_date_date_picker = (
648-
ui.date(mask="YYYY-MM-DD HH:mm")
649+
ui.date(mask=DATETIME_MASK)
649650
.bind_value(submit_form, "due_date")
650651
.props(f":options=\"(date) => date >= '{today}'\"")
651652
.mark("DATE_DUE_DATE")
652653
)
653654
due_date_time_picker = (
654-
ui.time(mask="YYYY-MM-DD HH:mm")
655+
ui.time(mask=DATETIME_MASK)
655656
.bind_value(submit_form, "due_date")
656657
.props("format24h now-btn")
657658
.mark("TIME_DUE_DATE")
@@ -695,12 +696,12 @@ class ThumbnailRenderer {
695696
"text-sm mt-0 pt-0"
696697
)
697698
with ui.row().classes("full-width"):
698-
ui.date(mask="YYYY-MM-DD HH:mm").bind_value(submit_form, "deadline").props(
699+
ui.date(mask=DATETIME_MASK).bind_value(submit_form, "deadline").props(
699700
f":options=\"(date) => date >= '{today}'\""
700701
).mark("DATE_DEADLINE")
701-
ui.time(mask="YYYY-MM-DD HH:mm").bind_value(submit_form, "deadline").props(
702-
"format24h now-btn"
703-
).mark("TIME_DEADLINE")
702+
ui.time(mask=DATETIME_MASK).bind_value(submit_form, "deadline").props("format24h now-btn").mark(
703+
"TIME_DEADLINE"
704+
)
704705

705706
def _scheduling_next() -> None:
706707
if submit_form.upload_and_submit_button is None:

0 commit comments

Comments
 (0)