ansi-pixel 0.2.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 (37) hide show
  1. ansi_pixel-0.2.0/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
  2. ansi_pixel-0.2.0/.github/pull_request_template.md +24 -0
  3. ansi_pixel-0.2.0/.github/workflows/ci.yml +86 -0
  4. ansi_pixel-0.2.0/.github/workflows/publish.yml +76 -0
  5. ansi_pixel-0.2.0/.github/workflows/release-binaries.yml +114 -0
  6. ansi_pixel-0.2.0/.gitignore +31 -0
  7. ansi_pixel-0.2.0/IMPROVEMENTS.md +160 -0
  8. ansi_pixel-0.2.0/LICENSE +21 -0
  9. ansi_pixel-0.2.0/PKG-INFO +304 -0
  10. ansi_pixel-0.2.0/README.md +269 -0
  11. ansi_pixel-0.2.0/TASK_PLAN.md +101 -0
  12. ansi_pixel-0.2.0/docs/homebrew.md +79 -0
  13. ansi_pixel-0.2.0/img_to_ansi.py +15 -0
  14. ansi_pixel-0.2.0/logo.png +0 -0
  15. ansi_pixel-0.2.0/main.py +16 -0
  16. ansi_pixel-0.2.0/packaging/homebrew/ansi-pixel.rb +48 -0
  17. ansi_pixel-0.2.0/pyproject.toml +105 -0
  18. ansi_pixel-0.2.0/requirements.txt +1 -0
  19. ansi_pixel-0.2.0/rules.md +112 -0
  20. ansi_pixel-0.2.0/src/ansi_pixel/__init__.py +49 -0
  21. ansi_pixel-0.2.0/src/ansi_pixel/cli.py +299 -0
  22. ansi_pixel-0.2.0/src/ansi_pixel/converter.py +374 -0
  23. ansi_pixel-0.2.0/src/ansi_pixel/exporters/__init__.py +100 -0
  24. ansi_pixel-0.2.0/src/ansi_pixel/exporters/ansi.py +19 -0
  25. ansi_pixel-0.2.0/src/ansi_pixel/exporters/code.py +44 -0
  26. ansi_pixel-0.2.0/src/ansi_pixel/exporters/html.py +145 -0
  27. ansi_pixel-0.2.0/src/ansi_pixel/exporters/markdown.py +18 -0
  28. ansi_pixel-0.2.0/src/ansi_pixel/optimizer.py +153 -0
  29. ansi_pixel-0.2.0/src/ansi_pixel/py.typed +1 -0
  30. ansi_pixel-0.2.0/src/ansi_pixel/render.py +57 -0
  31. ansi_pixel-0.2.0/tests/test_cli.py +415 -0
  32. ansi_pixel-0.2.0/tests/test_converter.py +259 -0
  33. ansi_pixel-0.2.0/tests/test_exporters.py +161 -0
  34. ansi_pixel-0.2.0/tests/test_optimizer.py +149 -0
  35. ansi_pixel-0.2.0/tests/test_packaging.py +61 -0
  36. ansi_pixel-0.2.0/tests/test_render.py +205 -0
  37. ansi_pixel-0.2.0/uv.lock +805 -0
