mirror of
https://github.com/django-components/django-components.git
synced 2025-09-22 13:42:27 +00:00
refactor: Fix path resolution relative to COMPONENTS.dirs + add CI test to ensure sampleproject works (#1075)
* refactor: Fix path resolution relative to COMPONENTS.dirs + add CI test to ensure sampleproject works * refactor: fix compat with Windows by explicitly using utf8 encoding to read component files * refactor: add missing components to tests * docs: update changelog * refactor: fix formatting
This commit is contained in:
parent
f07818fc7d
commit
9f68f0f1a1
6 changed files with 100 additions and 14 deletions
32
.github/workflows/tests.yml
vendored
32
.github/workflows/tests.yml
vendored
|
@ -67,3 +67,35 @@ jobs:
|
||||||
python -m pip install -e .
|
python -m pip install -e .
|
||||||
- name: Build documentation
|
- name: Build documentation
|
||||||
run: mkdocs build --verbose
|
run: mkdocs build --verbose
|
||||||
|
|
||||||
|
# Verify that the sample project works
|
||||||
|
test_sampleproject:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
python-version: ['3.13']
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Python ${{ matrix.python-version }}
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
cache: "pip"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
cd sampleproject
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
python -m pip install -r requirements.txt
|
||||||
|
# Install django-components locally
|
||||||
|
python -m pip install -e ..
|
||||||
|
- name: Check Django project
|
||||||
|
run: |
|
||||||
|
cd sampleproject
|
||||||
|
python manage.py check
|
||||||
|
python manage.py migrate --noinput
|
||||||
|
# Start the server, make request, and exit with error if it fails
|
||||||
|
python manage.py runserver & sleep 5
|
||||||
|
curl http://127.0.0.1:8000/ || exit 1
|
||||||
|
|
|
@ -56,6 +56,11 @@ where each class name or style property can be managed separately.
|
||||||
%}
|
%}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Fix
|
||||||
|
|
||||||
|
- Fix compat with Windows when reading component files ([#1074](https://github.com/django-components/django-components/issues/1074))
|
||||||
|
- Fix resolution of component media files edge case ([#1073](https://github.com/django-components/django-components/issues/1073))
|
||||||
|
|
||||||
## v0.134
|
## v0.134
|
||||||
|
|
||||||
#### Fix
|
#### Fix
|
||||||
|
|
|
@ -874,12 +874,16 @@ def resolve_media_file(
|
||||||
if is_url_path:
|
if is_url_path:
|
||||||
return [filepath], False
|
return [filepath], False
|
||||||
|
|
||||||
# The path may be a glob. So before we check if the file exists,
|
# The path may be a glob, which we need to resolve
|
||||||
# we need to resolve the glob.
|
|
||||||
if allow_glob and is_glob(filepath_abs_or_glob):
|
if allow_glob and is_glob(filepath_abs_or_glob):
|
||||||
|
# Since globs are matched against the files, then we know that these files exist.
|
||||||
matched_abs_filepaths = glob.glob(filepath_abs_or_glob)
|
matched_abs_filepaths = glob.glob(filepath_abs_or_glob)
|
||||||
else:
|
else:
|
||||||
|
# But if we were given non-glob file path, then we need to check if it exists.
|
||||||
|
if Path(filepath_abs_or_glob).exists():
|
||||||
matched_abs_filepaths = [filepath_abs_or_glob]
|
matched_abs_filepaths = [filepath_abs_or_glob]
|
||||||
|
else:
|
||||||
|
matched_abs_filepaths = []
|
||||||
|
|
||||||
# If there are no matches, return the original filepath
|
# If there are no matches, return the original filepath
|
||||||
if not matched_abs_filepaths:
|
if not matched_abs_filepaths:
|
||||||
|
@ -968,6 +972,8 @@ def _get_asset(
|
||||||
if full_path is None:
|
if full_path is None:
|
||||||
# NOTE: The short name, e.g. `js` or `css` is used in the error message for convenience
|
# NOTE: The short name, e.g. `js` or `css` is used in the error message for convenience
|
||||||
raise ValueError(f"Could not find {inlined_attr} file {asset_file}")
|
raise ValueError(f"Could not find {inlined_attr} file {asset_file}")
|
||||||
asset_content = Path(full_path).read_text()
|
|
||||||
|
# NOTE: Use explicit encoding for compat with Windows, see #1074
|
||||||
|
asset_content = Path(full_path).read_text(encoding="utf8")
|
||||||
|
|
||||||
return asset_content
|
return asset_content
|
||||||
|
|
|
@ -376,16 +376,6 @@ def djc_test(
|
||||||
param_names, values = parametrize
|
param_names, values = parametrize
|
||||||
ids = None
|
ids = None
|
||||||
|
|
||||||
for value in values:
|
|
||||||
# Validate that the first user-provided element in each value tuple is a dictionary,
|
|
||||||
# since it's meant to be used for overriding django-components settings
|
|
||||||
value_overrides = value[0]
|
|
||||||
if not isinstance(value_overrides, dict):
|
|
||||||
raise ValueError(
|
|
||||||
"The first element in each value tuple in `parametrize`"
|
|
||||||
f"must be a dictionary, but got {value_overrides}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# NOTE: Lazily import pytest, so user can still run tests with plain `unittest`
|
# NOTE: Lazily import pytest, so user can still run tests with plain `unittest`
|
||||||
# if they choose not to use parametrization.
|
# if they choose not to use parametrization.
|
||||||
import pytest
|
import pytest
|
||||||
|
|
|
@ -23,6 +23,35 @@ class GlobComponentRootDir(GlobComponent):
|
||||||
js = "glob/glob_*.js"
|
js = "glob/glob_*.js"
|
||||||
|
|
||||||
|
|
||||||
|
# The Media JS / CSS are NOT globs and are relative to the directory given in
|
||||||
|
# `COMPONENTS.dirs` and `COMPONENTS.app_dirs`. These should NOT be modified.
|
||||||
|
class NonGlobComponentRootDir(Component):
|
||||||
|
template = """
|
||||||
|
{% load component_tags %}
|
||||||
|
{% component_js_dependencies %}
|
||||||
|
{% component_css_dependencies %}
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Media:
|
||||||
|
css = "glob/glob_1.css"
|
||||||
|
js = "glob/glob_1.js"
|
||||||
|
|
||||||
|
|
||||||
|
# The Media JS / CSS are NOT globs. While relative to the directory given in
|
||||||
|
# `COMPONENTS.dirs` and `COMPONENTS.app_dirs`, these files do not exist.
|
||||||
|
# These paths should NOT be modified.
|
||||||
|
class NonGlobNonexistComponentRootDir(Component):
|
||||||
|
template = """
|
||||||
|
{% load component_tags %}
|
||||||
|
{% component_js_dependencies %}
|
||||||
|
{% component_css_dependencies %}
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Media:
|
||||||
|
css = "glob/glob_nonexist.css"
|
||||||
|
js = "glob/glob_nonexist.js"
|
||||||
|
|
||||||
|
|
||||||
# The Media JS / CSS are NOT globs, but URLs.
|
# The Media JS / CSS are NOT globs, but URLs.
|
||||||
class UrlComponent(Component):
|
class UrlComponent(Component):
|
||||||
template = """
|
template = """
|
||||||
|
|
|
@ -414,6 +414,30 @@ class TestComponentMedia:
|
||||||
assertInHTML('<script src="glob/glob_1.js"></script>', rendered)
|
assertInHTML('<script src="glob/glob_1.js"></script>', rendered)
|
||||||
assertInHTML('<script src="glob/glob_2.js"></script>', rendered)
|
assertInHTML('<script src="glob/glob_2.js"></script>', rendered)
|
||||||
|
|
||||||
|
@djc_test(
|
||||||
|
django_settings={
|
||||||
|
"INSTALLED_APPS": ("django_components", "tests"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
def test_non_globs_not_modified(self):
|
||||||
|
from tests.components.glob.glob import NonGlobComponentRootDir
|
||||||
|
rendered = NonGlobComponentRootDir.render()
|
||||||
|
|
||||||
|
assertInHTML('<link href="glob/glob_1.css" media="all" rel="stylesheet">', rendered)
|
||||||
|
assertInHTML('<script src="glob/glob_1.js"></script>', rendered)
|
||||||
|
|
||||||
|
@djc_test(
|
||||||
|
django_settings={
|
||||||
|
"INSTALLED_APPS": ("django_components", "tests"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
def test_non_globs_not_modified_nonexist(self):
|
||||||
|
from tests.components.glob.glob import NonGlobNonexistComponentRootDir
|
||||||
|
rendered = NonGlobNonexistComponentRootDir.render()
|
||||||
|
|
||||||
|
assertInHTML('<link href="glob/glob_nonexist.css" media="all" rel="stylesheet">', rendered)
|
||||||
|
assertInHTML('<script src="glob/glob_nonexist.js"></script>', rendered)
|
||||||
|
|
||||||
def test_glob_pattern_does_not_break_urls(self):
|
def test_glob_pattern_does_not_break_urls(self):
|
||||||
from tests.components.glob.glob import UrlComponent
|
from tests.components.glob.glob import UrlComponent
|
||||||
rendered = UrlComponent.render()
|
rendered = UrlComponent.render()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue