[project]
name = "codeflash-workspace"
version = "0.1.0"
requires-python = ">=3.9"

[tool.uv.workspace]
members = ["packages/*", "reports/*"]

[dependency-groups]
dev = [
    "codeflash-api",
    "codeflash-core",
    "codeflash-python",
    "codeflash-service",
    "black>=25.1",
    "interrogate>=1.7.0",
    "memray>=1.19.2",
    "mypy>=1.14",
    "parameterized>=0.9.0",
    "pydantic>=2.12.5",
    "pytest>=7.4",
    "pytest-asyncio>=1.2.0",
    "respx>=0.22.0",
    "ruff>=0.15.7",
    "tomlkit>=0.14.0",
    "types-requests>=2.32.4.20260107",
    "pytest-cov>=7.1.0",
    "testcontainers[postgres]>=4.12",
    "vulture>=2.16",
]
test-optional = [
    "jax[cpu]>=0.5",
    "numba>=0.61",
    "numpy>=2.2",
    "pandas>=2.2",
    "pyarrow>=19.0",
    "pyrsistent>=0.20",
    "scipy>=1.15",
    "tensorflow>=2.19",
    "torch>=2.6",
    "xarray>=2025.3",
]

[tool.uv.sources]
codeflash-api = { workspace = true }
codeflash-core = { workspace = true }
codeflash-python = { workspace = true }
codeflash-service = { workspace = true }
attrs = { url = "https://github.com/KRRT7/attrs/releases/download/26.1.0.post1/attrs-26.1.0.post1-py3-none-any.whl" }

[tool.ty.environment]
python-version = "3.12"

[tool.ruff]
src = [
    "packages/codeflash-api/src",
    "packages/codeflash-core/src",
    "packages/codeflash-python/src",
    "packages/codeflash-python/tests",
    "packages/github-app",
]
extend-exclude = [
    "packages/codeflash-python/tests/code_to_optimize",
    "packages/codeflash-python/src/codeflash_python/ai/_tabulate.py",
]
line-length = 79
target-version = "py39"

[tool.ruff.lint]
select = ["ALL"]
ignore = [
    "A",        # shadowing is fine
    "ANN",      # Mypy is better at this
    "ARG",      # unused arguments are common w/ interfaces
    "COM",      # formatter takes care of that
    "D",        # we prefer our own docstring style
    "E501",     # line length handled by formatter
    "FIX",      # we don't want these
    "INP001",   # tests have no __init__.py
    "ISC001",   # conflicts with formatter
    "PD",       # not using pandas
    "RET504",   # unnecessary-assign is useful for readability
    "TD",       # we don't want these
    "TID252",   # relative imports are fine
]

