Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ FROM python:3.12-slim AS builder
WORKDIR /build

# Install Poetry and export plugin
RUN pip install poetry==1.8.3
RUN pip install poetry==2.0.1

# Copy dependency files
COPY pyproject.toml poetry.lock README.md ./
Expand Down
407 changes: 363 additions & 44 deletions poetry.lock

Large diffs are not rendered by default.

73 changes: 38 additions & 35 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,52 +1,54 @@
# https://python-poetry.org/docs/pyproject/

[tool.poetry]
[project]
name = "regression_model_template"
version = "2.0.0"
description = "Predict the number of regression_model_template available."
authors = ["lgcorzo"]
authors = [{ name = "lgcorzo" }]
readme = "README.md"
license = "MIT"
keywords = ["mlops", "python", "package"]
classifiers = [
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.12",
]
packages = [{ include = "regression_model_template", from = "src" }]
requires-python = ">=3.12,<3.13"
dependencies = [
"loguru (>=0.7.2,<0.8.0)",
"matplotlib (>=3.9.0,<4.0.0)",
"mlflow (>=3.11.1,<4.0.0)",
"numpy (>=1.26.4,<2.0.0)",
"omegaconf (>=2.3.0,<3.0.0)",
"pandas (>=2.2.2,<3.0.0)",
"pandera (>=0.20.1,<0.21.0)",
"plotly (>=5.22.0,<6.0.0)",
"plyer (>=2.1.0,<3.0.0)",
"psutil (>=6.0.0,<7.0.0)",
"pyarrow (>=17.0.0,<18.0.0)",
"pydantic (>=2.7.4,<3.0.0)",
"pydantic-settings (>=2.3.4,<3.0.0)",
"pynvml (>=11.5.0,<12.0.0)",
"setuptools (>=78.1.1,<79.0.0)",
"scikit-learn (>=1.5.0,<2.0.0)",
"shap (>=0.46.0,<0.47.0)",
"dvc (>=3.67.1,<4.0.0)",
"mlserver (>=1.7.1,<2.0.0)",
"mlserver-mlflow (>=1.7.1,<2.0.0)",
"opentelemetry-instrumentation (>=0.51b0,<0.52)",
"opentelemetry-exporter-otlp-proto-http (>=1.30.0,<2.0.0)",
"opentelemetry-exporter-otlp (>=1.30.0,<2.0.0)",
"confluent-kafka (>=2.8.2,<3.0.0)",
"fastapi (==0.124.0)",
"pyopenssl (>=26.0.0,<27.0.0)",
"diskcache (>=5.6.3,<6.0.0)",
"starlette (>=0.49.3,<0.50.0)",
]

[tool.poetry.scripts]
[project.scripts]
regression_model_template = "regression_model_template.scripts:main"

[tool.poetry.dependencies]
python = ">=3.12,<3.13"
loguru = "^0.7.2"
matplotlib = "^3.9.0"
mlflow = "^3.10.1"
numpy = "^1.26.4"
omegaconf = "^2.3.0"
pandas = "^2.2.2"
pandera = "^0.20.1"
plotly = "^5.22.0"
plyer = "^2.1.0"
psutil = "^6.0.0"
pyarrow = "^17.0.0"
pydantic = "^2.7.4"
pydantic-settings = "^2.3.4"
pynvml = "^11.5.0"
setuptools = "^78.1.1"
scikit-learn = "^1.5.0"
shap = "^0.46.0"
dvc = "^3.67.1"
mlserver = "^1.7.1"
mlserver-mlflow = "^1.7.1"
opentelemetry-instrumentation = "^0.51b0"
opentelemetry-exporter-otlp-proto-http = "^1.30.0"
opentelemetry-exporter-otlp = "^1.30.0"
confluent-kafka = "^2.8.2"
fastapi = "0.124.0"
pyopenssl = "^26.0.0"
diskcache = "^5.6.3"
starlette = "^0.49.1"
[tool.poetry]
packages = [{ include = "regression_model_template", from = "src" }]

[tool.poetry.group.checks.dependencies]
bandit = "^1.7.9"
Expand All @@ -56,7 +58,7 @@ pytest = "^9.0.3"
pytest-cov = "^5.0.0"
pytest-xdist = "^3.6.1"
pandera = { extras = ["mypy"], version = "^0.20.1" }
ruff = "^0.5.0"
ruff = "^0.9.0"
pytest-mock = "^3.14.0"
pytest-asyncio = "^1.3.0"

Expand All @@ -67,6 +69,7 @@ pre-commit = "^3.7.1"
[tool.poetry.group.dev.dependencies]
invoke = "^2.2.0"
pip-audit = "^2.10.0"
safety = "^3.7.0"

