Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python3.12 error to find 'get_config' import from tailwind #212

Open
MarcelloDM opened this issue Oct 24, 2024 · 0 comments
Open

Python3.12 error to find 'get_config' import from tailwind #212

MarcelloDM opened this issue Oct 24, 2024 · 0 comments

Comments

@MarcelloDM
Copy link

MarcelloDM commented Oct 24, 2024

Hi to everyone,

I got an issue using python3.12 with tailwind and django-tailwind.

Description:

When I try to launch initialization

python3.12 manage.py tailwind init

It can't find the function 'get_config' from package. It seems it does not exist anymore as function.

Exit

Python3.11 >> OK
Python3.12 >> KO

Someone had the same issue?

Traceback (most recent call last):
  ...
    module = import_module("%s.management.commands.%s" % (app_name, name))
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3.12/importlib/__init__.py", line 90, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<frozen importlib._bootstrap>", line 1387, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 935, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 995, in exec_module
  File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed
  File "/home/<user>/.local/lib/python3.12/site-packages/tailwind/management/commands/tailwind.py", line 5, in <module>
    from tailwind import get_config
ImportError: cannot import name 'get_config' from 'tailwind' (/home/<user>/.local/lib/python3.12/site-packages/tailwind/__init__.py)

I noticed that the init file is changed in version 3.12

Version 3.12

"""Python wrapper for Tailwind CSS v3.1.5."""
import logging
import sys
import typing
from pathlib import Path
from subprocess import call, run

__all__ = [
    "init",
    "build",
    "watch",
]
__title__ = "tailwind"
__description__ = "Python wrapper for Tailwind CSS v3.1.5."
__author__ = "Seyeong Jeong"
__author_email__ = "[email protected]"
__license__ = "MIT"
__copyright__ = "Copyright 2022 Seyeong Jeong"
__version__ = "3.1.5b0"

_RELATIVE_TAIWIND_BIN = "bin/tailwindcss-linux-x64"
TAILWIND_BIN = str(Path(__file__).parent.resolve().joinpath(_RELATIVE_TAIWIND_BIN))
TAILWIND_VERSION = "v3.1.5"

logger = logging.getLogger(__name__)


class TailwindError(RuntimeError):
    """Top level Tailwind error."""


class InitError(TailwindError):
    """Initialization error."""


class ConfigFileExistsError(InitError):
    """Configuration file already exists error."""


class BuildError(TailwindError):
    """Build error."""


def _log_stderr(message: str) -> None:
    logger.warning(message)


def init(full: bool = False, postcss: bool = False) -> None:
    """Initialize Tailwind CSS environment."""
    options = ["init"]
    if full:
        options.append("--full")

    if postcss:
        options.append("--postcss")

    try:
        logger.debug("Invoking tailwind with %s options.", options)
        response = run(
            [TAILWIND_BIN] + options,
            capture_output=True,
            check=True,
        )
    except Exception as exc:
        raise InitError(f"Initi error occured with {options} options.") from exc

    if response.stderr:
        _log_stderr(response.stderr.decode())

    stdout = response.stdout.decode()
    if "already exists" in stdout:
        raise ConfigFileExistsError(stdout)


def _build_options(
    input: typing.Union[str, Path, None] = None,
    output: typing.Union[str, Path, None] = None,
    content: typing.Union[str, None] = None,
    postcss: typing.Union[bool, Path, str] = False,
    minify: bool = False,
    config: typing.Union[str, Path, None] = None,
    autoprefixer: bool = True,
) -> typing.List[str]:
    options = ["build"]

    if input is not None:
        options.append("--input")
        options.append(str(input))

    if output is not None:
        options.append("--output")
        options.append(str(output))

    if content is not None:
        options.append("--content")
        options.append(content)

    if postcss:
        options.append("--postcss")
        if isinstance(postcss, (Path, str)):
            options.append(str(postcss))

    if minify:
        options.append("--minify")

    if config is not None:
        options.append("--config")
        options.append(str(config))

    if not autoprefixer:
        options.append("--no-autoprefixer")

    return options


def build(
    input: typing.Union[str, Path, None] = None,
    output: typing.Union[str, Path, None] = None,
    content: typing.Union[str, None] = None,
    postcss: typing.Union[bool, Path, str] = False,
    minify: bool = False,
    config: typing.Union[str, Path, None] = None,
    autoprefixer: bool = True,
) -> typing.Union[str, None]:
    """Build Tailwind CSS."""
    options = _build_options(
        input=input,
        output=output,
        content=content,
        postcss=postcss,
        minify=minify,
        config=config,
        autoprefixer=autoprefixer,
    )
    try:
        logger.debug("Invoking tailwind with %s options.", options)
        response = run(
            [TAILWIND_BIN] + options,
            capture_output=True,
            check=True,
        )
    except Exception as exc:
        raise BuildError(f"Build error occured with {options}.") from exc

    if response.stderr:
        _log_stderr(response.stderr.decode())

    if output is None:
        return response.stdout.decode()

    return None


def watch(
    input: typing.Union[str, Path, None] = None,
    output: typing.Union[str, Path, None] = None,
    content: typing.Union[str, None] = None,
    postcss: typing.Union[bool, Path, str] = False,
    minify: bool = False,
    config: typing.Union[str, Path, None] = None,
    autoprefixer: bool = True,
    poll: bool = False,
) -> None:
    """Watch Tailwind CSS."""
    options = _build_options(
        input=input,
        output=output,
        content=content,
        postcss=postcss,
        minify=minify,
        config=config,
        autoprefixer=autoprefixer,
    )
    if poll:
        options.append("--poll")
    else:
        options.append("--watch")

    try:
        logger.debug("Invoking tailwind with %s options.", options)
        run(
            [TAILWIND_BIN] + options,
            check=True,
        )
    except Exception as exc:
        raise BuildError(f"Build error occured with {options}.") from exc


def main() -> int:
    """Invoke Tailwind CSS directly with arugments."""
    argv = sys.argv[1:]
    logger.debug("Invoking tailwind with %s options.", argv)
    return call([TAILWIND_BIN] + argv)


if __name__ == "__main__":
    sys.exit(main())

Version 3.11

from django.conf import settings


def get_config(setting_name):
    return {
        "NPM_BIN_PATH": getattr(settings, "NPM_BIN_PATH", "npm"),
        # 'TAILWIND_DEV_MODE' is deprecated. Leaving it here
        # to support legacy browser-sync based configs.
        "TAILWIND_DEV_MODE": getattr(settings, "TAILWIND_DEV_MODE", False),
        "TAILWIND_CSS_PATH": getattr(settings, "TAILWIND_CSS_PATH", "css/dist/s>
        "TAILWIND_APP_NAME": getattr(settings, "TAILWIND_APP_NAME", None),
    }[setting_name]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant