mirror of
https://github.com/django-components/django-components.git
synced 2025-10-13 07:22:00 +00:00
docs: self-contained examples (#1436)
This commit is contained in:
parent
48adaf98f1
commit
9877cf30ed
71 changed files with 673 additions and 361 deletions
93
sampleproject/examples/utils.py
Normal file
93
sampleproject/examples/utils.py
Normal file
|
@ -0,0 +1,93 @@
|
|||
import importlib.util
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List, Set
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
# Keep track of what we've already discovered to make subsequent calls a noop
|
||||
_discovered_examples: Set[str] = set()
|
||||
|
||||
|
||||
def discover_example_modules() -> List[str]:
|
||||
"""
|
||||
Find and import `component.py` and `page.py` files from example directories
|
||||
`docs/examples/*/` (e.g. `docs/examples/form/component.py`).
|
||||
|
||||
These files will be importable from other modules like:
|
||||
|
||||
```python
|
||||
from examples.dynamic.form.component import Form
|
||||
# or
|
||||
from examples.dynamic.form.page import FormPage
|
||||
```
|
||||
|
||||
Components will be also registered with the ComponentRegistry, so they can be used
|
||||
in the templates via the `{% component %}` tag like:
|
||||
|
||||
```django
|
||||
{% component "form" / %}
|
||||
```
|
||||
|
||||
This function is idempotent - calling it multiple times will not re-import modules.
|
||||
"""
|
||||
# Skip if we've already discovered examples
|
||||
if _discovered_examples:
|
||||
return list(_discovered_examples)
|
||||
|
||||
docs_examples_dir: Path = settings.EXAMPLES_DIR
|
||||
if not docs_examples_dir.exists():
|
||||
raise FileNotFoundError(f"Docs examples directory not found: {docs_examples_dir}")
|
||||
|
||||
for example_dir in docs_examples_dir.iterdir():
|
||||
if not example_dir.is_dir():
|
||||
continue
|
||||
|
||||
example_name = example_dir.name
|
||||
|
||||
component_file = example_dir / "component.py"
|
||||
if component_file.exists():
|
||||
_import_module_file(component_file, example_name, "component")
|
||||
|
||||
page_file = example_dir / "page.py"
|
||||
if page_file.exists():
|
||||
_import_module_file(page_file, example_name, "page")
|
||||
|
||||
# Mark this example as discovered
|
||||
_discovered_examples.add(example_name)
|
||||
|
||||
return list(_discovered_examples)
|
||||
|
||||
|
||||
def _import_module_file(py_file: Path, example_name: str, module_type: str):
|
||||
"""
|
||||
Dynamically import a python file as a module.
|
||||
|
||||
This file will then be importable from other modules like:
|
||||
|
||||
```python
|
||||
from examples.dynamic.form.component import Form
|
||||
# or
|
||||
from examples.dynamic.form.page import FormPage
|
||||
```
|
||||
"""
|
||||
module_name = f"examples.dynamic.{example_name}.{module_type}"
|
||||
|
||||
# Skip if module is already imported
|
||||
if module_name in sys.modules:
|
||||
return
|
||||
|
||||
try:
|
||||
spec = importlib.util.spec_from_file_location(module_name, py_file)
|
||||
if not spec or not spec.loader:
|
||||
raise ValueError(f"Failed to load {module_type} {example_name}/{py_file.name}")
|
||||
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
# Add to sys.modules so the contents can be imported from other modules
|
||||
# via Python import system.
|
||||
sys.modules[module_name] = module
|
||||
spec.loader.exec_module(module)
|
||||
|
||||
print(f"Loaded example {module_type}: {example_name}/{py_file.name}")
|
||||
except Exception as e: # noqa: BLE001
|
||||
print(f"Failed to load {module_type} {example_name}/{py_file.name}: {e}")
|
Loading…
Add table
Add a link
Reference in a new issue