[tool.poetry.group.docs.dependencies]
pdoc = "^14.5.1"
Expand Down
33 changes: 0 additions & 33 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,9 @@ async-timeout==5.0.1 ; python_version == "3.12"
asyncssh==2.22.0 ; python_version == "3.12"
atpublic==7.0.0 ; python_version == "3.12"
attrs==26.1.0 ; python_version == "3.12"
bandit==1.9.4 ; python_version == "3.12"
billiard==4.2.4 ; python_version == "3.12"
blinker==1.9.0 ; python_version == "3.12"
boolean-py==5.0 ; python_version == "3.12"
brotli==1.2.0 ; python_version == "3.12"
cachecontrol[filecache]==0.14.4 ; python_version == "3.12"
cachetools==7.0.6 ; python_version == "3.12"
celery==5.6.3 ; python_version == "3.12"
certifi==2026.4.22 ; python_version == "3.12"
Expand All @@ -36,13 +33,9 @@ colorama==0.4.6 ; python_version == "3.12"
configobj==5.0.9 ; python_version == "3.12"
confluent-kafka==2.14.0 ; python_version == "3.12"
contourpy==1.3.3 ; python_version == "3.12"
coverage==7.13.5 ; python_version == "3.12"
coverage[toml]==7.13.5 ; python_version == "3.12"
cryptography==46.0.7 ; python_version == "3.12"
cycler==0.12.1 ; python_version == "3.12"
cyclonedx-python-lib==11.7.0 ; python_version == "3.12"
databricks-sdk==0.105.0 ; python_version == "3.12"
defusedxml==0.7.1 ; python_version == "3.12"
deprecated==1.3.1 ; python_version == "3.12"
dictdiffer==0.9.0 ; python_version == "3.12"
diskcache==5.6.3 ; python_version == "3.12"
Expand All @@ -58,7 +51,6 @@ dvc-studio-client==0.22.0 ; python_version == "3.12"
dvc-task==0.40.2 ; python_version == "3.12"
dvc==3.67.1 ; python_version == "3.12"
entrypoints==0.4 ; python_version == "3.12"
execnet==2.1.2 ; python_version == "3.12"
fastapi==0.124.0 ; python_version == "3.12"
filelock==3.29.0 ; python_version == "3.12"
flask-cors==6.0.2 ; python_version == "3.12"
Expand Down Expand Up @@ -91,16 +83,12 @@ hydra-core==1.3.2 ; python_version == "3.12"
idna==3.13 ; python_version == "3.12"
importlib-metadata==8.5.0 ; python_version == "3.12"
importlib-resources==6.5.2 ; python_version == "3.12"
iniconfig==2.3.0 ; python_version == "3.12"
invoke==2.2.1 ; python_version == "3.12"
iterative-telemetry==0.0.10 ; python_version == "3.12"
itsdangerous==2.2.0 ; python_version == "3.12"
jinja2==3.1.6 ; python_version == "3.12"
joblib==1.5.3 ; python_version == "3.12"
kiwisolver==1.5.0 ; python_version == "3.12"
kombu==5.6.2 ; python_version == "3.12"
librt==0.9.0 ; platform_python_implementation != "PyPy" and python_version == "3.12"
license-expression==30.4.4 ; python_version == "3.12"
llvmlite==0.47.0 ; python_version == "3.12"
loguru==0.7.3 ; python_version == "3.12"
mako==1.3.11 ; python_version == "3.12"
Expand All @@ -113,11 +101,9 @@ mlflow-tracing==3.11.1 ; python_version == "3.12"
mlflow==3.11.1 ; python_version == "3.12"
mlserver-mlflow==1.7.1 ; python_version == "3.12"
mlserver==1.7.2rc1 ; python_version == "3.12"
msgpack==1.1.2 ; python_version == "3.12"
multidict==6.7.1 ; python_version == "3.12"
multimethod==1.10 ; python_version == "3.12"
mypy-extensions==1.1.0 ; python_version == "3.12"
mypy==1.20.2 ; python_version == "3.12"
networkx==3.6.1 ; python_version == "3.12"
numba==0.65.1 ; python_version == "3.12"
numpy==1.26.4 ; python_version == "3.12"
Expand All @@ -136,21 +122,13 @@ opentelemetry-sdk==1.30.0 ; python_version == "3.12"
opentelemetry-semantic-conventions==0.51b0 ; python_version == "3.12"
opentelemetry-util-http==0.51b0 ; python_version == "3.12"
orjson==3.11.8 ; python_version == "3.12"
packageurl-python==0.17.6 ; python_version == "3.12"
packaging==26.2 ; python_version == "3.12"
pandas-stubs==3.0.0.260204 ; python_version == "3.12"
pandas==2.3.3 ; python_version == "3.12"
pandera==0.20.4 ; python_version == "3.12"
pandera[mypy]==0.20.4 ; python_version == "3.12"
pathspec==1.1.1 ; python_version == "3.12"
pillow==12.2.0 ; python_version == "3.12"
pip-api==0.0.34 ; python_version == "3.12"
pip-audit==2.10.0 ; python_version == "3.12"
pip-requirements-parser==32.0.1 ; python_version == "3.12"
pip==26.1 ; python_version == "3.12"
platformdirs==4.9.6 ; python_version == "3.12"
plotly==5.24.1 ; python_version == "3.12"
pluggy==1.6.0 ; python_version == "3.12"
plyer==2.1.0 ; python_version == "3.12"
prettytable==3.17.0 ; python_version == "3.12"
prometheus-client==0.25.0 ; python_version == "3.12"
Expand All @@ -159,7 +137,6 @@ propcache==0.4.1 ; python_version == "3.12"
protobuf==5.29.6 ; python_version == "3.12"
psutil==6.1.1 ; python_version == "3.12"
py-grpc-prometheus==0.8.0 ; python_version == "3.12"
py-serializable==2.1.0 ; python_version == "3.12"
pyarrow==17.0.0 ; python_version == "3.12"
pyasn1-modules==0.4.2 ; python_version == "3.12"
pyasn1==0.6.3 ; python_version == "3.12"
Expand All @@ -174,11 +151,6 @@ pygtrie==2.5.0 ; python_version == "3.12"
pynvml==11.5.3 ; python_version == "3.12"
pyopenssl==26.1.0 ; python_version == "3.12"
pyparsing==3.3.2 ; python_version == "3.12"
pytest-asyncio==1.3.0 ; python_version == "3.12"
pytest-cov==5.0.0 ; python_version == "3.12"
pytest-mock==3.15.1 ; python_version == "3.12"
pytest-xdist==3.8.0 ; python_version == "3.12"
pytest==9.0.3 ; python_version == "3.12"
python-dateutil==2.9.0.post0 ; python_version == "3.12"
python-dotenv==1.2.2 ; python_version == "3.12"
python-multipart==0.0.27 ; python_version == "3.12"
Expand All @@ -189,7 +161,6 @@ pyyaml==6.0.3 ; python_version == "3.12"
requests==2.33.1 ; python_version == "3.12"
rich==15.0.0 ; python_version == "3.12"
ruamel-yaml==0.19.1 ; python_version == "3.12"
ruff==0.5.7 ; python_version == "3.12"
scikit-learn==1.8.0 ; python_version == "3.12"
scipy==1.17.1 ; python_version == "3.12"
scmrepo==3.6.2 ; python_version == "3.12"
Expand All @@ -203,18 +174,14 @@ six==1.17.0 ; python_version == "3.12"
skops==0.14.0 ; python_version == "3.12"
slicer==0.0.8 ; python_version == "3.12"
smmap==5.0.3 ; python_version == "3.12"
sortedcontainers==2.4.0 ; python_version == "3.12"
sqlalchemy==2.0.49 ; python_version == "3.12"
sqlparse==0.5.5 ; python_version == "3.12"
sqltrie==0.11.2 ; python_version == "3.12"
starlette-exporter==0.23.0 ; python_version == "3.12"
starlette==0.49.3 ; python_version == "3.12"
stevedore==5.7.0 ; python_version == "3.12"
tabulate==0.10.0 ; python_version == "3.12"
tenacity==9.1.4 ; python_version == "3.12"
threadpoolctl==3.6.0 ; python_version == "3.12"
tomli-w==1.2.0 ; python_version == "3.12"
tomli==2.4.1 ; python_version == "3.12"
tomlkit==0.14.0 ; python_version == "3.12"
tqdm==4.67.3 ; python_version == "3.12"
tritonclient[http]==2.68.0 ; python_version == "3.12"
Expand Down
2 changes: 1 addition & 1 deletion src/regression_model_template/controller/kafka_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
)

