Skip to content

Commit

Permalink
check_loader_instance checks every app
Browse files Browse the repository at this point in the history
  • Loading branch information
Niicck committed Oct 19, 2023
1 parent 030bac1 commit 9967dbf
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 37 deletions.
37 changes: 9 additions & 28 deletions django_vite/apps.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,21 @@
from contextlib import suppress

from django.apps import AppConfig
from django.core.checks import Warning, register
from django.core import checks

from .core.exceptions import DjangoViteManifestError
from .templatetags.django_vite import DjangoViteAssetLoader
from django_vite.core.asset_loader import DjangoViteAssetLoader


class DjangoViteAppConfig(AppConfig):
name = "django_vite"
verbose_name = "Django Vite"

def ready(self) -> None:
with suppress(DjangoViteManifestError):
# Create Loader instance at startup to prevent threading problems,
# but do not crash while doing so.
DjangoViteAssetLoader.instance()
# Make Loader instance at startup to prevent threading problems
# but do not crash while doing so.
DjangoViteAssetLoader.instance()

# Check for potential errors with loading manifests in DjangoViteConfigs.
checks.register(check_loader_instance, checks.Tags.staticfiles)

@register
def check_loader_instance(**kwargs):
"""Raise a warning during startup when instance retrieval fails."""

try:
# Make Loader instance at startup to prevent threading problems
DjangoViteAssetLoader.instance()
return []
except DjangoViteManifestError as exception:
return [
Warning(
exception,
id="DJANGO_VITE",
hint=(
"Make sure you have generated a manifest file, "
"and that the DJANGO_VITE_MANIFEST_PATH points "
"to the correct location."
),
)
]
def check_loader_instance(**kwargs):
return DjangoViteAssetLoader.instance().check(**kwargs)
62 changes: 53 additions & 9 deletions django_vite/core/asset_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from django.apps import apps
from django.conf import settings
from django.core.checks import Warning

from django_vite.core.exceptions import (
DjangoViteManifestError,
Expand Down Expand Up @@ -71,8 +72,11 @@ class ManifestClient:
get(path: str) -- return the ManifestEntry for the given path.
"""

def __init__(self, config: DjangoViteConfig) -> None:
def __init__(
self, config: DjangoViteConfig, app_name: str = DEFAULT_APP_NAME
) -> None:
self._config = config
self.app_name = app_name

self.dev_mode = config.dev_mode
self.manifest_path = self._clean_manifest_path()
Expand All @@ -81,8 +85,14 @@ def __init__(self, config: DjangoViteConfig) -> None:
self._entries: Dict[str, ManifestEntry] = {}
self.legacy_polyfills_entry: Optional[ManifestEntry] = None

# Don't crash if there is an error while parsing manifest.json.
# Running DjangoViteAssetLoader.instance().checks() on startup will log any
# errors.
if not self.dev_mode:
self._entries, self.legacy_polyfills_entry = self._parse_manifest()
try:
self._entries, self.legacy_polyfills_entry = self._parse_manifest()
except DjangoViteManifestError:
pass

def _clean_manifest_path(self) -> Path:
"""
Expand All @@ -105,11 +115,30 @@ def _clean_manifest_path(self) -> Path:
else:
return initial_manifest_path

def check(self) -> List[Warning]:
"""Check that manifest files are valid when dev_mode=False."""
try:
if not self.dev_mode:
self._parse_manifest()
return []
except DjangoViteManifestError as exception:
return [
Warning(
exception,
id="django_vite.W001",
hint=(
f"Make sure you have generated a manifest file, "
f'and that DJANGO_VITE["{self.app_name}"]["manifest_path"] '
"points to the correct location."
),
)
]

class ParsedManifestOutput(NamedTuple):
# all entries within the manifest
entries: Dict[str, ManifestEntry]
entries: Dict[str, ManifestEntry] = {}
# The manifest entry for legacy polyfills, if it exists within the manifest
legacy_polyfills_entry: Optional[ManifestEntry]
legacy_polyfills_entry: Optional[ManifestEntry] = None

def _parse_manifest(self) -> ParsedManifestOutput:
"""
Expand All @@ -125,6 +154,9 @@ def _parse_manifest(self) -> ParsedManifestOutput:
DjangoViteManifestError: if cannot load the file or JSON in file is
malformed.
"""
if self.dev_mode:
return self.ParsedManifestOutput()

entries: Dict[str, ManifestEntry] = {}
legacy_polyfills_entry: Optional[ManifestEntry] = None

Expand All @@ -143,7 +175,7 @@ def _parse_manifest(self) -> ParsedManifestOutput:

except Exception as error:
raise DjangoViteManifestError(
f"Cannot read Vite manifest file at "
f"Cannot read Vite manifest file for app {self.app_name} at "
f"{self.manifest_path} : {str(error)}"
) from error

Expand All @@ -160,7 +192,8 @@ def get(self, path: str) -> ManifestEntry:
"""
if path not in self._entries:
raise DjangoViteAssetNotFoundError(
f"Cannot find {path} in Vite manifest " f"at {self.manifest_path}"
f"Cannot find {path} for app={self.app_name} in Vite manifest at "
f"{self.manifest_path}"
)

return self._entries[path]
Expand All @@ -172,8 +205,11 @@ class DjangoViteAppClient:
DjangoViteConfig provides the arguments for the client.
"""

def __init__(self, config: DjangoViteConfig) -> None:
def __init__(
self, config: DjangoViteConfig, app_name: str = DEFAULT_APP_NAME
) -> None:
self._config = config
self.app_name = app_name

self.dev_mode = config.dev_mode
self.dev_server_protocol = config.dev_server_protocol
Expand All @@ -183,7 +219,7 @@ def __init__(self, config: DjangoViteConfig) -> None:
self.ws_client_url = config.ws_client_url
self.react_refresh_url = config.react_refresh_url

self.manifest = ManifestClient(config)
self.manifest = ManifestClient(config, app_name)

def _get_dev_server_url(
self,
Expand Down Expand Up @@ -622,6 +658,14 @@ def instance(cls):

return cls._instance

def check(self, **kwargs) -> List[Warning]:
"""Check that manifest files are valid for apps with dev_mode=False."""
errors: List[Warning] = []
for app_client in self._apps.values():
manifest_warnings = app_client.manifest.check()
errors.extend(manifest_warnings)
return errors

@classmethod
def _apply_django_vite_settings(cls):
"""
Expand All @@ -637,7 +681,7 @@ def _apply_django_vite_settings(cls):
for app_name, config in django_vite_settings.items():
if not isinstance(config, DjangoViteConfig):
config = DjangoViteConfig(**config)
cls._instance._apps[app_name] = DjangoViteAppClient(config)
cls._instance._apps[app_name] = DjangoViteAppClient(config, app_name)

@classmethod
def _apply_legacy_django_vite_settings(cls):
Expand Down

0 comments on commit 9967dbf

Please sign in to comment.