content: # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  # SETUP CONFIGURATION.                                                        #
  [build-system]
  requires = [
      "setuptools>=61",
      "wheel",
  ]
  build-backend = "setuptools.build_meta"
  
  [project]
  name = "otx"
  dynamic = ["version"]
  description = "OpenVINO™ Training Extensions: Train, Evaluate, Optimize, Deploy Computer Vision Models via OpenVINO™"
  readme = "README.md"
  requires-python = ">=3.10"
  license = {file = "LICENSE"}
  authors = [
      { name = "OpenVINO™ Training Extensions Contributors" },
  ]
  classifiers = [
      "Development Status :: 5 - Production/Stable",
      "License :: OSI Approved :: Apache Software License",
      "Programming Language :: Cython",
      "Programming Language :: Python :: 3",
      "Programming Language :: Python :: 3.10",
      "Programming Language :: Python :: 3.11",
      "Programming Language :: Python :: 3.12",
  ]
  dependencies = [
      "datumaro==1.10.0",
      "omegaconf==2.3.0",
      "rich==14.0.0",
      "jsonargparse==4.35.0",
      "ftfy==6.3.1",
      "regex==2024.11.6",
      "importlib_resources==6.5.2",
      "docstring_parser==0.16", # CLI help-formatter
      "rich_argparse==1.7.0", # CLI help-formatter
      "einops==0.8.1",
      "decord==0.6.0",
      "typeguard>=4.3,<4.5",
      # TODO(ashwinvaidya17): https://github.com/openvinotoolkit/anomalib/issues/2126
      "setuptools<70",
      "lightning==2.4.0",
      "torchmetrics==1.6.0",
      "pytorchcv==0.0.67",
      "timm==1.0.3",
      "openvino==2025.2",
      "openvino-model-api==0.3.0.2",
      "onnx==1.17.0",
      "onnxconverter-common==1.14.0",
      "nncf==2.17.0",
      "anomalib[core]==1.1.3",
  ]
  
  [project.optional-dependencies]
  dev = [
      "uv",
      "tox-uv==1.26.0",
      "pre-commit==4.2.0",
      "pylint",
      "pytest",
      "coverage",
      "pytest-timeout",
      "pytest-mock",
      "pytest-csv",
      "pytest-cov",
      "onnxruntime==1.21.1",
  ]
  
  cuda = ["torch==2.8.0",
          "torchvision==0.23.0"
  ]
  xpu = [
      "torch==2.8.0+xpu",
      "pytorch-triton-xpu==3.4.0",
      "torchvision==0.23.0"
  ]
  
  docs = [
      "furo",
      "myst-parser",
      "sphinx==7.2.6",
      "pydata-sphinx-theme==0.12.0",
      "sphinx-tabs",
      "sphinx-panels",
      "sphinx-design",
      "sphinx-copybutton==0.5.2",
      "sphinx-autoapi",
      "sphinxemoji",
      "nbsphinx",
      "myst-parser>=2.0.0",
      "linkify-it-py",
  ]
  
  ci_publish = [
      "build==1.2.2.post1",
  ]
  
  ci_benchmark = [
      "pandas<2.4",       # To avoid conflict with nncf==2.9.0
      "matplotlib==3.10.1",
      "openpyxl==3.1.5",
      "mlflow==2.21.3",
      "py-cpuinfo==9.0.0",
  ]
  
  [project.scripts]
  otx = "otx.cli:main"
  
  [project.urls]
  Documentation = "https://open-edge-platform.github.io/training_extensions/"
  Repository = "https://github.com/open-edge-platform/training_extensions/"
  
  [tool.uv.sources]
  torch = [
      { index = "torch-xpu", extra = "xpu"},
      { index = "torch-cuda", extra = "cuda"},
  ]
  pytorch-triton-xpu = [
      { index = "torch-xpu", extra = "xpu"},
  ]
  torchvision = [
      { index = "torch-xpu", extra = "xpu"},
      { index = "torch-cuda", extra = "cuda"},
  ]
  
  [[tool.uv.index]]
  name = "torch-cuda"
  url = "https://download.pytorch.org/whl/cu128"
  explicit = true
  
  [[tool.uv.index]]
  name = "torch-xpu"
  url = "https://download.pytorch.org/whl/xpu"
  explicit = true
  
  
  [tool.setuptools.dynamic]
  version = {attr = "otx.__version__"}
  
  [tool.setuptools]
  include-package-data = true
  
  [tool.setuptools.packages.find]
  where = ["src"]
  include = ["otx*"]
  
  
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  # COVERAGE CONFIGURATION.                                                     #
  [tool.coverage.report]
  exclude_lines = [
      "pragma: no cover",
      "if TYPE_CHECKING:",
  ]
  
  [tool.coverage.run]
  source = [
      "src/otx/",
  ]
  omit = [
      "**/__init__.py",
      "src/otx/recipes/*",
      "src/otx/tools/*",
      "**/exportable_code/*",
      "src/otx/core/model/utils/*",
  
      # Ignore some generated files by opencv-python
      "config.py",
      "config-3.py",
  ]
  
  
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  # MYPY CONFIGURATION.                                                         #
  [tool.mypy]
  python_version = "3.12"
  ignore_missing_imports = true
  show_error_codes = true
  
  
  # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
  # RUFF CONFIGURATION                                                          #
  [tool.ruff]
  
  # Same as Black.
  line-length = 120
  
  # minimum target version
  target-version = "py38"
  
  # Enumerate all fixed violations.
  show-fixes = true
  
  # Allow imports relative to the "src" and "tests" directories.
  src = ["src", "tests"]
  
  [tool.ruff.lint]
  
  # Enable rules
  select = [
      "F",    # Pyflakes (`F`)
  
      # Enable all `pydocstyle` rules, limiting to those that adhere to the
      # Google convention via `convention = "google"`, below.
      "D",    # pydocstyle (`D`)
      "E",    # pycodestyle error (`E`)
      "W",    # pycodestyle warning (`W`)
  
      "I",    # isort (`I`)
      "PL",   # pylint (`PL`)
  
      "C90",  # mccabe (`C90`)
      "N",    # pep8-naming (`N`)
      "UP",   # pyupgrade (`UP`)
  
      "YTT",  # flake8-2020 (`YTT`)
      "ANN",  # flake8-annotations (`ANN`)
      "S",    # flake8-bandit (`S`)
      # "BLE",  # flake8-blind-except (`BLE`)  -> Need to discuss new exception structure
      "B",    # flake8-bugbear (`B`)
      "A",    # flake8-builtins (`A`)
      "COM",  # flake8-commas (`COM`)
      "C4",   # flake8-comprehensions (`C4`)
      "DTZ",  # flake8-datatimez (`DTZ`)
      "T10",  # flake8-debugger (`T10`)
      "EM",   # flake8-errmsg (`EM`)
      "FA",   # flake8-future-annotations (`FA`)
      "ISC",  # flake8-implicit-str-concat (`ISC`)
      "ICN",  # flake8-import-conventions (`ICN`)
      "PIE",  # flake8-pie (`PIE`)
      "PT",   # flake8-pytest-style (`PT`)
      "RSE",  # flake8-raise (`RSE`)
      "RET",  # flake8-return (`RET`)
      "SLF",  # flake8-self (`SLF`)
      "SIM",  # flake8-simplify (`SIM`)
      "TID",  # flake8-tidy-imports (`TID`)
      "TCH",  # flake8-type-checking (`TCH`)
      "INT",  # flake8-gettext (`INT`)
      "ARG",  # flake8-unsused-arguments (`ARG`)
      "PTH",  # flake8-use-pathlib (`PTH`)
      "TD",   # flake8-todos (`TD`)
      "FIX",  # flake8-fixme (`FIX`)
      # "LOG",  # flake8-logging (`LOG`) -> Rules included in the preview version of RUFF. It may be added in the future, but for now, disable it.
  
      "ERA",  # eradicate (`ERA`)
      "PD",   # pandas-vet (`PD`)
      "PGH",  # pygrep-hooks (`PGH`)
      "TRY",  # tryceratos (`TRY`)
      "FLY",  # flynt (`FLY`)
      "NPY",  # NumPy-specific rules (`NPY`)
      "PERF", # Perflint (`PERF`)
      # "FURB", # refurb (`FURB`) -> Rules included in the preview version of RUFF. It may be added in the future, but for now, disable it.
      "RUF",  # Ruff-specific rules (`RUF`)
  ]
  
  ignore = [
      # pydocstyle
      # On top of the Google convention, disable `D417`, which requires
      # documentation for every function parameter.
      "D417",     # Missing argument descriptions in the docstring
  
      "D107",     # Missing docstring in `__init__`
      "D105",     # Missing docstring in magic method
  
      # flake8-annotations
      "ANN101",   # Missing-type-self
      "ANN002",   # Missing type annotation for *args
      "ANN003",   # Missing type annotation for **kwargs
  
      "ANN102",   # Missing type annotation for `cls` in classmethod
      "ANN204",   # Missing return type annotation for special method `__init__`
  
      "ARG002",   # Unused method argument -> some function cannot use argument
  
      "COM812",   # Missing trailing comma -> conflicts with ISC001
  
      # flake8-type-checking
      "TCH001",   # typing-only-first-party-import, Sometimes this causes an incorrect error.
      # flake8-fixme
      "FIX002",   # line-contains-todo
  
      "E731",     # Do not assign a `lambda` expression, use a `def`
      "TD003",    # Missing issue link on the line following this TODO
  
      # TODO (someone): Update legacy np.random.{method_name} call with np.random.Generator
      # Legacy (MT19964) and new (PCG64) random generators use different pseudo-random number generators.
      # (https://numpy.org/doc/stable/reference/random/legacy.html#legacy)
      # For now, remaining legacy random methods is required until numpy version is explicitly updated in OTX.
      "NPY002",   # Replace legacy np.random.{method_name} call with np.random.Generator
  ]
  
  # Allow autofix for all enabled rules (when `--fix`) is provided.
  fixable = ["ALL"]
  # fixable = ["A", "B", "C", "D", "E", "F", "G", "I", "N", "Q", "S", "T", "W", "ANN", "ARG", "BLE", "COM", "DJ", "DTZ", "EM", "ERA", "EXE", "FBT", "ICN", "INP", "ISC", "NPY", "PD", "PGH", "PIE", "PL", "PT", "PTH", "PYI", "RET", "RSE", "RUF", "SIM", "SLF", "TCH", "TID", "TRY", "UP", "YTT"]
  # unfixable = [
  #     "F401",     # disable autofix for unused imports
  # ]
  
  # Exclude a variety of commonly ignored directories.
  exclude = [
      ".bzr",
      ".direnv",
      ".eggs",
      ".git",
      ".hg",
      ".mypy_cache",
      ".nox",
      ".pants.d",
      ".pytype",
      ".ruff_cache",
      ".svn",
      ".tox",
      ".venv",
      "__pypackages__",
      "_build",
      "buck-out",
      "build",
      "dist",
      "node_modules",
      "venv",
      "tests/assets",
  
      # it will be cleaned up later
      "for_developers/helpers.py",
  
      # Ruff complains it but don't know how to fix since it literally showed no useful logs.
      # https://github.com/openvinotoolkit/training_extensions/actions/runs/7176557723/job/19541622452?pr=2718#step:5:170
      "tests/regression/*.py",
  
      # Mostly borrowed from jsonargparse codebase
      "src/otx/core/utils/jsonargparse.py"
  ]
  
  # Allow unused variables when underscore-prefixed.
  dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
  
  [tool.ruff.lint.flake8-bugbear]
  # Allow default arguments like, e.g., `data: List[str] = fastapi.Query(None)`.
  extend-immutable-calls = [
      # Label info objects
      "otx.types.label.LabelInfo",
      "otx.types.label.HLabelInfo",
      "otx.types.label.SegLabelInfo",
      "otx.types.label.NullLabelInfo",
      "otx.types.label.AnomalyLabelInfo",
  
      # Config objects
      "otx.config.data.TileConfig",
  ]
  
  [tool.ruff.lint.mccabe]
  # Unlike Flake8, default to a complexity level of 10.
  max-complexity = 20
  
  [tool.ruff.lint.pylint]
  allow-magic-value-types = ["str", "bytes", "int", "float"]
  max-args = 20
  max-branches = 50
  max-statements = 150
  max-returns = 10
  
  [tool.ruff.lint.flake8-copyright]
  notice-rgx = """
  # Copyright \\(C\\) (\\d{4}(-\\d{4})?) Intel Corporation
  # SPDX-License-Identifier: Apache-2\\.0
  """
  
  [tool.ruff.lint.per-file-ignores]
  # Declare an additional exclude rule for test code
  "tests/**/*.py" = [
      "S101",     # pytest-style allows `assert` statements in tests.
      "SLF001",   # We sometimes need to inspect private functions for testing.
      "TCH003",   # It doesn't seem necessary to use TYPE_CHECKING in tests.
      "PT004",    # fixture ignore type returning.
      "E501",     # Test skips lines that are too long.
      "ANN001",   # Skip annotation type hint in test codes
      "ANN201",   # Skip return type hint in test codes
      "D",     # Test skips missing docstring argument with magic (fixture) methods.
      "ARG001",   # Some arguments are passed for executing fixture
  ]
  "src/otx/**/*.py" = [
      "ERA001",
  ]
  # See https://github.com/openvinotoolkit/training_extensions/actions/runs/7109500350/job/19354528819?pr=2700
  "src/otx/core/config/**/*.py" = [
      "UP007"
  ]
  
  [tool.ruff.lint.pydocstyle]
  convention = "google"
  
  [tool.pytest.ini_options]
  markers = [
      "gpu",  # mark tests which require NVIDIA GPU
      "cpu",
      "xpu",  # mark tests which require Intel dGPU,
  ]
  python_files = "tests/**/*.py"
  