[tool.ruff.lint.per-file-ignores]
"packages/codeflash-api/src/codeflash_api/_config.py" = [
    "S104",     # binding to 0.0.0.0 is the dev default, overridden in production
    "S105",     # dev placeholder secret_key, overridden via env var in production
]
"packages/codeflash-api/src/codeflash_api/languages/python/_cst_utils.py" = [
    "N802",     # libcst visitor methods must match visit_NodeName / leave_NodeName
    "PLR2004",  # magic values in faithfully ported ellipsis depth checks
]
"packages/codeflash-api/src/codeflash_api/languages/python/_postprocess.py" = [
    "BLE001",   # broad except is intentional — postprocessing must not crash the pipeline
    "C901",     # faithfully ported recursive annotation walker and comment cleaner
    "N802",     # libcst visitor methods must match visit_NodeName / leave_NodeName
    "PERF203",  # try/except in loop is intentional — each candidate processed independently
    "PLR0912",  # faithfully ported comment cleaning logic
    "PLR0915",  # faithfully ported comment cleaning logic
    "TRY300",   # faithfully ported control flow
]
"packages/codeflash-api/src/codeflash_api/diff/_v4a.py" = [
    "C901",     # peek_next_section and _parse_update_file_sections faithfully ported from Django
    "PLR0912",  # too many branches in faithfully ported _parse_update_file_sections
    "PLR0915",  # too many statements in faithfully ported _parse_update_file_sections
]
"packages/codeflash-api/src/codeflash_api/llm/_client.py" = [
    "PLC0415",  # conditional imports for event loop safety (clients recreated on loop change)
    "PLR0913",  # LLMClient.call needs many params for provider routing + observability
    "TRY301",   # raise inside try is the intended pattern for cost-tracking on unsupported model type
]
"packages/codeflash-api/src/codeflash_api/observability/_recording.py" = [
    "PLR0913",  # recording functions faithfully match Django signatures
]
"packages/codeflash-api/src/codeflash_api/testgen/_review_router.py" = [
    "PLR0913",  # _review_single_test needs all context params for prompt assembly
]
"packages/codeflash-api/src/codeflash_api/testgen/_generate.py" = [
    "PLR0913",  # generate_tests needs all params for pipeline orchestration
    "PLR2004",  # magic values in faithfully ported version parsing
]
"packages/codeflash-api/src/codeflash_api/testgen/_validate.py" = [
    "EM101",    # CodeValidationError needs descriptive inline messages
    "FURB110",  # ternary form clearer than `or` for AST line numbers
    "PLR0913",  # CodeValidationError.__init__ needs all debug context params
    "TRY003",   # long exception messages required for debug info
    "TRY300",   # faithfully ported preamble repair control flow
]
"packages/codeflash-api/src/codeflash_api/optimize/_context.py" = [
    "PLR2004",  # magic values in faithfully ported version parsing and humanize_ns
]
"packages/codeflash-api/src/codeflash_api/optimize/_pipeline.py" = [
    "PLR0913",  # faithfully ported signatures require many args for LLM call orchestration
]
"packages/codeflash-api/src/codeflash_api/_app.py" = [
    "PLC0415",  # local import for router registration avoids circular imports
]
"packages/codeflash-core/src/codeflash_core/_model.py" = [
    "C901",     # humanize_runtime is complex but faithfully ported
    "PLR2004",  # magic values in humanize_runtime thresholds
    "PLR0912",  # too many branches in humanize_runtime
]
"packages/codeflash-python/src/codeflash_python/_compat.py" = [
    "C901",     # humanize_runtime is complex but faithfully ported
    "PLR0911",  # too many return statements in faithfully ported modify_addopts
    "PLR0912",  # too many branches in humanize_runtime
    "PLR0915",  # too many statements in faithfully ported save_api_key_to_rc
    "PLR2004",  # magic values in humanize_runtime thresholds
    "TRY300",   # ported version_check control flow
]
"packages/codeflash-core/src/codeflash_core/_git.py" = [
    "PLR0911",  # too many return statements in faithfully ported check_and_push_branch
]
"packages/codeflash-core/src/codeflash_core/_shell.py" = [
    "C901",     # save_api_key_to_rc is complex but faithfully ported
    "PLR0912",  # too many branches in faithfully ported save_api_key_to_rc
]
"packages/codeflash-python/src/codeflash_python/pipeline/_config.py" = [
    "C901",     # parse_config_file is complex but faithfully ported
    "PLR0912",  # too many branches in faithfully ported parse_config_file
    "PLR2004",  # HTTP status code 200
    "TRY300",   # ported version_check control flow
]
"packages/codeflash-python/src/codeflash_python/testing/_pytest_config.py" = [
    "PLR0911",  # too many return statements in faithfully ported modify_addopts
]
"packages/codeflash-python/src/codeflash_python/analysis/_extraction.py" = [
    "C901",     # get_code has nested find_target closure
    "PLR0912",  # too many branches in faithfully ported get_code
    "PLR0915",  # too many statements in faithfully ported get_code
    "PLR2004",  # magic values in AST traversal (dunder name length, name_parts indices)
]
"packages/codeflash-python/src/codeflash_python/verification/_comparator.py" = [
    "BLE001",   # catching broad Exception is intentional in comparator
    "E501",     # long docstring line
]
"packages/codeflash-python/src/codeflash_python/analysis/_discovery.py" = [
    "N802",     # libcst visitor methods must match visit_NodeName
]
"packages/codeflash-core/src/codeflash_core/danom/safe.py" = [
    "BLE001",   # catching blind Exception is the point of @safe
]
"packages/codeflash-python/src/codeflash_python/testing/_instrumentation.py" = [
    "C901",     # faithfully ported complex methods
    "PLR0912",  # too many branches in ported methods
    "PLR0915",  # too many statements in find_and_update_line_node
]
"packages/codeflash-python/src/codeflash_python/testing/_instrument_core.py" = [
    "C901",     # detect_frameworks_from_code has many framework branches
]
"packages/codeflash-python/src/codeflash_python/testing/_instrument_capture.py" = [
    "C901",     # visit_ClassDef is complex but faithfully ported
    "ERA001",   # comments show equivalent Python for AST code below
    "PLR0912",  # too many branches in visit_ClassDef
    "PLR0913",  # add_codeflash_capture_to_init has 6 args
    "PLR2004",  # magic value in decorator part-count check
]
"packages/codeflash-python/src/codeflash_python/analysis/_discovery_worker.py" = [
    "BLE001",   # broad Exception catches are intentional in subprocess worker
    "I001",     # import sorting not applicable to standalone script
    "PLW0602",  # global statement without assignment (list.extend)
    "PLW0603",  # global statement is intentional for subprocess communication
    "T201",     # print is the logging mechanism for subprocess workers
]
"packages/codeflash-python/src/codeflash_python/benchmarking/_benchmark_tracing.py" = [
    "BLE001",   # broad Exception catches are intentional in tracing infrastructure
    "PLR2004",  # magic buffer-size thresholds ported from reference
    "T201",     # print is the error-reporting mechanism for tracing
]
"packages/codeflash-python/src/codeflash_python/benchmarking/_benchmark_plugin.py" = [
    "BLE001",   # broad Exception catches are intentional in plugin infrastructure
    "SLF001",   # _getframe access is required for line number capture
    "T201",     # print is the error-reporting mechanism for the plugin
]
"packages/codeflash-python/src/codeflash_python/analysis/_formatter.py" = [
    "FBT",      # ported signatures use boolean positional args
    "PLR0913",  # ported format_code signature has 6 args
    "PLR2004",  # magic numeric thresholds in formatting diff logic
]
"packages/codeflash-python/src/codeflash_python/benchmarking/_benchmarking.py" = [
    "C901",     # inspect_function_properties faithfully ported
    "N802",     # libcst visitor methods must match visit_NodeName
    "PLR0913",  # ported signatures require many args
    "PLR2004",  # magic numeric thresholds in formatting functions
]
"packages/codeflash-python/src/codeflash_python/benchmarking/_benchmark_worker.py" = [
    "BLE001",   # broad Exception catch is intentional in subprocess worker
    "I001",     # import sorting not applicable to standalone script
    "T201",     # print is the logging mechanism for subprocess workers
]
"packages/*/tests/*" = [
    "ASYNC251", # time.sleep in async tests (testing blocking behavior)
    "B007",     # unused loop variable in tests
    "B011",     # assert False is fine in tests
    "B018",     # useless expressions fine in test setup
    "BLE001",   # blind except fine in tests
    "C901",     # complex test functions are fine
    "DTZ001",   # datetime without tz fine in tests
    "E402",     # import not at top fine in tests
    "E501",     # test data strings often exceed line length
    "E712",     # comparison to True/False fine in tests
    "E741",     # ambiguous variable names fine in test data
    "EM101",    # string literal in exception fine in tests
    "ERA001",   # commented code fine in tests
    "F401",     # try/except import guards appear unused to ruff
    "F821",     # ExceptionGroup and other 3.11+ names
    "FA100",    # future annotations fine in tests
    "FBT",      # boolean params are fine in test helpers
    "F841",     # unused locals are fine in test setup
    "FURB177",  # Path.cwd vs Path() fine in tests
    "N802",     # non-lowercase function names fine in tests
    "N806",     # non-lowercase variable names fine in tests
    "N818",     # exception naming fine in tests
    "NPY002",   # legacy numpy random fine in tests
    "PERF401",  # list comprehension alternative fine in tests
    "PGH003",   # blanket type:ignore fine in tests
    "PLC0415",  # imports inside functions are fine in tests
    "PLR0915",  # too many statements fine in tests
    "PLR2004",  # magic values are fine in tests
    "PLW1641",  # missing __hash__ fine in tests
    "PT006",    # parametrize types fine in tests
    "PT009",    # unittest-style assertions fine in ported tests
    "PT014",    # duplicate parametrize fine in tests
    "PT015",    # assert in fixtures fine in tests
    "PT016",    # pytest.fail message fine in tests
    "PT017",    # assert in except fine in tests
    "PT018",    # compound assertions are fine in tests
    "PT019",    # fixture without return fine in tests
    "PTH109",   # Path.getcwd fine in tests
    "PTH123",   # open() fine in tests
    "PYI024",   # named tuple fine in tests
    "RUF005",   # tuple concat is fine in tests
    "RUF012",   # mutable class vars fine in tests
    "RUF013",   # implicit Optional fine in tests
    "RUF015",   # next() vs slice fine in tests
    "RUF032",   # decimal literal fine in tests
    "RUF043",   # pairwise fine in tests
    "RUF059",   # unused unpacked vars are fine in tests
    "S101",     # assert is fine in tests
    "S108",     # temp paths are fine in tests
    "S301",     # pickle fine in tests
    "S311",     # random fine in tests
    "SIM102",   # collapsible if fine in tests
    "SIM108",   # explicit if/else is fine in tests
    "SIM118",   # dict key check fine in tests
    "SIM300",   # Yoda style is fine in tests (expected == actual)
    "SLF001",   # private member access is fine in tests
    "T201",     # print is fine in tests
    "TC001",    # type-checking imports are fine in tests
    "TC002",    # type-checking imports are fine in tests
    "TC003",    # type-checking imports are fine in tests
    "TRY002",   # exception subclass fine in tests
    "TRY003",   # long exception message fine in tests
    "W",        # whitespace issues in test data strings
]