# Security Middlewares
app.add_middleware(ProxyHeadersMiddleware, trusted_hosts=TRUSTED_PROXIES) # type: ignore[arg-type]
app.add_middleware(ProxyHeadersMiddleware, trusted_hosts=TRUSTED_PROXIES)

app.add_middleware(TrustedHostMiddleware, allowed_hosts=ALLOWED_HOSTS)

Expand Down
12 changes: 6 additions & 6 deletions tests/core/test_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ def test_sklearn_metric(
assert low <= scorer <= high, "Scorer should be in the expected interval!"
# - mlflow metric
assert mlflow_metric.name == metric.name, "Mlflow metric name should be the same!"
assert (
mlflow_metric.greater_is_better == metric.greater_is_better
), "Mlflow metric greater is better should be the same!"
assert mlflow_metric.greater_is_better == metric.greater_is_better, (
"Mlflow metric greater is better should be the same!"
)
# - mlflow results
assert mlflow_results.metrics == {
metric.name: score * (1 if greater_is_better else -1)
}, "Mlflow results metrics should have the same name and score!"
assert mlflow_results.metrics == {metric.name: score * (1 if greater_is_better else -1)}, (
"Mlflow results metrics should have the same name and score!"
)


# %% THRESHOLDS
Expand Down
24 changes: 12 additions & 12 deletions tests/core/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ def predict(self, inputs: schemas.Inputs) -> schemas.Outputs:
"a": 10,
"b": 20,
}, "Model should have the given params after set_params!"
assert isinstance(
explain_model_error.value, NotImplementedError
), "Model should raise NotImplementedError for explain_model_error()!"
assert isinstance(
explain_samples_error.value, NotImplementedError
), "Model should raise NotImplementedError for explain_samples_error()!"
assert isinstance(
get_internal_model_error.value, NotImplementedError
), "Model should raise NotImplementedError for get_internal_model_error()!"
assert isinstance(explain_model_error.value, NotImplementedError), (
"Model should raise NotImplementedError for explain_model_error()!"
)
assert isinstance(explain_samples_error.value, NotImplementedError), (
"Model should raise NotImplementedError for explain_samples_error()!"
)
assert isinstance(get_internal_model_error.value, NotImplementedError), (
"Model should raise NotImplementedError for get_internal_model_error()!"
)


