pytailwindcss 0.3.0__tar.gz → 0.4.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 (31) hide show
  1. pytailwindcss-0.4.0/.github/dependabot.yml +12 -0
  2. pytailwindcss-0.4.0/.github/workflows/ci.yml +83 -0
  3. pytailwindcss-0.4.0/.github/zizmor.yml +6 -0
  4. pytailwindcss-0.4.0/.gitignore +146 -0
  5. pytailwindcss-0.4.0/.pre-commit-config.yaml +41 -0
  6. pytailwindcss-0.4.0/CHANGELOG.md +30 -0
  7. pytailwindcss-0.4.0/PKG-INFO +191 -0
  8. pytailwindcss-0.4.0/README.md +164 -0
  9. pytailwindcss-0.4.0/pyproject.toml +88 -0
  10. pytailwindcss-0.4.0/src/pytailwindcss/__init__.py +68 -0
  11. pytailwindcss-0.4.0/src/pytailwindcss/__main__.py +27 -0
  12. {pytailwindcss-0.3.0 → pytailwindcss-0.4.0}/src/pytailwindcss/exceptions.py +4 -0
  13. pytailwindcss-0.4.0/src/pytailwindcss/installation.py +167 -0
  14. pytailwindcss-0.4.0/src/pytailwindcss/py.typed +0 -0
  15. pytailwindcss-0.4.0/src/pytailwindcss/utils.py +63 -0
  16. pytailwindcss-0.4.0/tests/__init__.py +0 -0
  17. pytailwindcss-0.4.0/tests/conftest.py +26 -0
  18. pytailwindcss-0.4.0/tests/fakes.py +41 -0
  19. pytailwindcss-0.4.0/tests/test_core.py +83 -0
  20. pytailwindcss-0.4.0/tests/test_installation.py +234 -0
  21. pytailwindcss-0.4.0/tests/test_main.py +71 -0
  22. pytailwindcss-0.4.0/tests/test_utils.py +92 -0
  23. pytailwindcss-0.4.0/uv.lock +743 -0
  24. pytailwindcss-0.3.0/PKG-INFO +0 -138
  25. pytailwindcss-0.3.0/README.md +0 -112
  26. pytailwindcss-0.3.0/pyproject.toml +0 -41
  27. pytailwindcss-0.3.0/src/pytailwindcss/__init__.py +0 -69
  28. pytailwindcss-0.3.0/src/pytailwindcss/__main__.py +0 -24
  29. pytailwindcss-0.3.0/src/pytailwindcss/installation.py +0 -88
  30. pytailwindcss-0.3.0/src/pytailwindcss/utils.py +0 -52
  31. {pytailwindcss-0.3.0 → pytailwindcss-0.4.0}/LICENSE +0 -0