".codeflash/**" = [
    "B007",     # unused loop variable in benchmarks
    "B023",     # function binding loop variable in timeit lambdas
    "BLE001",   # broad Exception catches in scripts
    "C901",     # complex benchmark functions
    "E402",     # imports after sys.path manipulation
    "F841",     # unused locals in benchmark setup
    "PERF102",  # dict values iteration fine in scripts
    "PERF401",  # list comprehension not always clearer
    "PLC0415",  # imports in functions fine in scripts
    "PLR0912",  # many branches in benchmark harnesses
    "PLR0913",  # many args in benchmark functions
    "PLR0915",  # many statements in benchmark functions
    "PLR2004",  # magic values in benchmarks
    "PLW1510",  # subprocess.run without check
    "PTH110",   # os.path.exists in scripts
    "PTH111",   # os.path.expanduser in scripts
    "PT006",    # parametrize types fine in benchmarks
    "PTH123",   # open() in scripts
    "S101",     # assert in scripts
    "S108",     # temp paths in scripts
    "S307",     # eval used for benchmark code generation
    "S311",     # random in benchmarks
    "S324",     # hashlib in benchmarks
    "S603",     # subprocess calls in scripts
    "S607",     # partial executable path in scripts
    "SIM105",   # contextlib.suppress suggestion
    "SIM110",   # any() suggestion
    "SLF001",   # private member access in benchmarks
    "T201",     # print is the output mechanism
]
"scripts/*" = [
    "BLE001",   # broad Exception catches in scripts
    "C901",     # complex analysis functions
    "FA102",    # future annotations not needed in scripts
    "PERF102",  # dict keys iteration fine in scripts
    "PERF203",  # try-except in loop fine in scripts
    "PERF401",  # list comprehension not always clearer
    "PLC0415",  # imports in functions fine in scripts
    "PLR0911",  # many return statements in analysis
    "PLR0912",  # many branches in analysis scripts
    "PLR0913",  # many args in script functions
    "PLR0915",  # many statements in analysis scripts
    "PLR2004",  # magic values in scripts
    "PLW1510",  # subprocess.run without check
    "PTH111",   # os.path.expanduser in scripts
    "PTH117",   # os.path.isabs in scripts
    "PTH118",   # os.path.join in scripts
    "PTH123",   # open() in scripts
    "PTH208",   # os.listdir in scripts
    "S112",     # try-except-continue in scripts
    "S311",     # random in scripts
    "S324",     # hashlib in scripts
    "S603",     # subprocess calls in scripts
    "S607",     # partial executable path in scripts
    "SIM102",   # collapsible if fine in scripts
    "SIM105",   # contextlib.suppress suggestion
    "SIM110",   # any() suggestion
    "T201",     # print is the output mechanism
    "TC003",    # type-checking imports fine in scripts
    "TRY300",   # try-except-return fine in scripts
]
"evals/**" = [
    "B007",     # unused loop variable
    "C401",     # generator to set fine in evals
    "C901",     # complex test/eval functions
    "F841",     # unused locals fine in eval setup
    "FA102",    # future annotations not needed in evals
    "PERF102",  # dict values iteration fine in evals
    "PERF203",  # try-except in loop fine in evals
    "PERF401",  # list comprehension not always clearer
    "PLC0206",  # dict keys iteration fine in evals
    "PLC0415",  # imports in functions fine in evals
    "PLR0911",  # many return statements
    "PLR0912",  # many branches
    "PLR0913",  # many args in eval functions
    "PLR0915",  # many statements
    "PLR2004",  # magic values in eval scenarios
    "PLW1510",  # subprocess.run without check
    "PT006",    # parametrize types fine in evals
    "PTH123",   # open() fine in evals
    "RUF003",   # ambiguous unicode fine in test data
    "S101",     # assert in evals
    "S311",     # random fine in evals
    "S324",     # hashlib fine in evals
    "S603",     # subprocess calls in evals
    "S607",     # partial executable path in evals
    "SIM105",   # contextlib.suppress suggestion
    "SIM110",   # any() suggestion
    "SLF001",   # private member access in evals
    "T201",     # print in eval harnesses
]
"plugin/**" = [
    "B007",     # unused loop variable in reference scripts
    "PTH100",   # os.path.abspath in scripts
    "PTH110",   # os.path.exists in scripts
    "PTH123",   # open() in scripts
    "S108",     # temp paths in scripts
    "SLF001",   # private member access in plugin scripts
    "T201",     # print is the output mechanism
]
"reports/*" = [
    "C901",     # complex layout builders are expected in Dash apps
    "E501",     # long strings in inline HTML
    "ERA001",   # section separator comments
    "PERF403",  # dict comprehension not clearer here
    "PLR0913",  # helper functions with many style params
    "PLR0915",  # long layout functions are expected in Dash
    "PLR2004",  # magic values in layout (pixel sizes, etc.)
    "T201",     # print for dev server
]

