Skip to content

Commit

Permalink
Closes #70
Browse files Browse the repository at this point in the history
  • Loading branch information
oliverandrich committed Nov 25, 2023
1 parent 4c30d8a commit 0ca3907
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 39 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Changelog

## 2.7.0 (unreleased)
## 2.7.0

- Added more command line arguments to `tailwind runserver` and `tailwind runserver_plus`.
- `tailwind runserver`
Expand All @@ -17,6 +17,8 @@
- `--pm`
- `--print-sql`
- Fixed [#67](https://github.com/oliverandrich/django-tailwind-cli/issues/67) to fetch the correct CLI on the Windows platform.
- `TAILWIND_CLI_PATH` can also point to an pre-installed binary from a package manager.
- Added a new setting `TAILWIND_CLI_AUTOMATIC_DOWNLOAD` to steer if you want the library to download the CLI binary or not. This comes in handy with the additional option for `TAILWIND_CLI_PATH` to point to a pre-installed binary.

## 2.6.0

Expand Down
17 changes: 16 additions & 1 deletion docs/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,22 @@ The package can be configured by a few settings, which can be overwritten in the
`TAILWIND_CLI_PATH`
: **Default**: `"~/.local/bin/"`

The path where to store CLI binary on your machine. The default value aims for an installation in your home directory and is tailored for Unix and macOS systems. On Windows you might need to configure a different path.
The path where to store CLI binary on your machine or the path to an manually installed binary.

The default behaviour is, that `TAILWIND_CLI_PATH` should point to a directory, where `django-tailwind-cli` is allowed to download the official CLI to. Normally, this library tries to manage the tailwind CLI by itself and don't rely on externally installed versions of it.

Starting with version **2.7.0** TAILWIND_CLI_PATH can also point to an existing binary, in case you want to install it using some package manager or if you have installed `tailwindcss`` globally with `npm` along with some plugins you want to use.

!!! warning

If you use the new option from **2.7.0** but haven't installed a binary before running any of the management commands, these commands will treat the configured path as a directory and create it, if it is missing. Afterwards the official CLI will be downloaded to this path.

In case you want to use the new behaviour, it is highly recommended to also set the new setting `TAILWIND_CLI_AUTOMATIC_DOWNLOAD` to `False`.

`TAILWIND_CLI_AUTOMATIC_DOWNLOAD`
: **Default**: `True`

Enable or disable the automatic downloading of the official CLI to your machine.

`TAILWIND_CLI_SRC_CSS`
: **Default**: `None`
Expand Down
55 changes: 28 additions & 27 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "django-tailwind-cli"
version = "2.6.0"
version = "2.7.0"
description = "Django and Tailwind integration based on the prebuilt Tailwind CSS CLI."
authors = ["Oliver Andrich <[email protected]>"]
readme = "README.md"
Expand Down
4 changes: 2 additions & 2 deletions src/django_tailwind_cli/management/commands/tailwind.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,9 @@ def get_watch_cmd(self) -> List[str]:

def _download_cli_if_not_exists(self) -> None:
dest_file = self.config.get_full_cli_path()
download_url = self.config.get_download_url()

if not dest_file.exists():
if not dest_file.exists() and self.config.automatic_download:
download_url = self.config.get_download_url()
self.stdout.write(self.style.ERROR("Tailwind CSS CLI not found."))
self.stdout.write(
self.style.WARNING(f"Downloading Tailwind CSS CLI from '{download_url}'")
Expand Down
31 changes: 25 additions & 6 deletions src/django_tailwind_cli/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
the various paths.
"""

import os
import platform
from pathlib import Path
from typing import Tuple, Union
Expand All @@ -20,8 +21,15 @@ def tailwind_version(self) -> str:
return getattr(settings, "TAILWIND_CLI_VERSION", "3.3.5")

@property
def cli_path(self) -> Union[str, None]:
return getattr(settings, "TAILWIND_CLI_PATH", "~/.local/bin/")
def cli_path(self) -> Union[Path, None]:
p = getattr(settings, "TAILWIND_CLI_PATH", "~/.local/bin/")
if p is None:
return p
return Path(p).expanduser()

@property
def automatic_download(self) -> bool:
return bool(getattr(settings, "TAILWIND_CLI_AUTOMATIC_DOWNLOAD", True))

@property
def src_css(self) -> Union[str, None]:
Expand All @@ -44,13 +52,13 @@ def validate_settings(self) -> None:
def get_system_and_machine(self) -> Tuple[str, str]:
"""Get the system and machine name."""
system = platform.system().lower()
if system == "darwin": # pragma: no cover
if system == "darwin":
system = "macos"

machine = platform.machine().lower()
if machine in ["x86_64", "amd64"]: # pragma: no cover
if machine in ["x86_64", "amd64"]:
machine = "x64"
elif machine == "aarch64": # pragma: no cover
elif machine == "aarch64":
machine = "arm64"

return (system, machine)
Expand All @@ -66,13 +74,24 @@ def get_download_url(self) -> str:

def get_full_cli_path(self) -> Path:
"""Get path to the Tailwind CSS CLI."""

# If Tailwind CSS CLI path points to an existing executable use is.
if (
self.cli_path
and self.cli_path.exists()
and self.cli_path.is_file()
and os.access(self.cli_path, os.X_OK)
):
return self.cli_path

# Otherwise try to calculate the full cli path as usual.
system, machine = self.get_system_and_machine()
extension = ".exe" if system == "windows" else ""
executable_name = f"tailwindcss-{system}-{machine}-{self.tailwind_version}{extension}"
if self.cli_path is None:
return Path(settings.BASE_DIR) / executable_name
else:
return Path(self.cli_path).expanduser() / executable_name
return self.cli_path / executable_name

def get_full_src_css_path(self) -> Path:
"""Get path to the source css."""
Expand Down
12 changes: 11 additions & 1 deletion tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from pathlib import Path

import pytest
from django.conf import LazySettings
from pytest_mock import MockerFixture
Expand All @@ -12,7 +14,7 @@ def configure_settings(settings: LazySettings):

def test_default_config(config: Config):
assert "3.3.5" == config.tailwind_version
assert "~/.local/bin/" == config.cli_path
assert Path("~/.local/bin/").expanduser() == config.cli_path
assert config.src_css is None
assert "css/tailwind.css" == config.dist_css
assert "tailwind.config.js" == config.config_file
Expand Down Expand Up @@ -130,6 +132,14 @@ def test_get_full_cli_path(config: Config, mocker: MockerFixture):
assert str(config.get_full_cli_path()).endswith("tailwindcss-macos-arm64-3.3.5")


def test_get_full_cli_path_with_existing_executable(
config: Config, tmp_path: Path, settings: LazySettings
):
settings.TAILWIND_CLI_PATH = tmp_path / "tailwindcss.exe"
settings.TAILWIND_CLI_PATH.touch(mode=0o755, exist_ok=True)
assert config.get_full_cli_path() == tmp_path / "tailwindcss.exe"


def test_get_full_cli_path_with_changed_tailwind_cli_path(config: Config, settings: LazySettings):
settings.TAILWIND_CLI_PATH = "/opt/bin"
assert "/opt/bin/tailwindcss-" in str(config.get_full_cli_path())

0 comments on commit 0ca3907

Please sign in to comment.