@@ -0,0 +1,32 @@
1
+ ---
2
+ name: Issue
3
+ about: Report a bug, suggest an improvement, or ask a question about ansi-pixel
4
+ title: ""
5
+ labels: ""
6
+ assignees: ""
7
+ ---
8
+
9
+ ## Description
10
+
11
+ <!-- What would you like to report or discuss? -->
12
+
13
+ ## Details
14
+
15
+ <!-- For bugs, include steps to reproduce and the expected behavior. For ideas, describe the proposed change and the problem it solves. -->
16
+
17
+ - Input image or a minimal example:
18
+ - Command used:
19
+ - Expected behavior:
20
+ - Actual behavior or proposed solution:
21
+
22
+ ## Environment
23
+
24
+ <!-- Complete these fields when relevant. -->
25
+
26
+ - OS:
27
+ - Python version:
28
+ - Pillow version:
29
+
30
+ ## Additional context
31
+
32
+ <!-- Include a traceback, screenshot, or sample image when useful. -->
@@ -0,0 +1,24 @@
1
+ ## Summary
2
+
3
+ <!-- What does this pull request change, and why? -->
4
+
5
+ ## Changes
6
+
7
+ -
8
+
9
+ ## Testing
10
+
11
+ <!-- Include the command(s) you ran and the result. -->
12
+
13
+ - [ ] Tested locally
14
+ - [ ] Updated documentation, if needed
15
+ - [ ] Added or updated tests, if needed
16
+
17
+ ## Screenshots or sample output
18
+
19
+ <!-- Include before/after output when the change affects rendering or CLI behavior. -->
20
+
21
+ ## Checklist
22
+
23
+ - [ ] The change is focused and ready for review.
24
+ - [ ] I have not committed generated output files.
@@ -0,0 +1,86 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ - "release/**"
8
+ pull_request:
9
+ branches:
10
+ - main
11
+ workflow_dispatch:
12
+
13
+ concurrency:
14
+ group: ${{ github.workflow }}-${{ github.ref }}
15
+ cancel-in-progress: true
16
+
17
+ jobs:
18
+ lint:
19
+ name: Code Quality & Linting
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - name: Check out repository
23
+ uses: actions/checkout@v4
24
+
25
+ - name: Set up Python 3.12
26
+ uses: actions/setup-python@v5
27
+ with:
28
+ python-version: "3.12"
29
+ cache: "pip"
30
+
31
+ - name: Install dependencies
32
+ run: |
33
+ python -m pip install --upgrade pip
34
+ python -m pip install -e ".[dev]"
35
+
36
+ - name: Check formatting with Ruff
37
+ run: ruff format --check src tests
38
+
39
+ - name: Run Ruff linter
40
+ run: ruff check src tests
41
+
42
+ - name: Run Mypy strict type checking
43
+ run: mypy src tests
44
+
45
+ test:
46
+ name: Test (${{ matrix.os }} - Py ${{ matrix.python-version }})
47
+ needs: lint
48
+ runs-on: ${{ matrix.os }}
49
+ strategy:
50
+ fail-fast: false
51
+ matrix:
52
+ os: [ubuntu-latest, macos-latest, windows-latest]
53
+ python-version:
54
+ - "3.9"
55
+ - "3.10"
56
+ - "3.11"
57
+ - "3.12"
58
+ - "3.13"
59
+ - "3.14-dev"
60
+ include:
61
+ # Allow experimental Python 3.14-dev pre-release builds to fail without blocking CI
62
+ - python-version: "3.14-dev"
63
+ experimental: true
64
+ continue-on-error: ${{ matrix.experimental || false }}
65
+
66
+ steps:
67
+ - name: Check out repository
68
+ uses: actions/checkout@v4
69
+
70
+ - name: Set up Python ${{ matrix.python-version }}
71
+ uses: actions/setup-python@v5
72
+ with:
73
+ python-version: ${{ matrix.python-version }}
74
+ allow-prereleases: true
75
+ cache: "pip"
76
+
77
+ - name: Install package and dependencies
78
+ run: |
79
+ python -m pip install --upgrade pip
80
+ python -m pip install -e ".[dev]"
81
+
82
+ - name: Run Pytest test suite
83
+ run: pytest
84
+
85
+ - name: Verify CLI console script entry point
86
+ run: ansi-pixel --help
@@ -0,0 +1,76 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*.*.*"
7
+ workflow_dispatch:
8
+ inputs:
9
+ target:
10
+ description: "Publish target"
11
+ type: choice
12
+ required: true
13
+ default: "pypi"
14
+ options:
15
+ - pypi
16
+ - testpypi
17
+
18
+ concurrency:
19
+ group: ${{ github.workflow }}-${{ github.ref }}
20
+ cancel-in-progress: false
21
+
22
+ jobs:
23
+ build:
24
+ name: Build distribution packages
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - name: Check out repository
28
+ uses: actions/checkout@v4
29
+
30
+ - name: Set up Python 3.12
31
+ uses: actions/setup-python@v5
32
+ with:
33
+ python-version: "3.12"
34
+ cache: "pip"
35
+
36
+ - name: Install build tools
37
+ run: |
38
+ python -m pip install --upgrade pip
39
+ python -m pip install build twine
40
+
41
+ - name: Build sdist and wheel
42
+ run: python -m build
43
+
44
+ - name: Verify package distributions with twine
45
+ run: twine check --strict dist/*
46
+
47
+ - name: Upload distribution packages
48
+ uses: actions/upload-artifact@v4
49
+ with:
50
+ name: python-package-distributions
51
+ path: dist/
52
+ retention-days: 7
53
+
54
+ publish:
55
+ name: Publish to ${{ github.event.inputs.target || 'pypi' }}
56
+ needs: build
57
+ runs-on: ubuntu-latest
58
+ environment:
59
+ name: ${{ github.event.inputs.target || 'pypi' }}
60
+ url: ${{ (github.event.inputs.target == 'testpypi') && 'https://test.pypi.org/p/ansi-pixel' || 'https://pypi.org/p/ansi-pixel' }}
61
+ permissions:
62
+ id-token: write
63
+ contents: read
64
+
65
+ steps:
66
+ - name: Download distribution packages
67
+ uses: actions/download-artifact@v4
68
+ with:
69
+ name: python-package-distributions
70
+ path: dist/
71
+
72
+ - name: Publish package distributions to PyPI
73
+ uses: pypa/gh-action-pypi-publish@release/v1
74
+ with:
75
+ repository-url: ${{ (github.event.inputs.target == 'testpypi') && 'https://test.pypi.org/legacy/' || '' }}
76
+ packages-dir: dist/
@@ -0,0 +1,114 @@
1
+ name: Release Standalone Binaries
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*.*.*"
7
+ workflow_dispatch:
8
+ inputs:
9
+ tag_name:
10
+ description: "Release tag (optional, e.g. v0.2.0)"
11
+ required: false
12
+ type: string
13
+
14
+ concurrency:
15
+ group: ${{ github.workflow }}-${{ github.ref }}
16
+ cancel-in-progress: false
17
+
18
+ jobs:
19
+ build-binaries:
20
+ name: Build (${{ matrix.target }})
21
+ runs-on: ${{ matrix.os }}
22
+ strategy:
23
+ fail-fast: false
24
+ matrix:
25
+ include:
26
+ - target: Linux x86_64
27
+ os: ubuntu-latest
28
+ binary_name: ansi-pixel-linux-x86_64
29
+ output_file: dist/ansi-pixel-linux-x86_64
30
+ - target: macOS Apple Silicon (ARM64)
31
+ os: macos-latest
32
+ binary_name: ansi-pixel-darwin-arm64
33
+ output_file: dist/ansi-pixel-darwin-arm64
34
+ - target: macOS Intel (x86_64)
35
+ os: macos-13
36
+ binary_name: ansi-pixel-darwin-x86_64
37
+ output_file: dist/ansi-pixel-darwin-x86_64
38
+ - target: Windows x86_64
39
+ os: windows-latest
40
+ binary_name: ansi-pixel-windows-x86_64
41
+ output_file: dist/ansi-pixel-windows-x86_64.exe
42
+
43
+ steps:
44
+ - name: Check out repository
45
+ uses: actions/checkout@v4
46
+
47
+ - name: Set up Python 3.12
48
+ uses: actions/setup-python@v5
49
+ with:
50
+ python-version: "3.12"
51
+ cache: "pip"
52
+
53
+ - name: Install dependencies and PyInstaller
54
+ run: |
55
+ python -m pip install --upgrade pip
56
+ python -m pip install pyinstaller .
57
+
58
+ - name: Build standalone executable with PyInstaller
59
+ run: pyinstaller --onefile --clean --name ${{ matrix.binary_name }} main.py
60
+
61
+ - name: Smoke test executable (Linux / macOS)
62
+ if: runner.os != 'Windows'
63
+ run: |
64
+ ./${{ matrix.output_file }} --help
65
+ ./${{ matrix.output_file }} --version
66
+
67
+ - name: Smoke test executable (Windows)
68
+ if: runner.os == 'Windows'
69
+ run: |
70
+ .\${{ matrix.output_file }} --help
71
+ .\${{ matrix.output_file }} --version
72
+
73
+ - name: Upload binary artifact
74
+ uses: actions/upload-artifact@v4
75
+ with:
76
+ name: ${{ matrix.binary_name }}
77
+ path: ${{ matrix.output_file }}
78
+ retention-days: 7
79
+
80
+ release:
81
+ name: Create GitHub Release & Upload Assets
82
+ needs: build-binaries
83
+ runs-on: ubuntu-latest
84
+ permissions:
85
+ contents: write
86
+
87
+ steps:
88
+ - name: Check out repository
89
+ uses: actions/checkout@v4
90
+
91
+ - name: Download all binary artifacts
92
+ uses: actions/download-artifact@v4
93
+ with:
94
+ path: release-assets
95
+ merge-multiple: true
96
+
97
+ - name: Generate SHA256 checksums
98
+ run: |
99
+ cd release-assets
100
+ sha256sum ansi-pixel-* > checksums.txt
101
+ echo "Generated checksums:"
102
+ cat checksums.txt
103
+
104
+ - name: Publish GitHub Release
105
+ if: startsWith(github.ref, 'refs/tags/v') || (github.event.inputs.tag_name != '')
106
+ uses: softprops/action-gh-release@v2
107
+ with:
108
+ tag_name: ${{ github.event.inputs.tag_name || github.ref_name }}
109
+ files: |
110
+ release-assets/ansi-pixel-*
111
+ release-assets/checksums.txt
112
+ generate_release_notes: true
113
+ draft: false
114
+ prerelease: false
@@ -0,0 +1,31 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # Virtual environments
7
+ .venv/
8
+ venv/
9
+ ENV/
10
+ env/
11
+
12
+ # Environment variables
13
+ .env
14
+
15
+ # PyInstaller / Build artifacts
16
+ build/
17
+ dist/
18
+ *.spec
19
+ *.egg-info/
20
+
21
+ # Quality tool caches
22
+ .mypy_cache/
23
+ .pytest_cache/
24
+ .ruff_cache/
25
+
26
+ # Output test files
27
+ output.txt
28
+ output.md
29
+ output.py
30
+ *.ans
31
+ repomix-output.md
@@ -0,0 +1,160 @@
1
+ # Improvements & Evolution Roadmap (`IMPROVEMENTS.md`)
2
+
3
+ This document identifies all current limitations of `ansi-pixel`, defines real-world use cases, and outlines the technical roadmap to elevate this project into a widely adopted CLI utility and published Python package.
4
+
5
+ ---
6
+
7
+ ## 1. Analysis of Current Limitations & Bugs
8
+
9
+ ### 1.1 Inadvertent White Pixel Erasure (Bug)
10
+
11
+ - **Current Behavior**:
12
+ ```python
13
+ top_empty = top_a < 128 or (top_r > 245 and top_g > 245 and top_b > 245)
14
+ ```
15
+ The script assumes any pixel with $R > 245, G > 245, B > 245$ is background and replaces it with an empty terminal space.
16
+ - **Problem**: In images that legitimately contain white elements (logos, eyes, clouds, text), these regions become transparent voids.
17
+ - **Solution**: Decouple alpha transparency from color filtering. Only transparent pixels ($A < 128$) are empty by default. Provide an optional `--chroma-key <HEX>` or `--trim-bg` flag for users who intentionally want to strip a white/solid background.
18
+
19
+ ### 1.2 Dead Code & Broken Border Crop
20
+
21
+ - **Current Behavior**:
22
+ ```python
23
+ bg = Image.new("RGBA", img.size, (255, 255, 255, 0))
24
+ bbox = img.getbbox()
25
+ ```
26
+ `bg` is allocated and never used. Furthermore, `getbbox()` on an RGBA image only trims where alpha is 0. It does not crop solid white backgrounds.
27
+ - **Solution**: Remove unused variables. If auto-trimming borders is desired, implement a robust bounding-box calculator that detects margin borders against background color or alpha.
28
+
29
+ ### 1.3 Bloated ANSI Output (No Sequence Compression)
30
+
31
+ - **Current Behavior**:
32
+ For every single column, the script emits:
33
+ `\033[38;2;{top_r};{top_g};{top_b}m\033[48;2;{bot_r};{bot_g};{bot_b}m▀\033[0m`
34
+ - **Problem**: Every character carries up to 40 bytes of ANSI sequences, even if the entire row has the same color. A $100 \times 50$ output can exceed 150 KB.
35
+ - **Solution**: Implement an **ANSI Sequence Optimizer**:
36
+ - Track current foreground and background colors.
37
+ - Only emit color escape sequences when the color transitions.
38
+ - Omit `\033[0m` resets between consecutive characters, resetting only at end-of-line or when entering a transparent block.
39
+ - Result: 50% to 75% reduction in output size and faster rendering over remote SSH connections.
40
+
41
+ ### 1.4 Hardcoded File Overwrites in CWD
42
+
43
+ - **Current Behavior**:
44
+ `main.py` hardcodes file output paths to `./output.txt`, `./output.md`, or `./output.py`.
45
+ - **Problem**: When `ansi-pixel` is installed globally via `pip` or `pipx`, running it inside any project directory will create unwanted files in the user's working folder.
46
+ - **Solution**:
47
+ - Follow standard UNIX CLI conventions: Print directly to `stdout` by default.
48
+ - Provide `-o` / `--output <PATH>` to write to a specific destination file.
49
+ - Provide `-f` / `--format <txt|md|py|js|html>` to specify the format.
50
+
51
+ ### 1.5 Suboptimal Pixel Reading Loop
52
+
53
+ - **Current Behavior**:
54
+ Nested Python loops calling `img.getpixel((x, y))` twice per coordinate.
55
+ - **Problem**: `getpixel()` in pure Python has high function-call overhead.
56
+ - **Solution**: Use `img.load()` (direct pixel buffer pointer) or byte arrays, which executes 10x–30x faster.
57
+
58
+ ---
59
+
60
+ ## 2. Real-World Purpose & Practical Applications
61
+
62
+ To make `ansi-pixel` a tool that developers actively seek out and integrate, we target four core use cases:
63
+
64
+ ```
65
+ ┌────────────────────────────────────────────────────────┐
66
+ │ ansi-pixel Real Use Cases │
67
+ └────────────────────────────────────────────────────────┘
68
+ │ │ │
69
+ ┌──────────┴────────┐ ┌────────┴────────┐ ┌────────┴────────┐
70
+ │ CLI Tool Banners │ │ Remote Terminal │ │ GitHub README │
71
+ │ & Startup Mascots │ │ Image Preview │ │ & Doc Badges │
72
+ └───────────────────┘ └─────────────────┘ └─────────────────┘
73
+ ```
74
+
75
+ 1. **CLI Branding & Welcome Screens**:
76
+ - CLI framework authors (FastAPI, Typer, Click, Node.js CLI tools) want branded logos in the console.
77
+ - `ansi-pixel logo.png -f python` generates ready-to-paste Python banner code (`LOGO = "..."`).
78
+ - `ansi-pixel logo.png -f js` generates JavaScript template strings for Node.js / Deno CLIs.
79
+ 2. **Headless & SSH Image Previewer**:
80
+ - Developers and sysadmins on remote servers or inside Docker containers lack GUI viewers.
81
+ - Running `ansi-pixel cat.png` provides an immediate visual preview right in their shell.
82
+ - Support streaming from pipes: `curl -sL https://site.com/image.png | ansi-pixel -`.
83
+ 3. **Rich & Textual TUI Dashboard Avatars**:
84
+ - Python terminal applications need to display user avatars, status badges, or product icons in terminal user interfaces.
85
+ - Providing an importable Python API (`import ansi_pixel`) allows direct embedding into Rich consoles, Textual widgets, and prompt_toolkit applications.
86
+ 4. **GitHub Markdown Colored Art**:
87
+ - Modern GitHub Markdown renders ``ansi` code blocks. `ansi-pixel` produces ready-to-paste ANSI markdown blocks to spice up repository READMEs.
88
+
89
+ ---
90
+
91
+ ## 3. High-Priority Feature Improvements
92
+
93
+ ### 3.1 Terminal Dimensions Auto-Detection
94
+
95
+ - Automatically read the user's terminal column width using `shutil.get_terminal_size()`.
96
+ - Default to fitting cleanly within the terminal (e.g. `width = min(terminal_cols, 80)`), eliminating horizontal line-wrapping on small screens while keeping images crisp.
97
+
98
+ ### 3.2 Flexible Resampling Filters
99
+
100
+ - Pixel art logos look best with `Image.Resampling.NEAREST` (sharp pixels).
101
+ - Photographs and gradients look best with `Image.Resampling.LANCZOS` or `BILINEAR`.
102
+ - Provide `--filter <nearest|lanczos|bilinear>` (default: `nearest` for small images, `lanczos` for large photos).
103
+
104
+ ### 3.3 Color Mode Reductions & Fallbacks
105
+
106
+ - **TrueColor (24-bit)**: `\033[38;2;r;g;bm` (Default).
107
+ - **256-Color (8-bit)**: Maps RGB to the standard xterm 256-color palette for older terminals or restricted SSH sessions.
108
+ - **16-Color (4-bit)**: Basic ANSI colors.
109
+ - **Grayscale / Monochromatic**: For clean ASCII/block aesthetic.
110
+ - **`NO_COLOR` Compliance**: Automatically disable ANSI escape sequences when the `NO_COLOR` environment variable is detected or when redirected to a non-TTY pipe without forced color flags.
111
+
112
+ ### 3.4 Extended Exporters
113
+
114
+ - `-f ansi` (default): Pure ANSI escape strings.
115
+ - `-f md`: GitHub-compliant ``ansi` Markdown block.
116
+ - `-f py`: Clean Python snippet (`BANNER = "..."` or list of lines).
117
+ - `-f js`: ES6 JavaScript template literal (`export const banner = \`...\``).
118
+ - `-f html`: HTML `<pre>` block using styled `<span style="color:...;background:...">` for web pages.
119
+
120
+ ---
121
+
122
+ ## 4. Packaging & Distribution Plan
123
+
124
+ ### Where to Release:
125
+
126
+ | Platform | Channel | Install Method | Target Audience |
127
+ | :------------------ | :--------------------- | :-------------------------------------------------------------------------------- | :-------------------------------------- |
128
+ | **PyPI** | Official Python Index | `pip install ansi-pixel`<br>`pipx run ansi-pixel`<br>`uv tool install ansi-pixel` | Python developers, CLI users, sysadmins |
129
+ | **GitHub Releases** | Binaries & Assets | Download pre-built binary | Users without Python runtime installed |
130
+ | **Homebrew Tap** | macOS / Linux packages | `brew install senuradesilva/tap/ansi-pixel` | Mac / Linux terminal power users |
131
+ | **Docker / GHCR** | Container image | `docker run --rm ghcr.io/senuradesilva/ansi-pixel` | CI/CD automation & pipeline inspection |
132
+
133
+ ### How to Package:
134
+
135
+ 1. **Modern PEP 621 Standard**:
136
+ - Adopt `pyproject.toml` with `hatchling` build backend.
137
+ - Declare entrypoint script: `ansi-pixel = "ansi_pixel.cli:main"`.
138
+ 2. **Source Code Structure**:
139
+ ```
140
+ ansi-pixel/
141
+ ├── pyproject.toml
142
+ ├── README.md
143
+ ├── LICENSE
144
+ ├── src/
145
+ │ └── ansi_pixel/
146
+ │ ├── __init__.py
147
+ │ ├── cli.py
148
+ │ ├── converter.py
149
+ │ ├── optimizer.py
150
+ │ ├── exporters.py
151
+ │ └── py.typed
152
+ └── tests/
153
+ ├── test_cli.py
154
+ ├── test_converter.py
155
+ ├── test_optimizer.py
156
+ └── test_exporters.py
157
+ ```
158
+ 3. **Automated Publishing via GitHub Actions**:
159
+ - Configure **PyPI Trusted Publishing (OIDC)**: No manual API tokens or passwords needed.
160
+ - Pushing a new git tag (e.g., `git tag v0.2.0 && git push origin v0.2.0`) builds the distribution wheels and securely publishes directly to PyPI.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Senura Hesara
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.