[tool.isort]
known_first_party = ["codeflash_api", "codeflash_python", "codeflash_core"]

[tool.mypy]
strict = true
pretty = true
[[tool.mypy.overrides]]
module = "dill.*"
ignore_missing_imports = true
follow_imports = "skip"

[[tool.mypy.overrides]]
module = "codeflash_python.ai._tabulate"
ignore_errors = true

[[tool.mypy.overrides]]
module = "codeflash_python.benchmarking._profile_stats"
ignore_errors = true

[[tool.mypy.overrides]]
module = "codeflash_python.testing._instrumentation"
ignore_errors = true

[[tool.mypy.overrides]]
module = ["engagement_report", "theme"]
ignore_errors = true

[tool.pytest.ini_options]
asyncio_mode = "auto"
addopts = [
    "--strict-markers",
    "--strict-config",
    "--import-mode=importlib",
]
testpaths = [
    "packages/codeflash-api/tests",
    "packages/codeflash-core/tests",
    "packages/codeflash-python/tests",
    "packages/github-app/tests",
]
norecursedirs = [
    "code_to_optimize",
]
xfail_strict = true
markers = [
    "asyncio: mark a test as an asyncio test",
    "ci_skip: skip test in CI environments",
]

[tool.interrogate]
fail-under = 100
verbose = 2
exclude = [
    "packages/codeflash-python/src/codeflash_python/ai/_tabulate.py",
]
