[build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [project] name = "laborious" version = "0.0.0" description = "Sientia DataOps Laborious - ML Model Orchestration System" readme = "README.md" requires-python = ">=3.11" authors = [ {name = "Aignosi", email = "dev@aignosi.com"} ] [tool.ruff] line-length = 100 target-version = "py311" exclude = [ ".git", ".venv", "venv", "__pycache__", "*.pyc", ".pytest_cache", "htmlcov", "tests/laborious/workflows/subworkflows/test_prediction_process.py", ] [tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort "B", # flake8-bugbear "C4", # flake8-comprehensions "UP", # pyupgrade "N", # pep8-naming "YTT", # flake8-2020 "S", # flake8-bandit "BLE", # flake8-blind-except "A", # flake8-builtins "C90", # mccabe complexity ] ignore = [ "BLE001", # ignore blind except, we need to send notifications with any error "E501", # line too long (handled by formatter) "S101", # use of assert (needed for tests) "S105", # possible hardcoded password (false positives) "S106", # possible hardcoded password (false positives) "S608", # potential sql injection (false positives) "N802", # function name should be lowercase (temporal decorators) "N806", # variable in function should be lowercase ] [tool.ruff.lint.per-file-ignores] "tests/**/*.py" = [ "S101", # assert allowed in tests "S105", # hardcoded passwords ok in tests "S106", # hardcoded passwords ok in tests ] "e2e/conftest.py" = [ # Imports below the sientia/ModelAnalysis stub are load-order critical: the stub # must be in sys.modules before Activities is imported, so they cannot move up. "E402", ] [tool.ruff.lint.mccabe] max-complexity = 15 [tool.ruff.format] quote-style = "single" indent-style = "space" line-ending = "auto" [tool.mypy] python_version = "3.11" warn_return_any = false warn_unused_configs = true disallow_untyped_defs = false disallow_incomplete_defs = false check_untyped_defs = true no_implicit_optional = true warn_redundant_casts = true warn_unused_ignores = false warn_no_return = true strict_equality = true ignore_missing_imports = true # Ignore missing imports for external packages [[tool.mypy.overrides]] module = "temporalio.*" ignore_missing_imports = true [[tool.mypy.overrides]] module = "sientia_do.*" ignore_missing_imports = true [[tool.mypy.overrides]] module = "mlflow.*" ignore_missing_imports = true [[tool.mypy.overrides]] module = "prometheus_client.*" ignore_missing_imports = true [[tool.mypy.overrides]] module = "sientia.*" ignore_missing_imports = true [[tool.mypy.overrides]] module = "pandas.*" ignore_missing_imports = true [tool.pytest.ini_options] testpaths = ["tests"] python_files = ["test_*.py"] python_classes = ["Test*"] python_functions = ["test_*"] addopts = [ "-v", "--strict-markers", # pytest>=9.1 has a known bug where its unraisableexception plugin crashes # (tracemalloc partially-initialized AttributeError) when 2+ unraisable # exceptions land close together — e.g. "coroutine was never awaited" from # AsyncMock-mocked sync methods (metrics_controller, minio_repository) being # GC'd. Harmless mock artifacts turned into a hard ERROR by the plugin itself. "-p", "no:unraisableexception", ] markers = [ "asyncio: marks tests as async", "integration: marks tests as integration tests", "unit: marks tests as unit tests", "opc: marks tests that use the in-process OPC UA server (OpcRepository E2E)", ] [tool.coverage.run] source = ["laborious"] omit = [ "*/tests/*", "*/venv/*", "*/__pycache__/*", "*/site-packages/*", ] branch = true [tool.coverage.report] precision = 2 show_missing = true skip_covered = false exclude_lines = [ "pragma: no cover", "def __repr__", "def __str__", "raise AssertionError", "raise NotImplementedError", "if __name__ == .__main__.:", "if TYPE_CHECKING:", "class .*\\bProtocol\\):", "@(abc\\.)?abstractmethod", ] [tool.coverage.html] directory = "htmlcov" [tool.bandit] exclude_dirs = ["tests", "venv", ".venv"] skips = ["B101", "B601", "B608"] # Skip assert, shell injection, and SQL injection (false positives)