pycmdcheck 0.1.0__py3-none-any.whl

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 (41) hide show
  1. pycmdcheck/__init__.py +104 -0
  2. pycmdcheck/__main__.py +6 -0
  3. pycmdcheck/ast_cache.py +45 -0
  4. pycmdcheck/checks/__init__.py +1 -0
  5. pycmdcheck/checks/base.py +143 -0
  6. pycmdcheck/checks/build.py +101 -0
  7. pycmdcheck/checks/changelog.py +101 -0
  8. pycmdcheck/checks/ci.py +87 -0
  9. pycmdcheck/checks/citation.py +102 -0
  10. pycmdcheck/checks/community.py +108 -0
  11. pycmdcheck/checks/dependencies.py +309 -0
  12. pycmdcheck/checks/docs.py +305 -0
  13. pycmdcheck/checks/doctests.py +129 -0
  14. pycmdcheck/checks/formatting.py +200 -0
  15. pycmdcheck/checks/imports.py +239 -0
  16. pycmdcheck/checks/license.py +304 -0
  17. pycmdcheck/checks/linting.py +304 -0
  18. pycmdcheck/checks/metadata.py +233 -0
  19. pycmdcheck/checks/py_typed.py +207 -0
  20. pycmdcheck/checks/python_versions.py +188 -0
  21. pycmdcheck/checks/structure.py +282 -0
  22. pycmdcheck/checks/tests.py +230 -0
  23. pycmdcheck/checks/typing.py +257 -0
  24. pycmdcheck/checks/urls.py +124 -0
  25. pycmdcheck/checks/version.py +184 -0
  26. pycmdcheck/cli.py +296 -0
  27. pycmdcheck/config.py +194 -0
  28. pycmdcheck/constants.py +29 -0
  29. pycmdcheck/discovery.py +127 -0
  30. pycmdcheck/package_layout.py +234 -0
  31. pycmdcheck/profiles.py +158 -0
  32. pycmdcheck/py.typed +0 -0
  33. pycmdcheck/pyproject_reader.py +226 -0
  34. pycmdcheck/results.py +320 -0
  35. pycmdcheck/runner.py +236 -0
  36. pycmdcheck/subprocess_runner.py +166 -0
  37. pycmdcheck-0.1.0.dist-info/METADATA +346 -0
  38. pycmdcheck-0.1.0.dist-info/RECORD +41 -0
  39. pycmdcheck-0.1.0.dist-info/WHEEL +4 -0
  40. pycmdcheck-0.1.0.dist-info/entry_points.txt +24 -0
  41. pycmdcheck-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,346 @@
