[build-system] requires = ["setuptools>=83.0.0", "setuptools-scm>=8"] build-backend = "setuptools.build_meta" [project] name = "hate_crack" dynamic = ["version"] description = "Menu driven Python wrapper for hashcat" readme = "README.md" requires-python = ">=3.13" dependencies = [ "requests>=2.34.2", "beautifulsoup4>=4.15.0", "openpyxl>=3.0.0", "packaging>=26.2", "simple-term-menu==1.6.6", "click>=8.4.2", "atomic-agents>=2.0.0", # Imported directly by hate_crack/llm.py; declared explicitly rather than # relying on atomic-agents pulling them in transitively. "instructor>=1.14.5", "openai>=2.48.0", "pydantic>=2.13.4", ] [project.scripts] hate_crack = "hate_crack.__main__:main" [tool.setuptools.packages.find] include = ["hate_crack*"] [tool.setuptools.package-data] hate_crack = [ "config.json.example", ] [tool.setuptools_scm] version_scheme = "no-guess-dev" local_scheme = "no-local-version" [tool.ruff] exclude = [ "build", "dist", "PACK", "hashcat-utils", "omen", "princeprocessor", "wordlists", "rules", ] [tool.bandit] # hate_crack shells out to hashcat and its helper binaries extensively, so the # scan produces many low-severity subprocess/shlex findings. These are reviewed # and captured in .bandit-baseline.json; CI compares against that baseline so # only NEW findings fail the build (mirrors the hashview approach). Scan the # first-party package only — bundled third-party trees are excluded. exclude_dirs = [ "tests", ".venv", "build", "dist", "PACK", "hashcat-utils", "omen", "princeprocessor", ] [tool.ty.src] exclude = [ "build/", "dist/", "PACK/", "wordlists/", "HashcatRosetta/", "hashcat-utils/", "omen/", "princeprocessor/", ] [tool.ty.rules] # Module-level globals in main.py are assigned at runtime unresolved-reference = "warn" # Optional deps (hashcat_rosetta) not always installed unresolved-import = "warn" # BeautifulSoup union types and module-level globals unresolved-attribute = "warn" invalid-argument-type = "warn" # ty 0.0.63 tightened these to error for the same legacy pattern # (module-level `hcatHashFile = None` etc. in main.py, later used as # strings). Downgrade to warn to match the rest. unsupported-operator = "warn" no-matching-overload = "warn" invalid-assignment = "warn" unresolved-global = "warn" [tool.pytest.ini_options] testpaths = [ "tests", ] [dependency-groups] dev = [ "ty==0.0.63", "ruff==0.15.1", "pytest==9.0.3", "pytest-cov==7.1.0", "pytest-timeout>=2.4.0", ]