lupaxa-github-token-validator 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. lupaxa_github_token_validator-0.1.0/LICENCE +21 -0
  2. lupaxa_github_token_validator-0.1.0/PKG-INFO +206 -0
  3. lupaxa_github_token_validator-0.1.0/README.md +159 -0
  4. lupaxa_github_token_validator-0.1.0/pyproject.toml +292 -0
  5. lupaxa_github_token_validator-0.1.0/setup.cfg +4 -0
  6. lupaxa_github_token_validator-0.1.0/src/lupaxa/github_token_validator/__init__.py +7 -0
  7. lupaxa_github_token_validator-0.1.0/src/lupaxa/github_token_validator/__main__.py +8 -0
  8. lupaxa_github_token_validator-0.1.0/src/lupaxa/github_token_validator/classify.py +52 -0
  9. lupaxa_github_token_validator-0.1.0/src/lupaxa/github_token_validator/cli.py +150 -0
  10. lupaxa_github_token_validator-0.1.0/src/lupaxa/github_token_validator/client.py +131 -0
  11. lupaxa_github_token_validator-0.1.0/src/lupaxa/github_token_validator/constants.py +37 -0
  12. lupaxa_github_token_validator-0.1.0/src/lupaxa/github_token_validator/probes.py +478 -0
  13. lupaxa_github_token_validator-0.1.0/src/lupaxa/github_token_validator/report.py +221 -0
  14. lupaxa_github_token_validator-0.1.0/src/lupaxa/github_token_validator/scopes.py +98 -0
  15. lupaxa_github_token_validator-0.1.0/src/lupaxa_github_token_validator.egg-info/PKG-INFO +206 -0
  16. lupaxa_github_token_validator-0.1.0/src/lupaxa_github_token_validator.egg-info/SOURCES.txt +26 -0
  17. lupaxa_github_token_validator-0.1.0/src/lupaxa_github_token_validator.egg-info/dependency_links.txt +1 -0
  18. lupaxa_github_token_validator-0.1.0/src/lupaxa_github_token_validator.egg-info/entry_points.txt +3 -0
  19. lupaxa_github_token_validator-0.1.0/src/lupaxa_github_token_validator.egg-info/requires.txt +17 -0
  20. lupaxa_github_token_validator-0.1.0/src/lupaxa_github_token_validator.egg-info/top_level.txt +1 -0
  21. lupaxa_github_token_validator-0.1.0/tests/test_catalog.py +93 -0
  22. lupaxa_github_token_validator-0.1.0/tests/test_classify.py +50 -0
  23. lupaxa_github_token_validator-0.1.0/tests/test_cli.py +280 -0
  24. lupaxa_github_token_validator-0.1.0/tests/test_client.py +153 -0
  25. lupaxa_github_token_validator-0.1.0/tests/test_report.py +172 -0
  26. lupaxa_github_token_validator-0.1.0/tests/test_runner.py +227 -0
  27. lupaxa_github_token_validator-0.1.0/tests/test_scopes.py +104 -0
  28. lupaxa_github_token_validator-0.1.0/tests/test_version.py +24 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) The Lupaxa Project
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,206 @@
1
+ Metadata-Version: 2.4
2
+ Name: lupaxa-github-token-validator
3
+ Version: 0.1.0
4
+ Summary: Report what a GitHub token is allowed to do.
5
+ Author: The Lupaxa Project
6
+ Maintainer: The Lupaxa Project
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/lupaxa-gh-toolbox/github-token-validator
9
+ Project-URL: Repository, https://github.com/lupaxa-gh-toolbox/github-token-validator
10
+ Project-URL: Issues, https://github.com/lupaxa-gh-toolbox/github-token-validator/issues
11
+ Keywords: github,permissions,token
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Natural Language :: English
16
+ Classifier: Operating System :: MacOS
17
+ Classifier: Operating System :: Microsoft :: Windows
18
+ Classifier: Operating System :: POSIX
19
+ Classifier: Operating System :: POSIX :: Linux
20
+ Classifier: Programming Language :: Python
21
+ Classifier: Programming Language :: Python :: 3
22
+ Classifier: Programming Language :: Python :: 3 :: Only
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Programming Language :: Python :: 3.13
26
+ Classifier: Programming Language :: Python :: 3.14
27
+ Classifier: Topic :: Software Development
28
+ Requires-Python: >=3.11
29
+ Description-Content-Type: text/markdown
30
+ License-File: LICENCE
31
+ Requires-Dist: colored<3.0.0,>=2.3.2
32
+ Requires-Dist: requests<3.0.0,>=2.32.0
33
+ Requires-Dist: rich<15.0.0,>=14.0.0
34
+ Provides-Extra: dev
35
+ Requires-Dist: build<2.0.0,>=1.2.2; extra == "dev"
36
+ Requires-Dist: mypy<2.0.0,>=1.17.0; extra == "dev"
37
+ Requires-Dist: pre-commit<5.0.0,>=4.2.0; extra == "dev"
38
+ Requires-Dist: pytest<9.0.0,>=8.4.0; extra == "dev"
39
+ Requires-Dist: pytest-cov<7.0.0,>=6.2.0; extra == "dev"
40
+ Requires-Dist: ruff<1.0.0,>=0.12.0; extra == "dev"
41
+ Requires-Dist: twine<7.0.0,>=6.1.0; extra == "dev"
42
+ Requires-Dist: types-setuptools<81.0.0,>=80.1.6; extra == "dev"
43
+ Provides-Extra: test
44
+ Requires-Dist: pytest>=8.0; extra == "test"
45
+ Requires-Dist: pytest-cov>=5.0; extra == "test"
46
+ Dynamic: license-file
47
+
48
+ <p align="center">
49
+ <a href="https://github.com/lupaxa-gh-toolbox">
50
+ <img src="https://raw.githubusercontent.com/the-lupaxa-project/brand-assets/master/logos/organisations/gh-toolbox/readme-logo.png" alt="Organisation Logo" />
51
+ </a>
52
+ </p>
53
+
54
+ <h1 align="center">GitHub Token Validator</h1>
55
+
56
+ **GitHub Token Validator** takes a GitHub token and reports what that token is allowed to do. It sends read-only `GET` requests. It does not list repositories, organisations, or other resources, and it never prints the token.
57
+
58
+ ## Installation
59
+
60
+ Requires Python 3.11 or newer.
61
+
62
+ ```bash
63
+ pip install lupaxa-github-token-validator
64
+ ```
65
+
66
+ Two commands are installed. They do the same work.
67
+
68
+ ```bash
69
+ gtv --version
70
+ github-token-validator --version
71
+ ```
72
+
73
+ The shorter `gtv` command is used in the examples below.
74
+
75
+ ## Token
76
+
77
+ `gtv` reads `GITHUB_TOKEN`. `--token` overrides that variable. A blank `--token` does not fall back to the environment. Surrounding whitespace is removed before the token is classified or sent.
78
+
79
+ ```bash
80
+ export GITHUB_TOKEN="your-token"
81
+ gtv
82
+ ```
83
+
84
+ ```bash
85
+ gtv --token "$OTHER_TOKEN"
86
+ ```
87
+
88
+ ## Which flags a token needs
89
+
90
+ Classic, OAuth, and user-to-server tokens return their scopes in the `X-OAuth-Scopes` header, so `--org` and `--repo` are optional.
91
+
92
+ Fine-grained, installation, and unknown tokens do not, so they need at least one of those flags before any request is sent.
93
+
94
+ A refresh token makes no request.
95
+
96
+ | Prefix | Kind | Needs a target |
97
+ | -------------- | ----------------------------------------- | -------------- |
98
+ | `ghp_` | Classic personal access token | No |
99
+ | `github_pat_` | Fine-grained personal access token | Yes |
100
+ | `gho_` | OAuth access token | No |
101
+ | `ghu_` | GitHub App user-to-server token | No |
102
+ | `ghs_` | GitHub App installation or Actions token | Yes |
103
+ | `ghr_` | Refresh token | No |
104
+ | anything else | Unknown | Yes |
105
+
106
+ Passing `--org` checks only that organisation. Passing `--repo` checks only that repository. Passing both checks both. The tool never looks up further targets.
107
+
108
+ `--org` is one name. Surrounding spaces are removed. A blank name, a space inside the name, or a `/` is rejected.
109
+
110
+ `--repo` is exactly `OWNER/NAME`: one slash, both sides non-empty, and no whitespace.
111
+
112
+ ## Examples
113
+
114
+ A classic, OAuth, or user-to-server token. The scope table is the permission report. Account checks still run.
115
+
116
+ ```bash
117
+ gtv
118
+ gtv --timeout 30
119
+ ```
120
+
121
+ The same token, plus one named target. Only the catalog you name is probed.
122
+
123
+ ```bash
124
+ gtv --org lupaxa-gh-toolbox
125
+ gtv --repo lupaxa-gh-toolbox/github-token-validator
126
+ gtv --org lupaxa-gh-toolbox --repo lupaxa-gh-toolbox/github-token-validator
127
+ ```
128
+
129
+ A fine-grained token, an installation or Actions token, or an unknown token. At least one target is required.
130
+
131
+ ```bash
132
+ gtv --repo lupaxa-gh-toolbox/github-token-validator
133
+ gtv --org lupaxa-gh-toolbox
134
+ ```
135
+
136
+ Omitting both flags exits 2 and prints a message such as `Fine-grained personal access token requires --org or --repo.` The token is not included in that message.
137
+
138
+ A refresh token (`ghr_`) prints a short summary and exits 2. It does not call the API.
139
+
140
+ ## Flags
141
+
142
+ | Flag | Meaning |
143
+ | ------------------- | ---------------------------------------------------------------------------------------------------- |
144
+ | `-h`, `--help` | Help, then exit 0 |
145
+ | `-V`, `--version` | Version, then exit 0 |
146
+ | `-t`, `--token` | Token. Overrides `GITHUB_TOKEN`. A blank value does not fall back to the environment |
147
+ | `-T`, `--timeout` | Seconds per request. Default 10. Must be an integer greater than 0 |
148
+ | `--org NAME` | One organisation. Required for fine-grained, installation, and unknown tokens unless `--repo` is set |
149
+ | `--repo OWNER/NAME` | One repository, as `OWNER/NAME`. Required for those same tokens unless `--org` is set |
150
+
151
+ ## Report
152
+
153
+ A completed run prints Rich tables.
154
+
155
+ **Summary.** Token kind, login from `GET /user`, the raw scope header, and the rate-limit limit, used count, remaining count, and reset time in UTC (`YYYY-MM-DD HH:MM:SS`).
156
+
157
+ **Scopes.** Classic, OAuth, and user-to-server tokens list each `X-OAuth-Scopes` value, in header order, with a short description. An unknown scope is `No local description.`
158
+
159
+ A missing or blank header is `none`, with the text `GitHub sent no scopes.`
160
+
161
+ Fine-grained tokens do not return OAuth scopes. That row says `Fine-grained tokens do not return OAuth scopes.`
162
+
163
+ Installation and Actions tokens list `X-Accepted-GitHub-Permissions` as a permission and its access, such as `read` or `write`. A missing header is `none`, with the text `GitHub sent no accepted permissions.`
164
+
165
+ **Account permissions.** Run for every API token except installation and Actions tokens, which are not user tokens:
166
+
167
+ - Profile, Emails, Following, Organisations, Org membership roles
168
+ - Gists, Notifications
169
+ - Public keys, GPG keys, SSH signing keys
170
+ - Packages, Repository list, Codespaces, Installations
171
+
172
+ **Target permissions.** Printed only when `--org` or `--repo` was passed.
173
+
174
+ Organisation checks: Organisation, Members, Hooks, Audit log, Actions permissions, Packages.
175
+
176
+ Repository checks: Repository, Contents, Hooks, Workflows, Deployments, Invitations, Code scanning, Commits.
177
+
178
+ List requests use `per_page=1`. Response bodies are discarded except the login on `GET /user`, so names, paths, messages, and other resource details are not printed.
179
+
180
+ | Result | Meaning |
181
+ | ----------------- | -------------------------------- |
182
+ | `granted` | HTTP 200 or 204 |
183
+ | `denied` | HTTP 403 |
184
+ | `not applicable` | HTTP 404 |
185
+ | `error N` | Any other HTTP status |
186
+
187
+ If GitHub rejects the token (HTTP 401), a rate limit stops the run, or a request times out or cannot connect, the run stops and exits 1.
188
+
189
+ A rate limit is HTTP 429, or HTTP 403 when `X-RateLimit-Remaining` is `0` or `Retry-After` is set. A 403 that is only a permission denial stays a `denied` row.
190
+
191
+ On the first request, only that error is printed. On a later request, the tables gathered so far are printed, then the error.
192
+
193
+ ## Exit codes
194
+
195
+ | Code | Meaning |
196
+ | ---- | -------------------------------------------------------------------------------------------------------------------- |
197
+ | 0 | The report completed, including rows that are denied, not applicable, or an HTTP error |
198
+ | 1 | The token was rejected, the rate limit stopped the run, or a request timed out or could not connect |
199
+ | 2 | Missing token, refresh token, missing target, invalid `--org`, `--repo`, or `--timeout`, or an unrecognized argument |
200
+ | 130 | Keyboard interrupt |
201
+
202
+ An unrecognized argument is rejected without printing the argument values.
203
+
204
+ <a href="https://github.com/the-lupaxa-project">
205
+ <img src="https://raw.githubusercontent.com/the-lupaxa-project/brand-assets/master/logos/components/footer-for-child-orgs.svg" alt="The Lupaxa Project Footer" width="100%" />
206
+ </a>
@@ -0,0 +1,159 @@
1
+ <p align="center">
2
+ <a href="https://github.com/lupaxa-gh-toolbox">
3
+ <img src="https://raw.githubusercontent.com/the-lupaxa-project/brand-assets/master/logos/organisations/gh-toolbox/readme-logo.png" alt="Organisation Logo" />
4
+ </a>
5
+ </p>
6
+
7
+ <h1 align="center">GitHub Token Validator</h1>
8
+
9
+ **GitHub Token Validator** takes a GitHub token and reports what that token is allowed to do. It sends read-only `GET` requests. It does not list repositories, organisations, or other resources, and it never prints the token.
10
+
11
+ ## Installation
12
+
13
+ Requires Python 3.11 or newer.
14
+
15
+ ```bash
16
+ pip install lupaxa-github-token-validator
17
+ ```
18
+
19
+ Two commands are installed. They do the same work.
20
+
21
+ ```bash
22
+ gtv --version
23
+ github-token-validator --version
24
+ ```
25
+
26
+ The shorter `gtv` command is used in the examples below.
27
+
28
+ ## Token
29
+
30
+ `gtv` reads `GITHUB_TOKEN`. `--token` overrides that variable. A blank `--token` does not fall back to the environment. Surrounding whitespace is removed before the token is classified or sent.
31
+
32
+ ```bash
33
+ export GITHUB_TOKEN="your-token"
34
+ gtv
35
+ ```
36
+
37
+ ```bash
38
+ gtv --token "$OTHER_TOKEN"
39
+ ```
40
+
41
+ ## Which flags a token needs
42
+
43
+ Classic, OAuth, and user-to-server tokens return their scopes in the `X-OAuth-Scopes` header, so `--org` and `--repo` are optional.
44
+
45
+ Fine-grained, installation, and unknown tokens do not, so they need at least one of those flags before any request is sent.
46
+
47
+ A refresh token makes no request.
48
+
49
+ | Prefix | Kind | Needs a target |
50
+ | -------------- | ----------------------------------------- | -------------- |
51
+ | `ghp_` | Classic personal access token | No |
52
+ | `github_pat_` | Fine-grained personal access token | Yes |
53
+ | `gho_` | OAuth access token | No |
54
+ | `ghu_` | GitHub App user-to-server token | No |
55
+ | `ghs_` | GitHub App installation or Actions token | Yes |
56
+ | `ghr_` | Refresh token | No |
57
+ | anything else | Unknown | Yes |
58
+
59
+ Passing `--org` checks only that organisation. Passing `--repo` checks only that repository. Passing both checks both. The tool never looks up further targets.
60
+
61
+ `--org` is one name. Surrounding spaces are removed. A blank name, a space inside the name, or a `/` is rejected.
62
+
63
+ `--repo` is exactly `OWNER/NAME`: one slash, both sides non-empty, and no whitespace.
64
+
65
+ ## Examples
66
+
67
+ A classic, OAuth, or user-to-server token. The scope table is the permission report. Account checks still run.
68
+
69
+ ```bash
70
+ gtv
71
+ gtv --timeout 30
72
+ ```
73
+
74
+ The same token, plus one named target. Only the catalog you name is probed.
75
+
76
+ ```bash
77
+ gtv --org lupaxa-gh-toolbox
78
+ gtv --repo lupaxa-gh-toolbox/github-token-validator
79
+ gtv --org lupaxa-gh-toolbox --repo lupaxa-gh-toolbox/github-token-validator
80
+ ```
81
+
82
+ A fine-grained token, an installation or Actions token, or an unknown token. At least one target is required.
83
+
84
+ ```bash
85
+ gtv --repo lupaxa-gh-toolbox/github-token-validator
86
+ gtv --org lupaxa-gh-toolbox
87
+ ```
88
+
89
+ Omitting both flags exits 2 and prints a message such as `Fine-grained personal access token requires --org or --repo.` The token is not included in that message.
90
+
91
+ A refresh token (`ghr_`) prints a short summary and exits 2. It does not call the API.
92
+
93
+ ## Flags
94
+
95
+ | Flag | Meaning |
96
+ | ------------------- | ---------------------------------------------------------------------------------------------------- |
97
+ | `-h`, `--help` | Help, then exit 0 |
98
+ | `-V`, `--version` | Version, then exit 0 |
99
+ | `-t`, `--token` | Token. Overrides `GITHUB_TOKEN`. A blank value does not fall back to the environment |
100
+ | `-T`, `--timeout` | Seconds per request. Default 10. Must be an integer greater than 0 |
101
+ | `--org NAME` | One organisation. Required for fine-grained, installation, and unknown tokens unless `--repo` is set |
102
+ | `--repo OWNER/NAME` | One repository, as `OWNER/NAME`. Required for those same tokens unless `--org` is set |
103
+
104
+ ## Report
105
+
106
+ A completed run prints Rich tables.
107
+
108
+ **Summary.** Token kind, login from `GET /user`, the raw scope header, and the rate-limit limit, used count, remaining count, and reset time in UTC (`YYYY-MM-DD HH:MM:SS`).
109
+
110
+ **Scopes.** Classic, OAuth, and user-to-server tokens list each `X-OAuth-Scopes` value, in header order, with a short description. An unknown scope is `No local description.`
111
+
112
+ A missing or blank header is `none`, with the text `GitHub sent no scopes.`
113
+
114
+ Fine-grained tokens do not return OAuth scopes. That row says `Fine-grained tokens do not return OAuth scopes.`
115
+
116
+ Installation and Actions tokens list `X-Accepted-GitHub-Permissions` as a permission and its access, such as `read` or `write`. A missing header is `none`, with the text `GitHub sent no accepted permissions.`
117
+
118
+ **Account permissions.** Run for every API token except installation and Actions tokens, which are not user tokens:
119
+
120
+ - Profile, Emails, Following, Organisations, Org membership roles
121
+ - Gists, Notifications
122
+ - Public keys, GPG keys, SSH signing keys
123
+ - Packages, Repository list, Codespaces, Installations
124
+
125
+ **Target permissions.** Printed only when `--org` or `--repo` was passed.
126
+
127
+ Organisation checks: Organisation, Members, Hooks, Audit log, Actions permissions, Packages.
128
+
129
+ Repository checks: Repository, Contents, Hooks, Workflows, Deployments, Invitations, Code scanning, Commits.
130
+
131
+ List requests use `per_page=1`. Response bodies are discarded except the login on `GET /user`, so names, paths, messages, and other resource details are not printed.
132
+
133
+ | Result | Meaning |
134
+ | ----------------- | -------------------------------- |
135
+ | `granted` | HTTP 200 or 204 |
136
+ | `denied` | HTTP 403 |
137
+ | `not applicable` | HTTP 404 |
138
+ | `error N` | Any other HTTP status |
139
+
140
+ If GitHub rejects the token (HTTP 401), a rate limit stops the run, or a request times out or cannot connect, the run stops and exits 1.
141
+
142
+ A rate limit is HTTP 429, or HTTP 403 when `X-RateLimit-Remaining` is `0` or `Retry-After` is set. A 403 that is only a permission denial stays a `denied` row.
143
+
144
+ On the first request, only that error is printed. On a later request, the tables gathered so far are printed, then the error.
145
+
146
+ ## Exit codes
147
+
148
+ | Code | Meaning |
149
+ | ---- | -------------------------------------------------------------------------------------------------------------------- |
150
+ | 0 | The report completed, including rows that are denied, not applicable, or an HTTP error |
151
+ | 1 | The token was rejected, the rate limit stopped the run, or a request timed out or could not connect |
152
+ | 2 | Missing token, refresh token, missing target, invalid `--org`, `--repo`, or `--timeout`, or an unrecognized argument |
153
+ | 130 | Keyboard interrupt |
154
+
155
+ An unrecognized argument is rejected without printing the argument values.
156
+
157
+ <a href="https://github.com/the-lupaxa-project">
158
+ <img src="https://raw.githubusercontent.com/the-lupaxa-project/brand-assets/master/logos/components/footer-for-child-orgs.svg" alt="The Lupaxa Project Footer" width="100%" />
159
+ </a>
@@ -0,0 +1,292 @@
1
+ [build-system]
2
+ requires = [
3
+ "setuptools>=77.0.0",
4
+ ]
5
+ build-backend = "setuptools.build_meta"
6
+
7
+ [project]
8
+ name = "lupaxa-github-token-validator"
9
+ version = "0.1.0"
10
+ description = "Report what a GitHub token is allowed to do."
11
+ readme = "README.md"
12
+ requires-python = ">=3.11"
13
+ license = "MIT"
14
+ license-files = [
15
+ "LICENCE",
16
+ ]
17
+
18
+ authors = [
19
+ { name = "The Lupaxa Project" },
20
+ ]
21
+
22
+ maintainers = [
23
+ { name = "The Lupaxa Project" },
24
+ ]
25
+
26
+ keywords = [
27
+ "github",
28
+ "permissions",
29
+ "token",
30
+ ]
31
+
32
+ classifiers = [
33
+ "Development Status :: 3 - Alpha",
34
+ "Environment :: Console",
35
+ "Intended Audience :: Developers",
36
+ "Natural Language :: English",
37
+ "Operating System :: MacOS",
38
+ "Operating System :: Microsoft :: Windows",
39
+ "Operating System :: POSIX",
40
+ "Operating System :: POSIX :: Linux",
41
+ "Programming Language :: Python",
42
+ "Programming Language :: Python :: 3",
43
+ "Programming Language :: Python :: 3 :: Only",
44
+ "Programming Language :: Python :: 3.11",
45
+ "Programming Language :: Python :: 3.12",
46
+ "Programming Language :: Python :: 3.13",
47
+ "Programming Language :: Python :: 3.14",
48
+ "Topic :: Software Development",
49
+ ]
50
+
51
+ dependencies = [
52
+ "colored>=2.3.2,<3.0.0",
53
+ "requests>=2.32.0,<3.0.0",
54
+ "rich>=14.0.0,<15.0.0",
55
+ ]
56
+
57
+ [project.optional-dependencies]
58
+ dev = [
59
+ "build>=1.2.2,<2.0.0",
60
+ "mypy>=1.17.0,<2.0.0",
61
+ "pre-commit>=4.2.0,<5.0.0",
62
+ "pytest>=8.4.0,<9.0.0",
63
+ "pytest-cov>=6.2.0,<7.0.0",
64
+ "ruff>=0.12.0,<1.0.0",
65
+ "twine>=6.1.0,<7.0.0",
66
+ "types-setuptools>=80.1.6,<81.0.0",
67
+ ]
68
+ test = [
69
+ "pytest>=8.0",
70
+ "pytest-cov>=5.0",
71
+ ]
72
+
73
+ [project.urls]
74
+ Homepage = "https://github.com/lupaxa-gh-toolbox/github-token-validator"
75
+ Repository = "https://github.com/lupaxa-gh-toolbox/github-token-validator"
76
+ Issues = "https://github.com/lupaxa-gh-toolbox/github-token-validator/issues"
77
+
78
+ [project.scripts]
79
+ github-token-validator = "lupaxa.github_token_validator.cli:main"
80
+ gtv = "lupaxa.github_token_validator.cli:main"
81
+
82
+ [tool.setuptools]
83
+ package-dir = { "" = "src" }
84
+
85
+ [tool.setuptools.packages.find]
86
+ where = [
87
+ "src",
88
+ ]
89
+ include = [
90
+ "lupaxa.github_token_validator*",
91
+ ]
92
+ namespaces = true
93
+
94
+ [tool.ruff]
95
+ target-version = "py311"
96
+ line-length = 88
97
+ src = [
98
+ "src",
99
+ "tests",
100
+ ]
101
+ extend-exclude = [
102
+ ".mypy_cache",
103
+ ".pytest_cache",
104
+ ".tox",
105
+ ".venv",
106
+ "build",
107
+ "dist",
108
+ ]
109
+
110
+ [tool.ruff.lint]
111
+ # Core Lupaxa rule set
112
+ select = [
113
+ # --- Essential correctness + hygiene ---
114
+ "E", # pycodestyle: basic style errors
115
+ "F", # pyflakes: unused vars, undefined names
116
+ "I", # import sorting
117
+ "B", # bugbear: common footguns
118
+
119
+ # --- Security layer ---
120
+ "S", # bandit-like security checks
121
+
122
+ # --- Modernisation + cleanup ---
123
+ "UP", # pyupgrade: modern Python idioms
124
+ "SIM", # simplify complex expressions/conditions
125
+ "C4", # flake8-comprehensions
126
+ "ISC", # implicit string-concat safety
127
+
128
+ # --- New additions (strict mode) ---
129
+ "D", # pydocstyle: docstring formatting/consistency
130
+ "ANN", # annotations: missing/incorrect typing hints
131
+ "PT", # pytest: best practices for tests
132
+ ]
133
+
134
+ # Disable rules that conflict with the Lupaxa documentation style
135
+ # or with Ruff's formatter.
136
+ ignore = [
137
+ "D200", # One-line docstring should fit on one line
138
+ "D201", # No blank lines allowed before function docstring
139
+ "D202", # No blank lines allowed after function docstring
140
+ "D203", # One blank line required before class docstring
141
+ "D204", # One blank line required after class docstring
142
+ "D205", # Blank line required between summary and description
143
+ "D206", # Docstring indentation
144
+ "D207", # Docstring under-indentation
145
+ "D208", # Docstring over-indentation
146
+ "D209", # Multi-line docstring closing quotes placement
147
+ "D210", # No surrounding whitespace allowed
148
+ "D211", # No blank line allowed before class docstring
149
+ "D212", # Summary must start on the first physical line
150
+ "ISC001", # Conflicts with Ruff formatting
151
+ ]
152
+
153
+ [tool.ruff.lint.per-file-ignores]
154
+ "tests/**/*.py" = [
155
+ "ANN",
156
+ "D",
157
+ "S101",
158
+ "S105",
159
+ ]
160
+
161
+ [tool.ruff.lint.flake8-annotations]
162
+ allow-star-arg-any = false
163
+ ignore-fully-untyped = false
164
+ mypy-init-return = true
165
+ suppress-dummy-args = false
166
+ suppress-none-returning = false
167
+
168
+ [tool.ruff.lint.flake8-builtins]
169
+ builtins-ignorelist = [
170
+ "id",
171
+ ]
172
+
173
+ [tool.ruff.lint.flake8-pytest-style]
174
+ fixture-parentheses = false
175
+ mark-parentheses = false
176
+ parametrize-names-type = "tuple"
177
+ parametrize-values-row-type = "tuple"
178
+ parametrize-values-type = "list"
179
+
180
+ [tool.ruff.lint.flake8-quotes]
181
+ docstring-quotes = "double"
182
+ inline-quotes = "double"
183
+ multiline-quotes = "double"
184
+
185
+ [tool.ruff.lint.flake8-tidy-imports]
186
+ ban-relative-imports = "parents"
187
+
188
+ [tool.ruff.lint.isort]
189
+ combine-as-imports = true
190
+ force-sort-within-sections = true
191
+ known-first-party = [
192
+ "lupaxa",
193
+ ]
194
+ split-on-trailing-comma = true
195
+
196
+ [tool.ruff.lint.mccabe]
197
+ max-complexity = 10
198
+
199
+ [tool.ruff.lint.pep8-naming]
200
+ classmethod-decorators = [
201
+ "classmethod",
202
+ ]
203
+ staticmethod-decorators = [
204
+ "staticmethod",
205
+ ]
206
+
207
+ [tool.ruff.lint.pylint]
208
+ allow-dunder-method-names = []
209
+ max-args = 10
210
+ max-branches = 12
211
+ max-returns = 6
212
+ max-statements = 50
213
+
214
+ [tool.ruff.lint.pyupgrade]
215
+ keep-runtime-typing = false
216
+
217
+ [tool.ruff.format]
218
+ docstring-code-format = true
219
+ docstring-code-line-length = 88
220
+ indent-style = "space"
221
+ line-ending = "lf"
222
+ quote-style = "double"
223
+ skip-magic-trailing-comma = false
224
+
225
+ [tool.mypy]
226
+ python_version = "3.11"
227
+ files = [ "src", "tests" ]
228
+ mypy_path = "src"
229
+ explicit_package_bases = true
230
+ packages = [ "lupaxa.github_token_validator" ]
231
+ strict = true
232
+ pretty = true
233
+ show_column_numbers = true
234
+ show_error_codes = true
235
+ show_error_context = true
236
+ show_traceback = true
237
+ warn_unreachable = true
238
+ warn_unused_configs = true
239
+ exclude = [ "^build/", "^dist/" ]
240
+
241
+ [[tool.mypy.overrides]]
242
+ module = "colored"
243
+ ignore_missing_imports = true
244
+
245
+ [tool.pytest.ini_options]
246
+ minversion = "8.0"
247
+ addopts = [
248
+ "--strict-config",
249
+ "--strict-markers",
250
+ "--showlocals",
251
+ "--tb=short",
252
+ ]
253
+ testpaths = [
254
+ "tests",
255
+ ]
256
+ pythonpath = [
257
+ "src",
258
+ ]
259
+ xfail_strict = true
260
+ filterwarnings = [
261
+ "error",
262
+ ]
263
+
264
+ [tool.coverage.run]
265
+ branch = true
266
+ parallel = true
267
+ source = [ "lupaxa.github_token_validator" ]
268
+
269
+ [tool.coverage.paths]
270
+ source = [
271
+ "src/lupaxa/github_token_validator",
272
+ "*/site-packages/lupaxa/github_token_validator",
273
+ ]
274
+
275
+ [tool.coverage.report]
276
+ exclude_also = [
277
+ "if TYPE_CHECKING:",
278
+ "if __name__ == \"__main__\":",
279
+ "raise AssertionError",
280
+ "raise NotImplementedError",
281
+ ]
282
+ fail_under = 90
283
+ precision = 2
284
+ show_missing = true
285
+ skip_covered = false
286
+ skip_empty = true
287
+
288
+ [tool.coverage.html]
289
+ directory = "coverage/html"
290
+
291
+ [tool.coverage.xml]
292
+ output = "coverage/coverage.xml"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,7 @@
1
+ """Report what a GitHub token is allowed to do."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from lupaxa.github_token_validator.cli import main
6
+
7
+ __all__ = ["main"]