1
+ Metadata-Version: 2.4
2
+ Name: pycmdcheck
3
+ Version: 0.1.0
4
+ Summary: Python package quality checker inspired by R CMD check
5
+ Project-URL: Homepage, https://github.com/pycmdcheck/pycmdcheck
6
+ Project-URL: Repository, https://github.com/pycmdcheck/pycmdcheck
7
+ Project-URL: Issues, https://github.com/pycmdcheck/pycmdcheck/issues
8
+ Author: pycmdcheck contributors
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: check,lint,package,quality,test
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Quality Assurance
20
+ Classifier: Topic :: Software Development :: Testing
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: click>=8.0
23
+ Requires-Dist: packaging>=21.0
24
+ Requires-Dist: rich>=13.0
25
+ Requires-Dist: tomli>=2.0; python_version < '3.11'
26
+ Provides-Extra: all
27
+ Requires-Dist: mypy>=1.0; extra == 'all'
28
+ Requires-Dist: pyright>=1.1; extra == 'all'
29
+ Requires-Dist: ruff>=0.1; extra == 'all'
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
32
+ Requires-Dist: pytest>=8.0; extra == 'dev'
33
+ Provides-Extra: docs
34
+ Requires-Dist: quartodoc>=0.7; extra == 'docs'
35
+ Provides-Extra: linting
36
+ Requires-Dist: ruff>=0.1; extra == 'linting'
37
+ Provides-Extra: typing-mypy
38
+ Requires-Dist: mypy>=1.0; extra == 'typing-mypy'
39
+ Provides-Extra: typing-pyright
40
+ Requires-Dist: pyright>=1.1; extra == 'typing-pyright'
41
+ Description-Content-Type: text/markdown
42
+
43
+ # pycmdcheck
44
+
45
+ A Python package quality checker inspired by R's `R CMD check`.
46
+
47
+ ## Installation
48
+
49
+ > **Note:** pycmdcheck is not yet published to PyPI. Install it directly from
50
+ > GitHub for now. Once it is released, `pip install pycmdcheck` will work too.
51
+
52
+ ```bash
53
+ pip install git+https://github.com/coatless-py-pkg/pycmdcheck
54
+ ```
55
+
56
+ Or with uv:
57
+
58
+ ```bash
59
+ uv pip install git+https://github.com/coatless-py-pkg/pycmdcheck
60
+ ```
61
+
62
+ To pin a specific branch, tag, or commit, append `@<ref>` to the URL — for
63
+ example `git+https://github.com/coatless-py-pkg/pycmdcheck@main`.
64
+
65
+ ### Optional dependencies
66
+
67
+ pycmdcheck can use external tools for linting and type checking. Request the
68
+ matching extra in the install command. For a GitHub install, the extra goes in
69
+ the PEP 508 `pycmdcheck[extra] @ <url>` form:
70
+
71
+ ```bash
72
+ # For mypy type checking
73
+ pip install "pycmdcheck[typing-mypy] @ git+https://github.com/coatless-py-pkg/pycmdcheck"
74
+
75
+ # For pyright type checking
76
+ pip install "pycmdcheck[typing-pyright] @ git+https://github.com/coatless-py-pkg/pycmdcheck"
77
+
78
+ # For ruff linting
79
+ pip install "pycmdcheck[linting] @ git+https://github.com/coatless-py-pkg/pycmdcheck"
80
+
81
+ # All optional dependencies
82
+ pip install "pycmdcheck[all] @ git+https://github.com/coatless-py-pkg/pycmdcheck"
83
+ ```
84
+
85
+ ## Usage
86
+
87
+ ### Command Line
88
+
89
+ ```bash
90
+ # Check current directory
91
+ pycmdcheck
92
+
93
+ # Check a specific directory
94
+ pycmdcheck /path/to/package
95
+
96
+ # Run only specific checks
97
+ pycmdcheck -c metadata -c tests
98
+
99
+ # Skip specific checks
100
+ pycmdcheck -s typing -s linting
101
+
102
+ # Fail on warnings too
103
+ pycmdcheck --fail-on error --fail-on warning
104
+
105
+ # List available checks
106
+ pycmdcheck --list
107
+
108
+ # JSON output
109
+ pycmdcheck --json
110
+
111
+ # Stop after first error (fail fast)
112
+ pycmdcheck -x
113
+ pycmdcheck --fail-fast
114
+
115
+ # Verbose output with details
116
+ pycmdcheck -v
117
+
118
+ # Use a check profile
119
+ pycmdcheck --profile pyopensci
120
+ pycmdcheck --profile minimal
121
+ pycmdcheck --profile strict
122
+
123
+ # List available profiles
124
+ pycmdcheck --list-profiles
125
+ ```
126
+
127
+ ### With uv
128
+
129
+ ```bash
130
+ uv run pycmdcheck
131
+ uv run pycmdcheck -c tests -c linting
132
+ ```
133
+
134
+ ### Python API
135
+
136
+ ```python
137
+ from pycmdcheck import check, CheckStatus
138
+
139
+ # Check current directory
140
+ report = check(".")
141
+
142
+ # Check specific directory
143
+ report = check("/path/to/package")
144
+
145
+ # Run only specific checks
146
+ report = check(".", checks=["metadata", "tests"])
147
+
148
+ # Skip specific checks
149
+ report = check(".", skip=["linting", "typing"])
150
+
151
+ # Check results
152
+ if report.passed:
153
+ print("All checks passed!")
154
+ else:
155
+ for result in report.results:
156
+ print(f"{result.status}: {result.name} - {result.message}")
157
+
158
+ # Get counts by status
159
+ counts = report.count_by_status()
160
+ print(f"OK: {counts[CheckStatus.OK]}, Errors: {counts[CheckStatus.ERROR]}")
161
+
162
+ # JSON output
163
+ import json
164
+ print(json.dumps(report.to_dict(), indent=2))
165
+ ```
166
+
167
+ ## Built-in Checks
168
+
169
+ ### Core checks
170
+
171
+ | Check | Description |
172
+ |-------|-------------|
173
+ | `build` | Verifies the package builds successfully (wheel/sdist) |
174
+ | `dependencies` | Audits declared vs. actual imports, warns on unbounded versions |
175
+ | `docs` | Checks for README (content sections, word count) and docstrings |
176
+ | `formatting` | Checks code formatting (ruff format/black) |
177
+ | `imports` | Validates all imports can be resolved |
178
+ | `license` | Checks for LICENSE file and OSI-approved license validation |
179
+ | `linting` | Runs ruff, flake8, or pylint |
180
+ | `metadata` | Validates pyproject.toml fields (required, recommended, extended) |
181
+ | `py_typed` | Checks for PEP 561 py.typed marker |
182
+ | `structure` | Checks package directory structure (src or flat layout) |
183
+ | `tests` | Runs pytest or unittest and reports results |
184
+ | `typing` | Runs mypy or pyright type checker |
185
+ | `version` | Verifies version consistency between pyproject.toml and code |
186
+
187
+ ### pyOpenSci / community checks
188
+
189
+ | Check | Description |
190
+ |-------|-------------|
191
+ | `changelog` | Checks for CHANGELOG, NEWS, or HISTORY file |
192
+ | `ci` | Checks for CI configuration (GitHub Actions, CircleCI, etc.) |
193
+ | `citation` | Checks for CITATION.cff or CITATION.bib file |
194
+ | `community` | Checks for CONTRIBUTING.md and CODE_OF_CONDUCT.md |
195
+ | `doctests` | Runs doctests via pytest --doctest-modules |
196
+ | `python_versions` | Checks requires-python excludes EOL Python versions |
197
+ | `urls` | Validates project URLs in metadata are reachable |
198
+
199
+ ## Profiles
200
+
201
+ Profiles bundle checks for common use cases:
202
+
203
+ | Profile | Description | Checks |
204
+ |---------|-------------|--------|
205
+ | `minimal` | Quick sanity checks | metadata, structure, license |
206
+ | `triage` | Static checks only — no install, external tools, or network (for CI triage of arbitrary repos) | All static checks (excludes tests, imports, dependencies, build, linting, typing, formatting, doctests, urls) |
207
+ | `default` | Standard quality checks | All 13 core checks |
208
+ | `pyopensci` | pyOpenSci onboarding | All 20 checks with stricter docs settings |
209
+ | `strict` | Maximum strictness | All 20 checks with strict typing |
210
+
211
+ ```bash
212
+ # Run pyOpenSci onboarding checks
213
+ pycmdcheck --profile pyopensci
214
+
215
+ # Static-only triage (safe to run on an un-installed repo in CI)
216
+ pycmdcheck --profile triage
217
+
218
+ # Quick check before committing
219
+ pycmdcheck --profile minimal
220
+ ```
221
+
222
+ Profiles can be combined with `--skip` to exclude specific checks:
223
+
224
+ ```bash
225
+ pycmdcheck --profile pyopensci -s urls -s doctests
226
+ ```
227
+
228
+ ## Configuration
229
+
230
+ Configure pycmdcheck in your `pyproject.toml`:
231
+
232
+ ```toml
233
+ [tool.pycmdcheck]
234
+ # Fail on these statuses (default: ["error"])
235
+ fail_on = ["error", "warning"]
236
+
237
+ [tool.pycmdcheck.checks]
238
+ # Enable/disable checks with boolean
239
+ metadata = true
240
+ structure = true
241
+ imports = true
242
+ license = true
243
+
244
+ # Configure checks with options
245
+ tests = { enabled = true, runner = "pytest" }
246
+ linting = { enabled = true, tool = "ruff" }
247
+ typing = { enabled = true, tool = "mypy", strict = false }
248
+ # formatting "tool" defaults to "auto": detects ruff vs black from
249
+ # [tool.ruff]/ruff.toml or [tool.black]; skips if neither is configured.
250
+ formatting = { enabled = true, tool = "auto" }
251
+ docs = { enabled = true, require_readme = true, check_docstrings = false, check_readme_sections = false }
252
+
253
+ # New checks (disabled by default in "default" profile)
254
+ community = true
255
+ ci = true
256
+ changelog = true
257
+ citation = true
258
+ python_versions = true
259
+ urls = { enabled = true, timeout = 10 }
260
+ doctests = true
261
+ ```
262
+
263
+ ### Linting tools
264
+
265
+ Supported linting tools:
266
+ - `ruff` (default, recommended)
267
+ - `flake8`
268
+ - `pylint`
269
+
270
+ ```toml
271
+ [tool.pycmdcheck.checks.linting]
272
+ tool = "ruff"
273
+ args = ["--select=E,F,W"]
274
+ ```
275
+
276
+ ### Build options
277
+
278
+ ```toml
279
+ [tool.pycmdcheck.checks.build]
280
+ timeout = 300 # seconds (default: 120)
281
+ args = ["--wheel"]
282
+ ```
283
+
284
+ ### Type checking tools
285
+
286
+ Supported type checkers:
287
+ - `mypy` (default)
288
+ - `pyright`
289
+
290
+ ```toml
291
+ [tool.pycmdcheck.checks.typing]
292
+ tool = "pyright"
293
+ strict = true
294
+ ```
295
+
296
+ ## Custom Checks
297
+
298
+ Create custom checks by implementing the `Check` protocol:
299
+
300
+ ```python
301
+ from pathlib import Path
302
+ from typing import Any
303
+ from pycmdcheck.checks.base import BaseCheck
304
+ from pycmdcheck.results import CheckResult, CheckStatus
305
+
306
+ class MyCustomCheck(BaseCheck):
307
+ name = "my_custom_check"
308
+ description = "My custom quality check"
309
+
310
+ def run(self, package_path: Path, config: dict[str, Any]) -> CheckResult:
311
+ # Your check logic here
312
+ issues = [] # ... populate with any issues found
313
+ if not issues:
314
+ return CheckResult(
315
+ name=self.name,
316
+ status=CheckStatus.OK,
317
+ message="All good!",
318
+ )
319
+ return CheckResult(
320
+ name=self.name,
321
+ status=CheckStatus.ERROR,
322
+ message="Something is wrong",
323
+ details=issues,
324
+ )
325
+ ```
326
+
327
+ Register your check via entry points in `pyproject.toml`:
328
+
329
+ ```toml
330
+ [project.entry-points."pycmdcheck.checks"]
331
+ my_custom_check = "my_package.checks:MyCustomCheck"
332
+ ```
333
+
334
+ ## Check Statuses
335
+
336
+ | Status | Symbol | Description |
337
+ |--------|--------|-------------|
338
+ | OK | ✓ | Check passed |
339
+ | NOTE | ℹ | Minor observation, not a problem |
340
+ | WARNING | ⚠ | Potential issue, should be reviewed |
341
+ | ERROR | ✗ | Check failed |
342
+ | SKIPPED | ○ | Check was skipped (e.g., tool not installed) |
343
+
344
+ ## License
345
+
346
+ MIT
@@ -0,0 +1,41 @@
1
+ pycmdcheck/__init__.py,sha256=GfesM3divwEOCvmtigML3PnKzmEV7VHsm7eS6F5hcMo,2954
2
+ pycmdcheck/__main__.py,sha256=iPl7C-a99WAWaNX-eBAC_39XVZ_j_N-PkEyG9r0OWZ0,116
3
+ pycmdcheck/ast_cache.py,sha256=W0pE-VE29086ZQ3-vzBdTVc-lLcu_LNP4hsl8YbedWI,1156
4
+ pycmdcheck/cli.py,sha256=SBOmg0xK3lptElIkFscgdC3oKB6t2veSctsCqfPpcjw,8148
5
+ pycmdcheck/config.py,sha256=3nRRV2fouo-TqbGDJmmkzaK5HUa-GaBT1vlGNwSVNUw,6166
6
+ pycmdcheck/constants.py,sha256=Y9v1KlK7I9k3ggow4A22qTXYbpQOs8AnPZqidmB_VD4,674
7
+ pycmdcheck/discovery.py,sha256=vtcxEO_NZrODNHAuy0ZyP7bnBA3xCO-iSqT93UrsQwI,3977
8
+ pycmdcheck/package_layout.py,sha256=JlpX2SzzqJN3ZtkIBREFrfoZAHWX67Uju9PjiyF8lSg,8129
9
+ pycmdcheck/profiles.py,sha256=kZBcYOvGoWYWzrI_qqPgIubTC4ANS_PHnFrvA-M6GgI,4337
10
+ pycmdcheck/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ pycmdcheck/pyproject_reader.py,sha256=bY4uQgzEABzC388tXVhnL3AJQCLGxj2R3gE642GmBvk,7649
12
+ pycmdcheck/results.py,sha256=m1gP3PRhJ7A_AAWlxtLZFBFdt7q1TyShOpWzV_A0HMw,9732
13
+ pycmdcheck/runner.py,sha256=u3okr3wiaPwuMvEiJOGgGkSZIFCNjVw9Uv7qX8y0h7U,7397
14
+ pycmdcheck/subprocess_runner.py,sha256=A5P8s12ZRAmWh-ptJDVJvgQXh6GRMrjmTla-MU-QzcI,5076
15
+ pycmdcheck/checks/__init__.py,sha256=DHT-oNFohsEa-fy8zf51PvRgKziqmInplAoalL0x_sk,38
16
+ pycmdcheck/checks/base.py,sha256=h6Tx5YS01CX28qEL5xPuscLdtnfITyxBXDSTT9YEV8I,4853
17
+ pycmdcheck/checks/build.py,sha256=4WBPejmgAIfp5ZQ46nPFgyTKCamfApcPxuv-7WGRLnA,3717
18
+ pycmdcheck/checks/changelog.py,sha256=Hrng6R3VqsMRvTGzXsbvVd8hYIeGOM5SQkE9g8Ds36M,3226
19
+ pycmdcheck/checks/ci.py,sha256=l8-rTUDKMcgGb5utjI1Sj0qc_UqGnYg45kqQU3vBKQ4,2906
20
+ pycmdcheck/checks/citation.py,sha256=1W3a_SzRD-xzycZCPq_mfXtgYQZx5NRl_hoH6F9oQhU,3232
21
+ pycmdcheck/checks/community.py,sha256=NV5M7RQqce-FnqHKq2xIisF3DbmuycKtyJFxzChRaq4,3412
22
+ pycmdcheck/checks/dependencies.py,sha256=iV6X8hy1z8tLf5w5EjfPqEgo26jv-1FuxZ3-2cz-fqA,11578
23
+ pycmdcheck/checks/docs.py,sha256=I_aGFKVOfdWeFtsChDS82kYBsdn1POn2I1EUvLrhWvo,11016
24
+ pycmdcheck/checks/doctests.py,sha256=AhFnFujuKBrgfJ4ur_jZque0SoTDeMDCvnjKgGtw-Gk,4282
25
+ pycmdcheck/checks/formatting.py,sha256=xrmr5SE6zqQK-Q0kqChE2rjf8m0ok4vlKZpfN14ihTM,7116
26
+ pycmdcheck/checks/imports.py,sha256=5I_ddDbtRiDZFWvHpKe9BFQWFe0vaXe85S2Osol7Qa0,8296
27
+ pycmdcheck/checks/license.py,sha256=m8T9sg17e1czgh5HWnbDEh3HnCGDpJsztUNicykL4f0,10746
28
+ pycmdcheck/checks/linting.py,sha256=V2Y6GY7LGgAf2ITjRTXW8ifEm6p5s8jAgUC5rLtJy60,10510
29
+ pycmdcheck/checks/metadata.py,sha256=hCZjUw21QjeijC3nUtlWyXX9xQrITx7sSeH7hIaAm1M,8920
30
+ pycmdcheck/checks/py_typed.py,sha256=I1tNZVUCkYNBXBnqeQos8KLRMGqTlPhlE9xxNAwaAlA,7370
31
+ pycmdcheck/checks/python_versions.py,sha256=tJJ-EM3VU3AwpdCFP3_RGy_zDOIdcGumYxLJT155TeA,7426
32
+ pycmdcheck/checks/structure.py,sha256=HaGnlUaSPW94ulQuMvfmt3l7LqoriVW7ZUMIoxZfjDc,9884
33
+ pycmdcheck/checks/tests.py,sha256=301WbzCyLt2uDF6B_J3KP9TFYckgZVX14EC8VnIBqP4,7726
34
+ pycmdcheck/checks/typing.py,sha256=NWJxQ6uQdVnNMl9x3IEcUxeAGJM7DJwk1zEUTtDo_z0,9127
35
+ pycmdcheck/checks/urls.py,sha256=kxBJDNP3-y3FF56J53xO7yWFO_cJxDhFv-xKw5PjcW4,4216
36
+ pycmdcheck/checks/version.py,sha256=3ds9Y17gnCQpTdRsRhagHn8lwZ8Fymx8sGndahZ5jMo,7123
37
+ pycmdcheck-0.1.0.dist-info/METADATA,sha256=Om3gWBYjSS4WqTwEc2_gSq7lkEYTj872jLiGigjUZA0,9685
38
+ pycmdcheck-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
39
+ pycmdcheck-0.1.0.dist-info/entry_points.txt,sha256=kXqVitvlcY4DXx8F4o4sX83gJUUiVpZW196UOq5WHkE,1080
40
+ pycmdcheck-0.1.0.dist-info/licenses/LICENSE,sha256=3-OoXjfqaCFy4LasY_7hVLS0qDX0-qGDzqS9mgijaBU,1080
41
+ pycmdcheck-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,24 @@
1
+ [console_scripts]
2
+ pycmdcheck = pycmdcheck.cli:main
3
+
4
+ [pycmdcheck.checks]
5
+ build = pycmdcheck.checks.build:BuildCheck
6
+ changelog = pycmdcheck.checks.changelog:ChangelogCheck
7
+ ci = pycmdcheck.checks.ci:CICheck
8
+ citation = pycmdcheck.checks.citation:CitationCheck
9
+ community = pycmdcheck.checks.community:CommunityCheck
10
+ dependencies = pycmdcheck.checks.dependencies:DependenciesCheck
11
+ docs = pycmdcheck.checks.docs:DocsCheck
12
+ doctests = pycmdcheck.checks.doctests:DoctestsCheck
13
+ formatting = pycmdcheck.checks.formatting:FormattingCheck
14
+ imports = pycmdcheck.checks.imports:ImportsCheck
15
+ license = pycmdcheck.checks.license:LicenseCheck
16
+ linting = pycmdcheck.checks.linting:LintingCheck
17
+ metadata = pycmdcheck.checks.metadata:MetadataCheck
18
+ py_typed = pycmdcheck.checks.py_typed:PyTypedCheck
19
+ python_versions = pycmdcheck.checks.python_versions:PythonVersionsCheck
20
+ structure = pycmdcheck.checks.structure:StructureCheck
21
+ tests = pycmdcheck.checks.tests:TestsCheck
22
+ typing = pycmdcheck.checks.typing:TypingCheck
23
+ urls = pycmdcheck.checks.urls:URLsCheck
24
+ version = pycmdcheck.checks.version:VersionCheck
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 pycmdcheck contributors
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.