@@ -0,0 +1,12 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ cooldown:
8
+ default-days: 7
9
+ groups:
10
+ actions:
11
+ patterns:
12
+ - "*"
@@ -0,0 +1,83 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+ workflow_dispatch:
7
+
8
+ concurrency:
9
+ group: ${{ github.workflow }}-${{ github.ref }}
10
+ cancel-in-progress: true
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ jobs:
16
+ pre-commit:
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v7
20
+ with:
21
+ persist-credentials: false
22
+ - uses: astral-sh/setup-uv@v10.3.0
23
+ with:
24
+ python-version: '3.14'
25
+ - run: uvx pre-commit run --all-files --show-diff-on-failure
26
+
27
+ tests:
28
+ needs: [ pre-commit ]
29
+ runs-on: ${{ matrix.os }}
30
+ strategy:
31
+ fail-fast: false
32
+ matrix:
33
+ os: [ ubuntu-latest ]
34
+ python-version: [ "3.11", "3.12", "3.13", "3.14" ]
35
+ include:
36
+ # Binary selection is OS-specific, so the newest Python also runs on macOS and Windows.
37
+ - os: macos-latest
38
+ python-version: "3.14"
39
+ - os: windows-latest
40
+ python-version: "3.14"
41
+ steps:
42
+ - uses: actions/checkout@v7
43
+ with:
44
+ persist-credentials: false
45
+ - uses: astral-sh/setup-uv@v10.3.0
46
+ with:
47
+ python-version: ${{ matrix.python-version }}
48
+ - run: uv sync --locked
49
+ - run: uv run pytest --cov --cov-report=term
50
+
51
+ tests-alpine:
52
+ needs: [ pre-commit ]
53
+ runs-on: ubuntu-latest
54
+ steps:
55
+ - uses: actions/checkout@v7
56
+ with:
57
+ persist-credentials: false
58
+ # JavaScript actions can't run inside Alpine containers (the runner's Node is glibc-only),
59
+ # so the musl test run happens through a plain `docker run`. Tailwind's musl builds link
60
+ # against libstdc++ and libgcc, which Alpine doesn't ship by default.
61
+ - run: >-
62
+ docker run --rm -v "$PWD:/src" -w /src -e UV_PYTHON_DOWNLOADS=never python:3.14-alpine
63
+ sh -c "apk add --no-cache libstdc++ libgcc && pip install --root-user-action=ignore uv && uv sync --locked && uv run pytest"
64
+
65
+ release:
66
+ needs: [ tests, tests-alpine ]
67
+ if: success() && startsWith(github.ref, 'refs/tags/')
68
+ runs-on: ubuntu-24.04
69
+ environment: release
70
+ permissions:
71
+ contents: read
72
+ id-token: write
73
+ steps:
74
+ - uses: actions/checkout@v7
75
+ with:
76
+ persist-credentials: false
77
+ - uses: astral-sh/setup-uv@v10.3.0
78
+ with:
79
+ python-version: '3.14'
80
+ - name: Check tag matches project version
81
+ run: test "${GITHUB_REF_NAME#v}" = "$(uv version --short)"
82
+ - run: uv build
83
+ - uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,6 @@
1
+ rules:
2
+ unpinned-uses:
3
+ config:
4
+ # Major-version tags kept current by Dependabot, rather than SHA pins.
5
+ policies:
6
+ "*": ref-pin
@@ -0,0 +1,146 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
98
+ __pypackages__/
99
+
100
+ # Celery stuff
101
+ celerybeat-schedule
102
+ celerybeat.pid
103
+
104
+ # SageMath parsed files
105
+ *.sage.py
106
+
107
+ # Environments
108
+ .env
109
+ .venv
110
+ env/
111
+ venv/
112
+ ENV/
113
+ env.bak/
114
+ venv.bak/
115
+
116
+ # Spyder project settings
117
+ .spyderproject
118
+ .spyproject
119
+
120
+ # Rope project settings
121
+ .ropeproject
122
+
123
+ # mkdocs documentation
124
+ /site
125
+
126
+ # mypy
127
+ .mypy_cache/
128
+ .dmypy.json
129
+ dmypy.json
130
+
131
+ # Pyre type checker
132
+ .pyre/
133
+
134
+ # pytype static type analyzer
135
+ .pytype/
136
+
137
+ # Cython debug symbols
138
+ cython_debug/
139
+
140
+ .DS_Store
141
+ .idea
142
+ src/pytailwindcss/bin
143
+ .claude
144
+ .history
145
+
146
+ _devcontext/
@@ -0,0 +1,41 @@
1
+ repos:
2
+ - repo: https://github.com/pre-commit/pre-commit-hooks
3
+ rev: v6.0.0
4
+ hooks:
5
+ - id: check-added-large-files
6
+ - id: check-ast
7
+ - id: check-case-conflict
8
+ - id: check-json
9
+ - id: check-merge-conflict
10
+ - id: check-symlinks
11
+ - id: check-toml
12
+ - id: check-yaml
13
+ - id: debug-statements
14
+ - id: detect-private-key
15
+ - id: end-of-file-fixer
16
+ - id: trailing-whitespace
17
+ - id: mixed-line-ending
18
+ - repo: https://github.com/crate-ci/typos
19
+ rev: v1.51.1
20
+ hooks:
21
+ - id: typos
22
+ - repo: https://github.com/tox-dev/pyproject-fmt
23
+ rev: v2.30.3
24
+ hooks:
25
+ - id: pyproject-fmt
26
+ - repo: https://github.com/astral-sh/ruff-pre-commit
27
+ rev: v0.17.0
28
+ hooks:
29
+ - id: ruff-check
30
+ args: [ --fix, --show-fixes ]
31
+ - id: ruff-format
32
+ - repo: https://github.com/pre-commit/mirrors-mypy
33
+ rev: v2.4.0
34
+ hooks:
35
+ - id: mypy
36
+ additional_dependencies:
37
+ - pytest>=9.0.3
38
+ - repo: https://github.com/zizmorcore/zizmor-pre-commit
39
+ rev: v1.30.1
40
+ hooks:
41
+ - id: zizmor
@@ -0,0 +1,30 @@
1
+ # Changelog
2
+
3
+ ## 0.4.0 (2026-10-13)
4
+
5
+ ### Added
6
+
7
+ - Downloads are verified against the release's `sha256sums.txt`; a mismatch raises `PyTailwindCssChecksumMismatch` and nothing is installed. Releases without checksums (before v4) install with a warning.
8
+ - Alpine and other musl-based Linux systems get the `-musl` Tailwind CSS binary (it needs `apk add libstdc++ libgcc`).
9
+ - `TAILWINDCSS_BIN_DIR` environment variable to choose where binaries are stored.
10
+ - Type hints and a `py.typed` marker.
11
+
12
+ ### Changed
13
+
14
+ - Installation is atomic: the binary is downloaded next to its destination and swapped in only after it's verified, so a failed download keeps the previous binary.
15
+ - Installed binaries are mode `0755`, so a binary installed as root (e.g. at Docker build time) runs for any user.
16
+ - Download progress is printed to stderr instead of stdout, so it no longer mixes with `tailwindcss` output.
17
+ - Network failures, HTTP errors other than 404, unsupported platforms, and unwritable binary directories raise `PyTailwindCssException` with a readable message; the CLI commands print it instead of a traceback.
18
+ - Downloads time out after 60 seconds without data.
19
+ - `run()` raises `PyTailwindCssBinaryNotFound` only when the binary is actually missing; a missing `cwd` now surfaces as the original `FileNotFoundError`.
20
+ - README updated for Tailwind CSS v4.
21
+
22
+ ### Fixed
23
+
24
+ - Windows: the binary is saved as `tailwindcss.exe`, so it can be executed.
25
+ - `run(bin_path="...", auto_install=True)` no longer crashes when `bin_path` is a string.
26
+ - Temporary download directories are no longer leaked.
27
+
28
+ ## Earlier releases
29
+
30
+ See the [git tags](https://github.com/timonweb/pytailwindcss/tags).
@@ -0,0 +1,191 @@
1
+ Metadata-Version: 2.5
2
+ Name: pytailwindcss
3
+ Version: 0.4.0
4
+ Summary: Standalone Tailwind CSS CLI, installable via pip. Use Tailwind CSS without Node.js.
5
+ Project-URL: Changelog, https://github.com/timonweb/pytailwindcss/blob/main/CHANGELOG.md
6
+ Project-URL: Homepage, https://github.com/timonweb/pytailwindcss
7
+ Project-URL: Issues, https://github.com/timonweb/pytailwindcss/issues
8
+ Project-URL: Source, https://github.com/timonweb/pytailwindcss
9
+ Author-email: Tim Kamanin <tim@timonweb.com>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: cli,css,tailwind
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Web Environment
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: Software Development :: Libraries
23
+ Classifier: Topic :: Utilities
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.11
26
+ Description-Content-Type: text/markdown
27
+
28
+ # Standalone Tailwind CSS CLI, installable via pip
29
+
30
+ Use *Tailwind CSS* without *Node.js* — install it via pip.
31
+
32
+ ## Why
33
+
34
+ *Tailwind CSS* is notoriously dependent on *Node.js*. If you're a *Python* developer, this dependency may not be welcome
35
+ in your team, your Docker container, or your inner circle.
36
+
37
+ The *Tailwind CSS* team ships a standalone CLI build that gives you the full power of *Tailwind CLI* in a
38
+ self-contained executable — no *Node.js* or `npm` required.
39
+
40
+ However, installing the standalone CLI isn't as easy as running `npm install`.
41
+
42
+ That's why I created this package to make it as simple as running the `pip install` command. Now you can install the standalone *Tailwind CLI* via `pip` by running:
43
+
44
+ ```bash
45
+ pip install pytailwindcss
46
+ ```
47
+
48
+ Now you can run `tailwindcss` in your terminal:
49
+
50
+ ```bash
51
+ tailwindcss -i input.css -o output.css --minify
52
+ ```
53
+
54
+ Voilà!
55
+
56
+ ## Get started
57
+
58
+ 1. Install `pytailwindcss` via `pip` (or `uv add pytailwindcss`):
59
+
60
+ ```bash
61
+ pip install pytailwindcss
62
+ ```
63
+
64
+ 2. **[Recommended]** Preinstall the `tailwindcss` binary:
65
+
66
+ ```bash
67
+ tailwindcss_install
68
+ ```
69
+
70
+ If you skip this step, the binary will be downloaded automatically on the first run of the `tailwindcss` command.
71
+
72
+ 3. Create an `input.css` file that imports Tailwind CSS:
73
+
74
+ ```css
75
+ @import "tailwindcss";
76
+ ```
77
+
78
+ Tailwind CSS v4 is configured right in your CSS — there's no `tailwind.config.js` and no `tailwindcss init` anymore. See the [official documentation](https://tailwindcss.com/docs) for theming and customization.
79
+
80
+ 4. Start a watcher to compile CSS automatically during development:
81
+
82
+ ```bash
83
+ tailwindcss -i input.css -o output.css --watch
84
+ ```
85
+
86
+ 5. Compile and minify your CSS for production:
87
+
88
+ ```bash
89
+ tailwindcss -i input.css -o output.css --minify
90
+ ```
91
+
92
+ That's it! Run `tailwindcss --help` to see all the CLI options.
93
+
94
+ ## Pinning a Tailwind CSS version
95
+
96
+ By default, the latest binary version is downloaded. To pin to a specific Tailwind CSS version, set the `TAILWINDCSS_VERSION` environment variable. It's used by both `tailwindcss_install` and `tailwindcss`:
97
+
98
+ ```bash
99
+ # On Linux/macOS
100
+ export TAILWINDCSS_VERSION=v4.3.3
101
+ tailwindcss_install
102
+
103
+ # On Windows (cmd)
104
+ set TAILWINDCSS_VERSION=v4.3.3
105
+ tailwindcss_install
106
+
107
+ # On Windows (PowerShell)
108
+ $env:TAILWINDCSS_VERSION="v4.3.3"
109
+ tailwindcss_install
110
+ ```
111
+
112
+ To see a list of available Tailwind CSS releases, visit: https://github.com/tailwindlabs/tailwindcss/releases
113
+
114
+ Every download is checked against the SHA-256 checksums published with the release, and a binary that doesn't match is never installed. Releases before v4 don't publish checksums; for those, `pytailwindcss` logs a warning and installs the binary unverified.
115
+
116
+ ## Where the binary lives
117
+
118
+ Binaries are stored per version inside the installed package, so every virtualenv gets its own copy and projects don't affect each other.
119
+
120
+ If that directory isn't writable (for example, a virtualenv owned by another user), point `TAILWINDCSS_BIN_DIR` at a directory you can write to (relative paths and `~` are resolved):
121
+
122
+ ```bash
123
+ export TAILWINDCSS_BIN_DIR=~/.cache/pytailwindcss
124
+ ```
125
+
126
+ Binaries then go to `$TAILWINDCSS_BIN_DIR/<version>/tailwindcss`.
127
+
128
+ ## Docker
129
+
130
+ Install the binary while building the image, so containers start without downloading anything:
131
+
132
+ ```dockerfile
133
+ ENV TAILWINDCSS_VERSION=v4.3.3
134
+ RUN pip install pytailwindcss && tailwindcss_install
135
+ ```
136
+
137
+ The binary is readable and executable by every user, so it's fine to install it as root and run your app as an unprivileged user.
138
+
139
+ On Alpine (musl) images, `pytailwindcss` downloads the matching `-musl` build of Tailwind CSS v4. That build needs the C++ runtime libraries, which Alpine doesn't include by default:
140
+
141
+ ```dockerfile
142
+ RUN apk add --no-cache libstdc++ libgcc
143
+ ```
144
+
145
+ ## Using it from Python
146
+
147
+ ```python
148
+ import pytailwindcss
149
+
150
+ # Download the binary (optional, see auto_install below).
151
+ pytailwindcss.install(version="v4.3.3")
152
+
153
+ # Run the CLI and get its output as a string.
154
+ pytailwindcss.run("-i input.css -o output.css --minify", version="v4.3.3")
155
+
156
+ # Arguments can be a list too; auto_install downloads the binary if it's missing.
157
+ pytailwindcss.run(["-i", "input.css", "-o", "output.css"], auto_install=True)
158
+ ```
159
+
160
+ `run()` raises `subprocess.CalledProcessError` when Tailwind CSS exits with an error. Pass `live_output=True` to stream Tailwind's output to the terminal instead; you then get the `subprocess.CompletedProcess` back. Download and installation problems raise subclasses of `pytailwindcss.exceptions.PyTailwindCssException`.
161
+
162
+ ## Caveats
163
+
164
+ Without *Node.js*, you can't install third-party plugins from npm. The standalone build bundles the official plugins, though — `@tailwindcss/forms`, `@tailwindcss/typography`, and `@tailwindcss/aspect-ratio` — so you can enable them in your CSS:
165
+
166
+ ```css
167
+ @import "tailwindcss";
168
+ @plugin "@tailwindcss/typography";
169
+ ```
170
+
171
+ This covers the vast majority of typical *Tailwind CSS* setups.
172
+
173
+ Here's what the *Tailwind CSS* team says about the standalone build:
174
+ > If you're working on a project where you don't otherwise need *Node.js* or `npm`, the standalone build can be a great choice. If Tailwind was the only reason you had a package.json file, this is probably going to feel like a nicer solution.
175
+
176
+ ## Development
177
+
178
+ ```bash
179
+ uv sync # create the virtualenv with dev dependencies
180
+ uv run pytest # run all tests (some download real binaries)
181
+ uv run pytest -m "not network" # skip the tests that need network access
182
+ uvx pre-commit install # run linters, formatters, and mypy on every commit
183
+ ```
184
+
185
+ ## Bugs and Suggestions
186
+
187
+ Found a bug or have a suggestion? Please use the issue tracker on GitHub:
188
+
189
+ [https://github.com/timonweb/pytailwindcss/issues](https://github.com/timonweb/pytailwindcss/issues)
190
+
191
+ 2021 - 2026 (c) Tim Kamanin — [A Full-Stack Django and Wagtail Developer](https://timonweb.com)
@@ -0,0 +1,164 @@
1
+ # Standalone Tailwind CSS CLI, installable via pip
2
+
3
+ Use *Tailwind CSS* without *Node.js* — install it via pip.
4
+
5
+ ## Why
6
+
7
+ *Tailwind CSS* is notoriously dependent on *Node.js*. If you're a *Python* developer, this dependency may not be welcome
8
+ in your team, your Docker container, or your inner circle.
9
+
10
+ The *Tailwind CSS* team ships a standalone CLI build that gives you the full power of *Tailwind CLI* in a
11
+ self-contained executable — no *Node.js* or `npm` required.
12
+
13
+ However, installing the standalone CLI isn't as easy as running `npm install`.
14
+
15
+ That's why I created this package to make it as simple as running the `pip install` command. Now you can install the standalone *Tailwind CLI* via `pip` by running:
16
+
17
+ ```bash
18
+ pip install pytailwindcss
19
+ ```
20
+
21
+ Now you can run `tailwindcss` in your terminal:
22
+
23
+ ```bash
24
+ tailwindcss -i input.css -o output.css --minify
25
+ ```
26
+
27
+ Voilà!
28
+
29
+ ## Get started
30
+
31
+ 1. Install `pytailwindcss` via `pip` (or `uv add pytailwindcss`):
32
+
33
+ ```bash
34
+ pip install pytailwindcss
35
+ ```
36
+
37
+ 2. **[Recommended]** Preinstall the `tailwindcss` binary:
38
+
39
+ ```bash
40
+ tailwindcss_install
41
+ ```
42
+
43
+ If you skip this step, the binary will be downloaded automatically on the first run of the `tailwindcss` command.
44
+
45
+ 3. Create an `input.css` file that imports Tailwind CSS:
46
+
47
+ ```css
48
+ @import "tailwindcss";
49
+ ```
50
+
51
+ Tailwind CSS v4 is configured right in your CSS — there's no `tailwind.config.js` and no `tailwindcss init` anymore. See the [official documentation](https://tailwindcss.com/docs) for theming and customization.
52
+
53
+ 4. Start a watcher to compile CSS automatically during development:
54
+
55
+ ```bash
56
+ tailwindcss -i input.css -o output.css --watch
57
+ ```
58
+
59
+ 5. Compile and minify your CSS for production:
60
+
61
+ ```bash
62
+ tailwindcss -i input.css -o output.css --minify
63
+ ```
64
+
65
+ That's it! Run `tailwindcss --help` to see all the CLI options.
66
+
67
+ ## Pinning a Tailwind CSS version
68
+
69
+ By default, the latest binary version is downloaded. To pin to a specific Tailwind CSS version, set the `TAILWINDCSS_VERSION` environment variable. It's used by both `tailwindcss_install` and `tailwindcss`:
70
+
71
+ ```bash
72
+ # On Linux/macOS
73
+ export TAILWINDCSS_VERSION=v4.3.3
74
+ tailwindcss_install
75
+
76
+ # On Windows (cmd)
77
+ set TAILWINDCSS_VERSION=v4.3.3
78
+ tailwindcss_install
79
+
80
+ # On Windows (PowerShell)
81
+ $env:TAILWINDCSS_VERSION="v4.3.3"
82
+ tailwindcss_install
83
+ ```
84
+
85
+ To see a list of available Tailwind CSS releases, visit: https://github.com/tailwindlabs/tailwindcss/releases
86
+
87
+ Every download is checked against the SHA-256 checksums published with the release, and a binary that doesn't match is never installed. Releases before v4 don't publish checksums; for those, `pytailwindcss` logs a warning and installs the binary unverified.
88
+
89
+ ## Where the binary lives
90
+
91
+ Binaries are stored per version inside the installed package, so every virtualenv gets its own copy and projects don't affect each other.
92
+
93
+ If that directory isn't writable (for example, a virtualenv owned by another user), point `TAILWINDCSS_BIN_DIR` at a directory you can write to (relative paths and `~` are resolved):
94
+
95
+ ```bash
96
+ export TAILWINDCSS_BIN_DIR=~/.cache/pytailwindcss
97
+ ```
98
+
99
+ Binaries then go to `$TAILWINDCSS_BIN_DIR/<version>/tailwindcss`.
100
+
101
+ ## Docker
102
+
103
+ Install the binary while building the image, so containers start without downloading anything:
104
+
105
+ ```dockerfile
106
+ ENV TAILWINDCSS_VERSION=v4.3.3
107
+ RUN pip install pytailwindcss && tailwindcss_install
108
+ ```
109
+
110
+ The binary is readable and executable by every user, so it's fine to install it as root and run your app as an unprivileged user.
111
+
112
+ On Alpine (musl) images, `pytailwindcss` downloads the matching `-musl` build of Tailwind CSS v4. That build needs the C++ runtime libraries, which Alpine doesn't include by default:
113
+
114
+ ```dockerfile
115
+ RUN apk add --no-cache libstdc++ libgcc
116
+ ```
117
+
118
+ ## Using it from Python
119
+
120
+ ```python
121
+ import pytailwindcss
122
+
123
+ # Download the binary (optional, see auto_install below).
124
+ pytailwindcss.install(version="v4.3.3")
125
+
126
+ # Run the CLI and get its output as a string.
127
+ pytailwindcss.run("-i input.css -o output.css --minify", version="v4.3.3")
128
+
129
+ # Arguments can be a list too; auto_install downloads the binary if it's missing.
130
+ pytailwindcss.run(["-i", "input.css", "-o", "output.css"], auto_install=True)
131
+ ```
132
+
133
+ `run()` raises `subprocess.CalledProcessError` when Tailwind CSS exits with an error. Pass `live_output=True` to stream Tailwind's output to the terminal instead; you then get the `subprocess.CompletedProcess` back. Download and installation problems raise subclasses of `pytailwindcss.exceptions.PyTailwindCssException`.
134
+
135
+ ## Caveats
136
+
137
+ Without *Node.js*, you can't install third-party plugins from npm. The standalone build bundles the official plugins, though — `@tailwindcss/forms`, `@tailwindcss/typography`, and `@tailwindcss/aspect-ratio` — so you can enable them in your CSS:
138
+
139
+ ```css
140
+ @import "tailwindcss";
141
+ @plugin "@tailwindcss/typography";
142
+ ```
143
+
144
+ This covers the vast majority of typical *Tailwind CSS* setups.
145
+
146
+ Here's what the *Tailwind CSS* team says about the standalone build:
147
+ > If you're working on a project where you don't otherwise need *Node.js* or `npm`, the standalone build can be a great choice. If Tailwind was the only reason you had a package.json file, this is probably going to feel like a nicer solution.
148
+
149
+ ## Development
150
+
151
+ ```bash
152
+ uv sync # create the virtualenv with dev dependencies
153
+ uv run pytest # run all tests (some download real binaries)
154
+ uv run pytest -m "not network" # skip the tests that need network access
155
+ uvx pre-commit install # run linters, formatters, and mypy on every commit
156
+ ```
157
+
158
+ ## Bugs and Suggestions
159
+
160
+ Found a bug or have a suggestion? Please use the issue tracker on GitHub:
161
+
162
+ [https://github.com/timonweb/pytailwindcss/issues](https://github.com/timonweb/pytailwindcss/issues)
163
+
164
+ 2021 - 2026 (c) Tim Kamanin — [A Full-Stack Django and Wagtail Developer](https://timonweb.com)