[project] name = "claude-howto" version = "1.0.0" description = "Claude Code How-To Guide with EPUB builder" readme = "README.md" license = "MIT" requires-python = ">=3.10" dependencies = [ "ebooklib", "markdown", "beautifulsoup4", "httpx", "pillow", "tenacity", ] [project.optional-dependencies] dev = [ "pytest>=7.0", "pytest-asyncio>=0.21", ] [tool.pytest.ini_options] testpaths = ["scripts/tests"] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function" python_files = ["test_*.py"] python_functions = ["test_*"] addopts = "-v" [build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [tool.setuptools.packages.find] where = ["scripts"] include = ["build_epub"] exclude = ["tests", "tests.*"] # ============================================================================= # Ruff Configuration # ============================================================================= [tool.ruff] target-version = "py310" line-length = 88 include = ["scripts/**/*.py"] exclude = [ ".git", ".venv", "__pycache__", ".pytest_cache", "*.egg-info", ] [tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # Pyflakes "I", # isort (import sorting) "B", # flake8-bugbear "C4", # flake8-comprehensions "UP", # pyupgrade "SIM", # flake8-simplify "TCH", # flake8-type-checking "RUF", # Ruff-specific rules "PTH", # flake8-use-pathlib "PL", # Pylint "PERF", # Perflint ] ignore = [ "E501", # Line too long (handled by formatter) "PLR0913", # Too many arguments "PLR2004", # Magic value comparison "PLR0915", # Too many statements "PERF203", # try-except in loop (acceptable for error handling) "PERF403", # dict comprehension (readability preference) "TC003", # Type-checking imports (not critical) "PLC0415", # Import not at top level (acceptable for lazy imports) "RUF005", # Collection concatenation (readability preference) ] fixable = ["ALL"] unfixable = [] [tool.ruff.lint.isort] known-first-party = ["build_epub"] force-single-line = false combine-as-imports = true [tool.ruff.lint.per-file-ignores] "scripts/tests/*.py" = ["S101", "PLR2004"] [tool.ruff.format] quote-style = "double" indent-style = "space" skip-magic-trailing-comma = false docstring-code-format = true # ============================================================================= # Bandit Configuration # ============================================================================= # ============================================================================= # Mypy Configuration # ============================================================================= [tool.mypy] python_version = "3.11" ignore_missing_imports = true no_implicit_optional = true warn_unused_ignores = true [[tool.mypy.overrides]] module = ["build_epub", "scripts.build_epub"] ignore_errors = true [[tool.mypy.overrides]] module = ["sync_translations", "scripts.sync_translations"] ignore_errors = true [tool.bandit] targets = ["scripts"] exclude_dirs = ["scripts/tests", ".venv", "__pycache__"] skips = ["B101", "B113"] # B113: httpx timeout false positive (timeout is set)