[build-system] requires = ["setuptools>=45", "wheel"] build-backend = "setuptools.build_meta" [project] name = "docuelevate" dynamic = ["version"] description = "Intelligent document processing system with AI-powered metadata extraction" readme = "README.md" requires-python = ">=3.11" license = {text = "Apache-2.0"} authors = [ {name = "Christian Louis", email = "christianlouis@users.noreply.github.com"} ] keywords = ["document", "processing", "ocr", "ai", "metadata", "extraction"] classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", ] [project.urls] Homepage = "https://github.com/christianlouis/DocuElevate" Documentation = "https://github.com/christianlouis/DocuElevate/tree/main/docs" Repository = "https://github.com/christianlouis/DocuElevate" Issues = "https://github.com/christianlouis/DocuElevate/issues" Changelog = "https://github.com/christianlouis/DocuElevate/blob/main/CHANGELOG.md" [tool.setuptools.dynamic] version = {file = "VERSION"} [tool.semantic_release] version_toml = [] version_source = "tag" commit_version_number = true tag_format = "v{version}" major_on_zero = false allow_zero_version = true build_command = """ chmod +x scripts/generate_build_metadata.sh ./scripts/generate_build_metadata.sh """ [tool.semantic_release.branches.main] match = "main" prerelease = false [tool.semantic_release.changelog] template_dir = "templates" exclude_commit_patterns = [ "^chore\\(release\\):", "^Merge", "^Bump version", ] [tool.semantic_release.changelog.default_templates] changelog_file = "CHANGELOG.md" [tool.semantic_release.changelog.environment] block_start_string = "{%" block_end_string = "%}" variable_start_string = "{{" variable_end_string = "}}" comment_start_string = "{#" comment_end_string = "#}" trim_blocks = false lstrip_blocks = false newline_sequence = "\n" keep_trailing_newline = false extensions = [] autoescape = true [tool.semantic_release.commit_parser_options] allowed_tags = [ "feat", "fix", "docs", "style", "refactor", "perf", "test", "build", "ci", "chore", ] minor_tags = ["feat"] patch_tags = ["fix", "perf"] default_bump_level = 0 [tool.semantic_release.remote] name = "origin" type = "github" ignore_token_for_push = false [tool.semantic_release.remote.token] env = "GH_TOKEN" [tool.semantic_release.publish] dist_glob_patterns = [] upload_to_vcs_release = true upload_to_pypi = false upload_to_repository = false # Black configuration [tool.black] line-length = 120 target-version = ['py311'] include = '\.pyi?$' extend-exclude = ''' /( # directories \.eggs | \.git | \.hg | \.mypy_cache | \.tox | \.venv | build | dist | migrations )/ ''' # isort configuration [tool.isort] profile = "black" line_length = 120 skip_gitignore = true known_first_party = ["app"] sections = ["FUTURE", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"] # pytest configuration [tool.pytest.ini_options] minversion = "7.0" testpaths = ["tests"] python_files = ["test_*.py"] python_classes = ["Test*"] python_functions = ["test_*"] addopts = [ "-v", "--strict-markers", "--strict-config", "--cov=app", "--cov-report=term-missing", "--cov-report=html", "--cov-branch", ] markers = [ "unit: Unit tests for individual functions/methods", "integration: Integration tests for API endpoints and workflows", "slow: Tests that take significant time to run", "security: Security-related tests", "requires_external: Tests requiring external services (OpenAI, Azure, etc.)", "requires_db: Tests requiring database", "requires_redis: Tests requiring Redis", "e2e: End-to-end tests with full infrastructure (requires Docker)", "requires_docker: Tests requiring Docker containers (testcontainers)", ] # mypy configuration [tool.mypy] python_version = "3.11" warn_return_any = true 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 warn_unreachable = false strict_equality = true ignore_missing_imports = true # Disable error codes that produce widespread false positives with SQLAlchemy ORM, # Pydantic, and other dynamic libraries used throughout the codebase. # These would require major refactoring to resolve and are tracked for future work. disable_error_code = [ "assignment", # SQLAlchemy Column[T] vs T assignments throughout ORM layer "arg-type", # SQLAlchemy Column types passed where plain types expected "union-attr", # Optional attribute access on ORM/Pydantic fields "call-overload", # SQLAlchemy query builder overload resolution "return-value", # Dynamic return types from ORM queries "attr-defined", # Dynamic attributes on ORM models and API clients "no-any-return", # Functions wrapping dynamic library calls "var-annotated", # Complex inferred types from ORM queries "index", # Indexing on dynamic ORM result types "operator", # Operator usage on Optional/Column types "dict-item", # Dict literal type inference with ORM fields "type-var", # Type variable constraints with ORM generics "method-assign", # Dynamic method assignment patterns "call-arg", # Dynamic call signatures in framework code ] # pylint configuration [tool.pylint.format] max-line-length = 120 [tool.pylint."messages control"] disable = [ "C0111", # missing-docstring (already documented functions use docstrings selectively) "C0103", # invalid-name (project uses domain-specific naming conventions) "C0114", # missing-module-docstring "C0115", # missing-class-docstring "C0116", # missing-function-docstring "C0415", # import-outside-toplevel (common pattern in FastAPI/Celery) "C0200", # consider-using-enumerate "C0201", # consider-iterating-dictionary "C0206", # consider-using-dict-items "C0207", # use-maxsplit-arg "C0123", # unidiomatic-typecheck "C0302", # too-many-lines "R0801", # duplicate-code (intentional patterns across storage providers) "R0401", # cyclic-import (FastAPI app structure with lazy imports) "R0903", # too-few-public-methods "R0911", # too-many-return-statements "R0912", # too-many-branches "R0913", # too-many-arguments "R0914", # too-many-locals "R0915", # too-many-statements "R0916", # too-many-boolean-expressions "R0917", # too-many-positional-arguments "R1702", # too-many-nested-blocks "R1705", # no-else-return "R1710", # inconsistent-return-statements "R1718", # consider-using-set-comprehension "R1720", # no-else-raise "R1723", # no-else-break "R1732", # consider-using-with "W0105", # pointless-string-statement "W0212", # protected-access "W0223", # abstract-method "W0404", # reimported "W0511", # fixme (TODO comments are acceptable) "W0603", # global-statement "W0611", # unused-import (managed by flake8/isort) "W0613", # unused-argument (common with framework callbacks) "W0621", # redefined-outer-name "W0641", # possibly-unused-variable "W0707", # raise-missing-from "W0718", # broad-exception-caught (intentional in error handlers) "W0719", # broad-exception-raised "W1203", # logging-fstring-interpolation (project uses f-strings consistently) "W1510", # subprocess-run-check "W1514", # unspecified-encoding "W0612", # unused-variable "E0213", # no-self-argument (Pydantic validators use cls) "E0611", # no-name-in-module (false positives with package imports) "E1101", # no-member (false positives with dynamic API clients) "E1102", # not-callable (false positives with SQLAlchemy func.now()) "E1133", # not-an-iterable (false positives with Pydantic fields) "E1135", # unsupported-membership-test (false positives with Pydantic fields) ] # Coverage configuration [tool.coverage.run] source = ["app"] omit = [ "*/tests/*", "*/migrations/*", "*/__pycache__/*", "*/venv/*", "*/env/*", ] [tool.coverage.report] precision = 2 show_missing = true skip_covered = false exclude_lines = [ "pragma: no cover", "def __repr__", "raise AssertionError", "raise NotImplementedError", "if __name__ == .__main__.:", "if TYPE_CHECKING:", "@abstractmethod", ]