[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "alpine-bits-python-server"
version = "0.1.2"
description = "Alpine Bits Python Server implementation"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
    "aiosqlite>=0.21.0",
    "annotatedyaml>=1.0.0",
    "dotenv>=0.9.9",
    "fastapi>=0.117.1",
    "generateds>=2.44.3",
    "httpx>=0.28.1",
    "lxml>=6.0.1",
    "pydantic[email]>=2.11.9",
    "pytest>=8.4.2",
    "pytest-asyncio>=1.2.0",
    "redis>=6.4.0",
    "ruff>=0.13.1",
    "slowapi>=0.1.9",
    "sqlalchemy>=2.0.43",
    "uvicorn>=0.37.0",
    "voluptuous>=0.15.2",
    "xsdata-pydantic[cli,lxml,soap]>=24.5",
    "xsdata[cli,lxml,soap]>=25.7",
]

[project.scripts]
alpine-bits-server = "alpine_bits_python.main:main"

[tool.hatch.build.targets.wheel]
packages = ["src/alpine_bits_python"]

[tool.pytest.ini_options]
testpaths = ["test"]
pythonpath = ["src"]

[tool.ruff]
src = ["src", "test"]

[tool.ruff.lint]
select = [
    "A001", # Variable {name} is shadowing a Python builtin
    "ASYNC210", # Async functions should not call blocking HTTP methods
    "ASYNC220", # Async functions should not create subprocesses with blocking methods
    "ASYNC221", # Async functions should not run processes with blocking methods
    "ASYNC222", # Async functions should not wait on processes with blocking methods
    "ASYNC230", # Async functions should not open files with blocking methods like open
    "ASYNC251", # Async functions should not call time.sleep
    "B002", # Python does not support the unary prefix increment
    "B005", # Using .strip() with multi-character strings is misleading
    "B007", # Loop control variable {name} not used within loop body
    "B014", # Exception handler with duplicate exception
    "B015", # Pointless comparison. Did you mean to assign a value? Otherwise, prepend assert or remove it.
    "B017", # pytest.raises(BaseException) should be considered evil
    "B018", # Found useless attribute access. Either assign it to a variable or remove it.
    "B023", # Function definition does not bind loop variable {name}
    "B024", # `{name}` is an abstract base class, but it has no abstract methods or properties
    "B026", # Star-arg unpacking after a keyword argument is strongly discouraged
    "B032", # Possible unintentional type annotation (using :). Did you mean to assign (using =)?
    "B035", # Dictionary comprehension uses static key
    "B904", # Use raise from to specify exception cause
    "B905", # zip() without an explicit strict= parameter
    "BLE",
    "C", # complexity
    "COM818", # Trailing comma on bare tuple prohibited
    "D", # docstrings
    "DTZ003", # Use datetime.now(tz=) instead of datetime.utcnow()
    "DTZ004", # Use datetime.fromtimestamp(ts, tz=) instead of datetime.utcfromtimestamp(ts)
    "E", # pycodestyle
    "F", # pyflakes/autoflake
    "F541", # f-string without any placeholders
    "FLY", # flynt
    "FURB", # refurb
    "G", # flake8-logging-format
    "I", # isort
    "INP", # flake8-no-pep420
    "ISC", # flake8-implicit-str-concat
    "ICN001", # import concentions; {name} should be imported as {asname}
    "LOG", # flake8-logging
    "N804", # First argument of a class method should be named cls
    "N805", # First argument of a method should be named self
    "N815", # Variable {name} in class scope should not be mixedCase
    "PERF", # Perflint
    "PGH", # pygrep-hooks
    "PIE", # flake8-pie
    "PL", # pylint
    "PT", # flake8-pytest-style
    "PTH", # flake8-pathlib
    "PYI", # flake8-pyi
    "RET", # flake8-return
    "RSE", # flake8-raise
    "RUF005", # Consider iterable unpacking instead of concatenation
    "RUF006", # Store a reference to the return value of asyncio.create_task
    "RUF007", # Prefer itertools.pairwise() over zip() when iterating over successive pairs
    "RUF008", # Do not use mutable default values for dataclass attributes
    "RUF010", # Use explicit conversion flag
    "RUF013", # PEP 484 prohibits implicit Optional
    "RUF016", # Slice in indexed access to type {value_type} uses type {index_type} instead of an integer
    "RUF017", # Avoid quadratic list summation
    "RUF018", # Avoid assignment expressions in assert statements
    "RUF019", # Unnecessary key check before dictionary access
    "RUF020", # {never_like} | T is equivalent to T
    "RUF021", # Parenthesize a and b expressions when chaining and and or together, to make the precedence clear
    "RUF022", # Sort __all__
    "RUF023", # Sort __slots__
    "RUF024", # Do not pass mutable objects as values to dict.fromkeys
    "RUF026", # default_factory is a positional-only argument to defaultdict
    "RUF030", # print() call in assert statement is likely unintentional
    "RUF032", # Decimal() called with float literal argument
    "RUF033", # __post_init__ method with argument defaults
    "RUF034", # Useless if-else condition
    "RUF100", # Unused `noqa` directive
    "RUF101", # noqa directives that use redirected rule codes
    "RUF200", # Failed to parse pyproject.toml: {message}
    "S102", # Use of exec detected
    "S103", # bad-file-permissions
    "S108", # hardcoded-temp-file
    "S306", # suspicious-mktemp-usage
    "S307", # suspicious-eval-usage
    "S313", # suspicious-xmlc-element-tree-usage
    "S314", # suspicious-xml-element-tree-usage
    "S315", # suspicious-xml-expat-reader-usage
    "S316", # suspicious-xml-expat-builder-usage
    "S317", # suspicious-xml-sax-usage
    "S318", # suspicious-xml-mini-dom-usage
    "S319", # suspicious-xml-pull-dom-usage
    "S601", # paramiko-call
    "S602", # subprocess-popen-with-shell-equals-true
    "S604", # call-with-shell-equals-true
    "S608", # hardcoded-sql-expression
    "S609", # unix-command-wildcard-injection
    "SIM", # flake8-simplify
    "SLF", # flake8-self
    "SLOT", # flake8-slots
    "T100", # Trace found: {name} used
    "T20", # flake8-print
    "TC", # flake8-type-checking
    "TID", # Tidy imports
    "TRY", # tryceratops
    "UP", # pyupgrade
    "UP031", # Use format specifiers instead of percent format
    "UP032", # Use f-string instead of `format` call
    "W", # pycodestyle
]