def test_baseline_sklearn_model(
Expand Down Expand Up @@ -78,6 +78,6 @@ def test_baseline_sklearn_model(
assert len(shap_values.columns) >= len(inputs_test.columns), "SHAP values should have more features than inputs!"
# - feature importances
assert feature_importances["importance"].sum() == 1.0, "Feature importances should add up to 1.0!"
assert len(feature_importances["feature"]) >= len(
inputs_train.columns
), "Feature importances should have more features than inputs!"
assert len(feature_importances["feature"]) >= len(inputs_train.columns), (
"Feature importances should have more features than inputs!"
)
18 changes: 9 additions & 9 deletions tests/io/test_registries.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ def test_uri_for_model_alias_or_version() -> None:
version_uri = registries.uri_for_model_alias_or_version(name=name, alias_or_version=version)
# then
assert alias_uri == registries.uri_for_model_alias(name=name, alias=alias), "The alias URI should be valid!"
assert version_uri == registries.uri_for_model_version(
name=name, version=version
), "The version URI should be valid!"
assert version_uri == registries.uri_for_model_version(name=name, version=version), (
"The version URI should be valid!"
)


# %% SAVERS/LOADERS/REGISTERS
Expand Down Expand Up @@ -82,9 +82,9 @@ def test_custom_pipeline(
# - adapter
assert adapter.model.metadata.run_id == version.run_id, "The adapter model run id should be the same!"
assert adapter.model.metadata.signature == signature, "The adapter model signature should be the same!"
assert (
adapter.model.metadata.flavors.get("python_function") is not None
), "The adapter model should have a python_function flavor!"
assert adapter.model.metadata.flavors.get("python_function") is not None, (
"The adapter model should have a python_function flavor!"
)
# - output
# assert schemas.OutputsSchema.check(outputs) is not None, "Outputs should be valid!"

Expand Down Expand Up @@ -128,9 +128,9 @@ def test_builtin_pipeline(
# - adapter
assert adapter.model.metadata.run_id == version.run_id, "The adapter model run id should be the same!"
assert adapter.model.metadata.signature == signature, "The adapter model signature should be the same!"
assert (
adapter.model.metadata.flavors.get("python_function") is not None
), "The adapter model should have a python_function flavor!"
assert adapter.model.metadata.flavors.get("python_function") is not None, (
"The adapter model should have a python_function flavor!"
)
assert adapter.model.metadata.flavors.get(flavor), f"The model should have a built-in model flavor: {flavor}!"
# - output
assert schemas.OutputsSchema.check(outputs) is not None, "Outputs should be valid!"
6 changes: 3 additions & 3 deletions tests/io/test_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ def test_alerts_service(enable: bool, mocker: pm.MockerFixture, capsys: pc.Captu
plyer.notification.notify.assert_not_called(),
"Notification method should not be called!",
)
assert (
capsys.readouterr().out == "[regression_model_template] test: hello\n"
), "Notification should be printed to stdout!"
assert capsys.readouterr().out == "[regression_model_template] test: hello\n", (
"Notification should be printed to stdout!"
)


def test_mlflow_service(mlflow_service: services.MlflowService) -> None:
Expand Down
Loading
Loading