asciilint 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.
@@ -0,0 +1,56 @@
1
+ name: CI tests
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ branches:
9
+ - main
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ strategy:
15
+ matrix:
16
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
17
+ fail-fast: false
18
+
19
+ steps:
20
+ - uses: actions/checkout@v7
21
+ - name: Set up Python ${{ matrix.python-version }}
22
+ uses: actions/setup-python@v6
23
+ with:
24
+ python-version: ${{ matrix.python-version }}
25
+ - name: Install dependencies
26
+ run: |
27
+ # we are using the -e flag, so that code cov finds the source.
28
+ # this is not ideal, since installing an editable can technically
29
+ # differ from a normal install in surprising ways.
30
+ pip install -e '.[all]'
31
+ - name: Test with pytest
32
+ run: |
33
+ pip install pytest
34
+ pytest
35
+
36
+ # - name: Upload coverage reports to Codecov
37
+ # uses: codecov/codecov-action@v4
38
+ # with:
39
+ # name: "py${{ matrix.python-version }}"
40
+ # token: ${{ secrets.CODECOV_TOKEN }}
41
+
42
+ test-windows:
43
+ runs-on: windows-latest
44
+ steps:
45
+ - uses: actions/checkout@v7
46
+ - name: Set up Python
47
+ uses: actions/setup-python@v6
48
+ with:
49
+ python-version: "3.14"
50
+ - name: Install dependencies
51
+ run: |
52
+ pip install -e '.[all]'
53
+ - name: Test with pytest
54
+ run: |
55
+ pip install pytest
56
+ pytest
@@ -0,0 +1,31 @@
1
+ name: Documentation
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ permissions:
9
+ contents: read
10
+ pages: write
11
+ id-token: write
12
+
13
+ jobs:
14
+ deploy:
15
+ environment:
16
+ name: github-pages
17
+ url: ${{ steps.deployment.outputs.page_url }}
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: actions/configure-pages@v6
21
+ - uses: actions/checkout@v7
22
+ - uses: actions/setup-python@v6
23
+ with:
24
+ python-version: 3.x
25
+ - run: pip install zensical mkdocstrings-python
26
+ - run: zensical build --clean
27
+ - uses: actions/upload-pages-artifact@v5
28
+ with:
29
+ path: site
30
+ - uses: actions/deploy-pages@v5
31
+ id: deployment
@@ -0,0 +1,34 @@
1
+ name: Mypy check
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ branches:
9
+ - "**"
10
+
11
+ jobs:
12
+ mypy:
13
+ runs-on: ubuntu-latest
14
+
15
+ steps:
16
+ - name: Checkout repository
17
+ uses: actions/checkout@v7
18
+
19
+ - name: Set up Python
20
+ uses: actions/setup-python@v6
21
+ with:
22
+ python-version: "3.14"
23
+
24
+ - name: Install uv
25
+ run: |
26
+ pip install uv
27
+
28
+ - name: Install dependencies
29
+ run: |
30
+ uv sync --dev
31
+
32
+ - name: Run Type Checks
33
+ run: |
34
+ uv run mypy .
@@ -0,0 +1,25 @@
1
+ name: Ruff check
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ branches:
9
+ - "**"
10
+
11
+ jobs:
12
+ ruff-check:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v7
16
+ - name: Install Python
17
+ uses: actions/setup-python@v6
18
+ with:
19
+ python-version: "3.14"
20
+ - name: Install dependencies
21
+ run: |
22
+ python -m pip install --upgrade pip
23
+ pip install ruff
24
+ - name: Run Ruff
25
+ run: ruff check --output-format=github .
@@ -0,0 +1,16 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ # Zensical site
13
+ /site/
14
+
15
+ # Vendor files
16
+ /vendor/
@@ -0,0 +1 @@
1
+ 3.14.6
@@ -0,0 +1,22 @@
1
+ # Changelog
2
+
3
+ ## asciilint 0.1.0
4
+
5
+ ### New features
6
+
7
+ - Added the `asciilint` command-line interface for recursively scanning projects
8
+ for disallowed characters in UTF-8 text files.
9
+ - Added ASCII-only defaults to detect non-ASCII characters with no required
10
+ configuration.
11
+ - Added configurable character policies with arbitrary allowed and disallowed
12
+ literal characters and Unicode code point ranges.
13
+ - Added `asciilint.toml` support, parsed with `tomllib`, plus equivalent
14
+ command line options for CI usage.
15
+ - Added gitignore-syntax file filtering with `pathspec`, including
16
+ `.gitignore`, `.asciilintignore`, and user-specified ignore files.
17
+ - Added automatic binary file skipping using the zlib `txtvsbin` heuristic.
18
+ - Added explicit reporting for files that look like text but are not valid UTF-8.
19
+ - Added concise terminal output with file, line, column, code point, and
20
+ summary information suitable for local use and CI logs.
21
+ - Added project documentation and pytest coverage for CLI behavior,
22
+ policy parsing, ignore handling, binary detection, and UTF-8 errors.
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2026, asciilint authors
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,117 @@
1
+ Metadata-Version: 2.4
2
+ Name: asciilint
3
+ Version: 0.1.0
4
+ Summary: ASCII and character policy checks for text files
5
+ Project-URL: Homepage, https://nanx.me/asciilint/
6
+ Project-URL: Documentation, https://nanx.me/asciilint/
7
+ Project-URL: Repository, https://github.com/nanxstats/asciilint
8
+ Project-URL: Issues, https://github.com/nanxstats/asciilint/issues
9
+ Project-URL: Changelog, https://github.com/nanxstats/asciilint/blob/main/CHANGELOG.md
10
+ Author-email: Nan Xiao <me@nanx.me>
11
+ License-File: LICENSE
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Software Development :: Quality Assurance
22
+ Classifier: Topic :: Text Processing
23
+ Classifier: Topic :: Utilities
24
+ Requires-Python: >=3.11
25
+ Requires-Dist: click>=8.4.2
26
+ Requires-Dist: pathspec>=1.1.1
27
+ Description-Content-Type: text/markdown
28
+
29
+ # asciilint
30
+
31
+ [![PyPI version](https://img.shields.io/pypi/v/asciilint)](https://pypi.org/project/asciilint/)
32
+ ![Python versions](https://img.shields.io/pypi/pyversions/asciilint)
33
+ [![CI tests](https://github.com/nanxstats/asciilint/actions/workflows/ci-tests.yml/badge.svg)](https://github.com/nanxstats/asciilint/actions/workflows/ci-tests.yml)
34
+ [![Mypy check](https://github.com/nanxstats/asciilint/actions/workflows/mypy.yml/badge.svg)](https://github.com/nanxstats/asciilint/actions/workflows/mypy.yml)
35
+ [![Ruff check](https://github.com/nanxstats/asciilint/actions/workflows/ruff-check.yml/badge.svg)](https://github.com/nanxstats/asciilint/actions/workflows/ruff-check.yml)
36
+ [![Documentation](https://github.com/nanxstats/asciilint/actions/workflows/docs.yml/badge.svg)](https://nanx.me/asciilint/)
37
+ ![License](https://img.shields.io/pypi/l/asciilint)
38
+
39
+ Minimal, configurable, CI-friendly character policy checks for text files.
40
+
41
+ By default, `asciilint` recursively scans a project and fails when UTF-8
42
+ text files contain non-ASCII characters. It can also enforce arbitrary Unicode
43
+ allowlists and denylists, so it is useful for broader character policy checks.
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ pip install asciilint
49
+ ```
50
+
51
+ With `uv`:
52
+
53
+ ```bash
54
+ uv add asciilint
55
+ ```
56
+
57
+ ## Usage
58
+
59
+ ```bash
60
+ asciilint .
61
+ ```
62
+
63
+ Example failing output:
64
+
65
+ ```text
66
+ > Checking characters in /path/to/project
67
+ Files found: 3, 2 text, 0 binary skipped, 1 ignored
68
+ Checking text: ✓x
69
+
70
+ Issues :-(
71
+ > Disallowed characters
72
+ 1. docs/page.md
73
+ 1. [L012:C018] U+2014 "\u2014" not allowed by policy
74
+ Summary: 1 disallowed character(s), 0 read error(s)
75
+ ```
76
+
77
+ Exit code `0` means no issues. Exit code `1` means disallowed characters or
78
+ read errors were found.
79
+
80
+ ## Configuration
81
+
82
+ Create `asciilint.toml`:
83
+
84
+ ```toml
85
+ [asciilint]
86
+ paths = ["."]
87
+ respect_gitignore = true
88
+ ignore_files = [".asciilintignore"]
89
+ allowed_ranges = ["U+0000-U+007F"]
90
+ allowed_chars = []
91
+ disallowed_ranges = []
92
+ disallowed_chars = []
93
+ max_issues_per_file = 5
94
+ ```
95
+
96
+ Ignore files use gitignore syntax and are matched with `pathspec`.
97
+ `.gitignore` is respected by default.
98
+ You can add other ignore files, for example:
99
+
100
+ ```bash
101
+ asciilint . --ignore-file .asciilintignore --ignore-file config/lint.ignore
102
+ ```
103
+
104
+ Character ranges can be written as `U+0000-U+007F`, `0x20..0x7e`, `32-126`, or
105
+ single code points such as `U+00A9`. Deny rules take precedence over allow rules.
106
+
107
+ To allow any Unicode character except a small denylist:
108
+
109
+ ```bash
110
+ asciilint . --allow-any --disallowed-char "→" --disallowed-range U+2000-U+206F
111
+ ```
112
+
113
+ ## UTF-8 and binary files
114
+
115
+ `asciilint` assumes text files are UTF-8. Files that are classified as text but
116
+ cannot be decoded as UTF-8 are reported explicitly and skipped. Binary files are
117
+ skipped automatically using the zlib `txtvsbin` heuristic.
@@ -0,0 +1,89 @@
1
+ # asciilint
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/asciilint)](https://pypi.org/project/asciilint/)
4
+ ![Python versions](https://img.shields.io/pypi/pyversions/asciilint)
5
+ [![CI tests](https://github.com/nanxstats/asciilint/actions/workflows/ci-tests.yml/badge.svg)](https://github.com/nanxstats/asciilint/actions/workflows/ci-tests.yml)
6
+ [![Mypy check](https://github.com/nanxstats/asciilint/actions/workflows/mypy.yml/badge.svg)](https://github.com/nanxstats/asciilint/actions/workflows/mypy.yml)
7
+ [![Ruff check](https://github.com/nanxstats/asciilint/actions/workflows/ruff-check.yml/badge.svg)](https://github.com/nanxstats/asciilint/actions/workflows/ruff-check.yml)
8
+ [![Documentation](https://github.com/nanxstats/asciilint/actions/workflows/docs.yml/badge.svg)](https://nanx.me/asciilint/)
9
+ ![License](https://img.shields.io/pypi/l/asciilint)
10
+
11
+ Minimal, configurable, CI-friendly character policy checks for text files.
12
+
13
+ By default, `asciilint` recursively scans a project and fails when UTF-8
14
+ text files contain non-ASCII characters. It can also enforce arbitrary Unicode
15
+ allowlists and denylists, so it is useful for broader character policy checks.
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pip install asciilint
21
+ ```
22
+
23
+ With `uv`:
24
+
25
+ ```bash
26
+ uv add asciilint
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ```bash
32
+ asciilint .
33
+ ```
34
+
35
+ Example failing output:
36
+
37
+ ```text
38
+ > Checking characters in /path/to/project
39
+ Files found: 3, 2 text, 0 binary skipped, 1 ignored
40
+ Checking text: ✓x
41
+
42
+ Issues :-(
43
+ > Disallowed characters
44
+ 1. docs/page.md
45
+ 1. [L012:C018] U+2014 "\u2014" not allowed by policy
46
+ Summary: 1 disallowed character(s), 0 read error(s)
47
+ ```
48
+
49
+ Exit code `0` means no issues. Exit code `1` means disallowed characters or
50
+ read errors were found.
51
+
52
+ ## Configuration
53
+
54
+ Create `asciilint.toml`:
55
+
56
+ ```toml
57
+ [asciilint]
58
+ paths = ["."]
59
+ respect_gitignore = true
60
+ ignore_files = [".asciilintignore"]
61
+ allowed_ranges = ["U+0000-U+007F"]
62
+ allowed_chars = []
63
+ disallowed_ranges = []
64
+ disallowed_chars = []
65
+ max_issues_per_file = 5
66
+ ```
67
+
68
+ Ignore files use gitignore syntax and are matched with `pathspec`.
69
+ `.gitignore` is respected by default.
70
+ You can add other ignore files, for example:
71
+
72
+ ```bash
73
+ asciilint . --ignore-file .asciilintignore --ignore-file config/lint.ignore
74
+ ```
75
+
76
+ Character ranges can be written as `U+0000-U+007F`, `0x20..0x7e`, `32-126`, or
77
+ single code points such as `U+00A9`. Deny rules take precedence over allow rules.
78
+
79
+ To allow any Unicode character except a small denylist:
80
+
81
+ ```bash
82
+ asciilint . --allow-any --disallowed-char "→" --disallowed-range U+2000-U+206F
83
+ ```
84
+
85
+ ## UTF-8 and binary files
86
+
87
+ `asciilint` assumes text files are UTF-8. Files that are classified as text but
88
+ cannot be decoded as UTF-8 are reported explicitly and skipped. Binary files are
89
+ skipped automatically using the zlib `txtvsbin` heuristic.
@@ -0,0 +1,88 @@
1
+ [project]
2
+ name = "asciilint"
3
+ version = "0.1.0"
4
+ description = "ASCII and character policy checks for text files"
5
+ authors = [{ name = "Nan Xiao", email = "me@nanx.me" }]
6
+ readme = "README.md"
7
+ dependencies = ["click>=8.4.2", "pathspec>=1.1.1"]
8
+
9
+ classifiers = [
10
+ "Development Status :: 3 - Alpha",
11
+
12
+ "Intended Audience :: Developers",
13
+
14
+ "Topic :: Software Development :: Quality Assurance",
15
+ "Topic :: Text Processing",
16
+ "Topic :: Utilities",
17
+
18
+ "Operating System :: OS Independent",
19
+
20
+ "License :: OSI Approved :: MIT License",
21
+
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "Programming Language :: Python :: 3.14",
27
+ ]
28
+
29
+ requires-python = ">=3.11"
30
+
31
+ [project.scripts]
32
+ asciilint = "asciilint.cli:main"
33
+
34
+ [project.urls]
35
+ Homepage = "https://nanx.me/asciilint/"
36
+ Documentation = "https://nanx.me/asciilint/"
37
+ Repository = "https://github.com/nanxstats/asciilint"
38
+ Issues = "https://github.com/nanxstats/asciilint/issues"
39
+ Changelog = "https://github.com/nanxstats/asciilint/blob/main/CHANGELOG.md"
40
+
41
+ [build-system]
42
+ requires = ["hatchling"]
43
+ build-backend = "hatchling.build"
44
+
45
+ [tool.hatch.build.targets.sdist]
46
+ exclude = ["/docs", "/scripts", "/AGENTS.md", "/uv.lock", "/zensical.toml"]
47
+
48
+ [tool.hatch.build.targets.wheel]
49
+ exclude = ["/docs", "/scripts", "/AGENTS.md", "/uv.lock", "/zensical.toml"]
50
+
51
+ [dependency-groups]
52
+ dev = [
53
+ "isort>=8.0.1",
54
+ "mkdocstrings-python>=2.0.5",
55
+ "mypy>=2.1.0",
56
+ "pytest>=9.1.1",
57
+ "ruff>=0.15.20",
58
+ "zensical>=0.0.46",
59
+ ]
60
+
61
+ [tool.ruff]
62
+ exclude = ["vendor", ".venv"]
63
+
64
+ [tool.ruff.lint]
65
+ select = [
66
+ # pycodestyle
67
+ "E",
68
+ # Pyflakes
69
+ "F",
70
+ # pyupgrade
71
+ "UP",
72
+ # flake8-bugbear
73
+ "B",
74
+ # flake8-simplify
75
+ "SIM",
76
+ # isort
77
+ "I",
78
+ ]
79
+
80
+ [tool.isort]
81
+ profile = "black"
82
+ skip = ["vendor", ".venv"]
83
+
84
+ [tool.mypy]
85
+ exclude = ["vendor/"]
86
+
87
+ [tool.pytest.ini_options]
88
+ testpaths = ["tests"]
@@ -0,0 +1,12 @@
1
+ """ASCII and character policy checks for text files."""
2
+
3
+ from importlib.metadata import PackageNotFoundError, version
4
+
5
+ try:
6
+ __version__ = version("asciilint")
7
+ except (
8
+ PackageNotFoundError
9
+ ): # pragma: no cover - package is not installed in editable docs
10
+ __version__ = "0.0.0"
11
+
12
+ __all__ = ["__version__"]
@@ -0,0 +1,6 @@
1
+ """Run asciilint as ``python -m asciilint``."""
2
+
3
+ from asciilint.cli import main
4
+
5
+ if __name__ == "__main__":
6
+ main()