-
-
Notifications
You must be signed in to change notification settings - Fork 551
Expand file tree
/
Copy pathpyproject.toml
More file actions
216 lines (178 loc) Β· 8.53 KB
/
Copy pathpyproject.toml
File metadata and controls
216 lines (178 loc) Β· 8.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# Β©AngelaMos | 2026
# pyproject.toml
#
# This file is the "instruction manual" for our Python project. Every
# modern Python project has one. It tells tools like uv, pip, pytest,
# ruff, mypy, and pylint:
#
# - What our project is called
# - Which third-party libraries we depend on
# - How to build and install it
# - How to lint, type-check, and test it
#
# The file format is called TOML β a simple, human-readable config
# language. Square brackets like [project] start a "table" (a section).
# Lines like name = "..." are key-value pairs inside that table.
#
# Read this top-to-bottom. Each section has a short comment explaining
# what it does and why it is here.
# =============================================================================
# [project] β the metadata that describes WHAT this project is
# =============================================================================
# This section is standardized across the whole Python ecosystem (PEP 621).
# Anyone who runs `pip install` or `uv sync` reads from here.
[project]
# The name people will install this package under.
# Must be unique on PyPI if we ever publish there.
name = "hash-identifier"
# Semantic version: MAJOR.MINOR.PATCH.
# 1.0.0 means "first stable release."
# When we add features β bump MINOR (1.1.0). When we break things β MAJOR.
version = "1.0.0"
# One-line description that shows up in `pip show` and on PyPI.
description = "Identify hash types by prefix, length, and charset (foundations tier)"
# The minimum Python version this project supports.
# >=3.13 means "Python 3.13 or anything newer."
# We need 3.13 because we use modern type-hint syntax (X | None).
requires-python = ">=3.13"
# Who wrote it. Shows up in package metadata.
authors = [
{name = "CarterPerez-dev", email = "support@certgames.com"}
]
# The README file is shown on PyPI and in `pip show`.
readme = "README.md"
# AGPL-3.0 means: anyone can use it, but if they modify and run it as a
# service, they must publish their changes. It protects the project
# from being privatized.
license = {text = "AGPL-3.0-or-later"}
# -----------------------------------------------------------------------------
# dependencies β third-party libraries we MUST have at runtime
# -----------------------------------------------------------------------------
# When a user runs `pip install hash-identifier`, these get installed too.
# The string format is "<name><operator><version>". We use ranges so we
# get bug fixes (>=) but never an incompatible major version (<).
#
# Just one runtime dependency β the detection logic is pure stdlib.
dependencies = [
# rich: pretty terminal output β colors, tables, panels.
# Used to render the results of identification as a clean table.
"rich>=15.0.0",
]
# -----------------------------------------------------------------------------
# optional-dependencies β extra libraries that are NOT needed at runtime
# -----------------------------------------------------------------------------
# These only matter to developers (testing, linting, formatting). End users
# don't install them. Activated with: `uv sync --extra dev` or `--all-extras`.
[project.optional-dependencies]
dev = [
# pytest β runs our test suite (the test_*.py file in this directory).
"pytest>=9.0.3",
# ruff β extremely fast linter and formatter. Catches bugs, style
# issues, dead imports. Modern replacement for flake8/black/isort.
"ruff>=0.15.12",
# mypy β static type checker. Reads our type hints and tells us if
# we passed a string where an int was expected, BEFORE running the code.
"mypy>=2.1.0",
# pylint β second linter that catches deeper logic issues ruff misses.
"pylint>=4.0.5",
# yapf β code formatter. Keeps every file looking identical.
"yapf>=0.43.0,<1.0.0",
]
# -----------------------------------------------------------------------------
# project.scripts β command-line entry points
# -----------------------------------------------------------------------------
# After `uv sync`, the user can type `hashid <hash>` instead of
# `python hash_identifier.py <hash>`. The right-hand side is
# "<module>:<function>" β the function gets called when the command runs.
# Here it points to the `main` function inside hash_identifier.py.
[project.scripts]
hashid = "hash_identifier:main"
# =============================================================================
# [build-system] β how to BUILD this project into an installable package
# =============================================================================
# Required by PEP 517. Tools like uv read this to know which builder
# to use. We chose hatchling β modern, fast, zero-config for our case.
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
# Tell hatchling exactly which file to package. This project is a SINGLE
# Python file (no src/<package>/ layout), so we use `only-include` to
# point at it directly. Without this, hatchling would not know what
# to ship.
[tool.hatch.build.targets.wheel]
only-include = ["hash_identifier.py"]
# =============================================================================
# [tool.ruff] β linter / formatter configuration
# =============================================================================
# Ruff is the FAST one. It runs in milliseconds and catches 90% of issues.
[tool.ruff]
# Target Python version β ruff adjusts which warnings apply.
target-version = "py313"
# Wrap lines at 88 characters (PEP 8 says 79, but 88 is the modern norm).
line-length = 88
# -----------------------------------------------------------------------------
# Which lint rules to enable. Each "code" is a category of check.
# -----------------------------------------------------------------------------
[tool.ruff.lint]
select = [
"E", # pycodestyle errors β basic PEP 8 spacing/indent rules
"F", # Pyflakes β unused imports, undefined names, real bugs
"W", # pycodestyle warnings β softer style issues
"B", # Bugbear β sneaky bugs (mutable default args, etc.)
"C4", # Comprehensions β encourages cleaner list/dict comprehensions
"UP", # Pyupgrade β flags old syntax we should modernize
"SIM", # Simplify β suggests cleaner equivalents
]
# Some rules we deliberately ignore.
ignore = [
# Line length is handled by yapf, not ruff. Avoids double-flagging.
"E501",
]
# =============================================================================
# [tool.mypy] β static type checker configuration
# =============================================================================
# Mypy reads our type hints (the `: int`, `-> str` parts) and verifies them
# without running the code. Catches whole categories of bugs at edit time.
[tool.mypy]
python_version = "3.13"
# Require type annotations on every function β strict mode.
disallow_untyped_defs = true
disallow_incomplete_defs = true
# Don't auto-add Optional just because a default is None. Be explicit.
no_implicit_optional = true
# Warn if we cast a value to a type it already has (dead code).
warn_redundant_casts = true
# Warn if a function might fall off the end without returning.
warn_no_return = true
# Pretty error output β helps when reading mypy output.
show_error_codes = true
pretty = true
# =============================================================================
# [tool.pylint] β second-opinion linter
# =============================================================================
# Slower than ruff but catches different things β class design issues,
# dead variables, complex code patterns.
[tool.pylint.main]
# Match the project's Python version.
py-version = "3.13"
# Run lint checks in parallel across 4 cores for speed.
jobs = 4
# Specific pylint warnings we deliberately turn off.
[tool.pylint.messages_control]
disable = [
"R0903", # too-few-public-methods β small data classes are fine
"C0103", # invalid-name β short names like `s` for hash strings are clearer
]
# =============================================================================
# [tool.pytest.ini_options] β test runner configuration
# =============================================================================
[tool.pytest.ini_options]
# Where to look for tests. "." = the project root, since this project's
# test file lives next to the source file.
testpaths = ["."]
# Files that match this pattern are treated as test modules.
python_files = ["test_*.py"]
# Default flags every `pytest` invocation gets:
# -v β verbose, show each test name
# --tb=short β short tracebacks on failure (less wall of text)
addopts = "-v --tb=short"