Generate content using DRF.
Project description
exdrf-gen
exdrf-gen orchestrates Jinja2 rendering and optional filesystem
tree generation for the exdrf domain model. One exdrf-gen CLI loads
all exdrf.plugins → exdrf_gen entry points (sibling exdrf-gen-*
packages) so commands such as al2pd, al2qt, pd2dare, and
openapi2rtk appear together after you install the matching plugins.
exdrf-gen is a Python library for generating text and project structure
from Jinja2 templates, built around the exdrf dataset model (resources,
fields, categories). It supplies a shared Jinja environment tuned for that
domain, optional composite file-tree builders that iterate over an
ExDataset, a small Click-based CLI scaffold, and a plugin hook so other
packages can extend templates and Jinja globals.
The PyPI distribution name is exdrf-gen; the import package is
exdrf_gen. Python 3.12.2+ is required.
Role in the exdrf stack
exdrfdescribes datasets, resources, and fields.exdrf-rcv— shared Python runtime for remote-controlled-view backends (types/helpers used withexdrf-gen-al2rcvoutput).exdrf-genrenders those descriptions (and arbitrary template context) through Jinja2, and can emit nested directories/files in one pass.- Sibling packages such as
exdrf-gen-al2pd(commandal2pd: PydanticXxx/XxxEx/XxxCreate/XxxEditfrom SQLAlchemy),exdrf-gen-al2qt,exdrf-gen-al2r(commandal2r: FastAPI route stubs;SCHEMAS-PKGmust matchal2pdoutput),exdrf-gen-al2rcv(commandal2rcv: remote-controlled-view path scaffolds),exdrf-gen-pd2dare(commandpd2dare: DARE TypeScript from PydanticExmodels), etc. register asexdrf.pluginsentry points namedexdrf_genand build on this layer for specific targets (e.g. pandas, Qt, web UI).
Installation
Install the core package (pulls exdrf, Click, Jinja2, dotenv loaders, and
inflect per pyproject.toml):
pip install exdrf-gen
If you use exdrf_gen.fs_support (composite generators), you also need
exdrf-al: that module imports exdrf_al.calc_q for related-model helpers.
Install it in the same environment when you rely on ResFile, TopDir, and
similar APIs.
Command-line interface
Installing exdrf-gen adds the exdrf-gen console script
([project.scripts] → exdrf_gen.__main__:main). It calls
plugin_support.load_plugins() (so sibling exdrf.plugins / exdrf_gen
packages register templates and commands), then runs the root Click group.
exdrf-gen --help
exdrf-gen --debug <subcommand> ...
Equivalent when the package is on PYTHONPATH:
python -m exdrf_gen --help
Subcommands (e.g. al2at, al2qt, al2r, al2rcv, pd2dare) come from plugins; install the
matching exdrf-gen-* distribution to enable them. Application repos may
also ship a plugin (e.g. resi_gen registers db2m, resi-al2at,
resi-al2qt) via the same exdrf.plugins / exdrf_gen entry point.
Package layout (exdrf_gen)
jinja_support
Central Jinja2 integration.
Loader: customjinja2.BaseLoaderthat resolves a template name in order: absolute file path; path under each configured search directory (with/as the path separator); or a Python module path of the formpackage.subpkg/template_name, which loadstemplate_nameortemplate_name.j2next to the imported package’s__file__.create_jinja_env(auto_reload=False): builds anEnvironmentwith that loader, auto-escaping, and a large set of globals, filters, and one custom test (None).- Module singleton
jinja_env: default environment fromcreate_jinja_env(). recreate_global_env(): replaces the globaljinja_envwith a fresh environment (e.g.auto_reload=Truefor development).
The environment is oriented toward documentation and UI-ish output: string
and number formatting, dates, inflect-backed pluralization, snake_case helpers,
to_json with optional attribute exclusion, list utilities (sorted variants,
equals / not_equals / contains filters), rounding modes, and symbolic
navigation URLs (exdrf://navigation/resource/...) plus CSS class names for
internal links and deleted records.
fs_support
Composite generators for walking an ExDataset and emitting files or
directories. Types are attrs-based (@define).
Base: sharedcreate_file,create_directory, andread_preserved. Rendering merges template context with preserved regions read from an existing output file: markersexdrf-keep-start <name>…exdrf-keep-enddefine blocks that are kept across regenerations and exposed to the template (by guard name).File/Dir: single file or directory;Dirrecurses into child components.FieldFile/FieldDir: one output per field; context includesfield_to_args(names, docs, types, ref flags, etc.).ResFile/ResDir: one output per resource (model); context includesresource_to_args(pascal/snake names, docs, primary fields, related-model lists fromexdrf_al, etc.).CategFile/CategDir: one output per category from the dataset.TopDir: root of a tree; injectsresources,categ_map,zero_categories(), andsorted_by_deps()into children.
Use these when your generator maps dataset topology to folder layout (e.g. one folder per model, one file per field).
cli_base
Minimal Click application (driven by exdrf_gen.__main__.main and the
exdrf-gen script):
cli: root group with--debug/--no-debug, loads.envviapython-dotenv, and storescreate_context_obj(debug)onctx.obj.create_context_obj: configures logging and returns a dict withjinja_envandinflect(exdrf.utils.inflect_e) for subcommands.
Downstream packages typically add subcommands to this group or reuse
create_context_obj.
template_emit
Helpers to write UTF-8 text files from Jinja templates for ExResource
and ExDataset category trees (used by exdrf-gen-pd2dare and
delegated to from resi_drf resource/dataset helpers).
plugin_support
load_plugins(): discoversimportlib.metadataentry points in groupexdrf.pluginsand loads each plugin whose name isexdrf_gen(sibling generator packages use this to register side effects on import).install_plugin(...): extends the sharedjinja_env—extra template search paths on the loader, and optional tests, globals, and filters (with warnings when names collide).
py_support
ModuleSymbol: a click.ParamType that resolves a string like
package.module:symbol via exdrf.py_support.get_symbol_from_path for CLI
arguments that refer to callables or objects.
utils
Reserved for small shared helpers; currently empty.
Version
exdrf_gen.__version__ is generated by setuptools-scm into
exdrf_gen/__version__.py at build time (fallback_version in
pyproject.toml).
Typical usage patterns
-
Render a template with the default environment:
from exdrf_gen.jinja_support import jinja_env text = jinja_env.get_template("path/or/module/template.j2").render(...)
-
Add template roots or filters from your package:
from exdrf_gen import plugin_support plugin_support.install_plugin( template_paths=["/my/templates"], extra_globals={"my_helper": my_helper}, )
-
Walk a dataset with
fs_support.TopDirand passenv=jinja_envanddset=...intogenerate(out_path, ...).
Writing a plugin package
Sibling generators follow the same pattern. Compare these installable packages
in the exdrf repo:
exdrf-gen-al2at(exdrf_gen_al2at) — attrs model output.exdrf-gen-al2pd(exdrf_gen_al2pd) — Pydantic-oriented output.exdrf-gen-al2qt(exdrf_gen_al2qt) — Qt-related output.exdrf-gen-al2rcv(exdrf_gen_al2rcv) — remote-controlled-view scaffolds.exdrf-rcv(exdrf_rcv) — RCV runtime library (consumed by generated code).
Each generator package does three things: register an entry point so load_plugins() can
import it, extend the shared Jinja environment on import, and attach
Click subcommands to the shared cli group.
1. Declare the exdrf.plugins entry point
In pyproject.toml, map the fixed entry point name exdrf_gen to the
module that should run when the plugin loads (usually your package’s
top-level __init__.py):
[project.entry-points.'exdrf.plugins']
exdrf_gen = 'exdrf_gen_mytarget'
plugin_support.load_plugins() loads every distribution that exposes this name
in the exdrf.plugins group. Use one such entry point per plugin package.
2. Register templates (and optional Jinja extensions) at import time
When the entry-point module is imported, call install_plugin so the
shared jinja_env can resolve your templates. The al2* packages only
add a template directory; you can also pass extra_globals,
extra_filters, or extra_tests.
Example:
import os
from exdrf_gen.cli_base import cli
from exdrf_gen.plugin_support import install_plugin
install_plugin(
template_paths=[
os.path.join(os.path.dirname(__file__), "my_templates"),
],
# optional:
# extra_globals={"my_helper": my_helper},
)
Your package should list exdrf-gen as a runtime dependency. Flows that
build from SQLAlchemy-backed datasets (like the al2* tools) typically also
need exdrf-al and click.
3. Add CLI commands to the shared cli group
Import cli from exdrf_gen.cli_base and register subcommands with
@cli.command(...). For rendering, use context.obj["jinja_env"] (and
other keys from create_context_obj, such as inflect).
Sketch matching al2at / al2qt (pass the environment into your own generator function):
import click
from exdrf_gen.cli_base import cli
@cli.command(name="mygen")
@click.pass_context
def mygen(context: click.Context, ...):
env = context.obj["jinja_env"]
...
The al2pd package registers al2pd the same way but keeps its command
implementation minimal; al2at and al2qt call into a creator module
and pass env=context.obj["jinja_env"] into the generator.
Loading plugins from an application
The exdrf-gen script and python -m exdrf_gen already run
load_plugins() before cli(). If you embed the CLI in another app,
do the same (or call main):
from exdrf_gen.__main__ import main
main()
Alternatively, call load_plugins() then cli() yourself:
from exdrf_gen import plugin_support
from exdrf_gen.cli_base import cli
plugin_support.load_plugins()
cli()
Development
Optional dev dependencies are listed under [project.optional-dependencies] dev in pyproject.toml (formatting, linting, tests, build tools). Versioning
uses setuptools_scm; see [tool.setuptools_scm] in the same file.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file exdrf_gen-0.1.15.tar.gz.
File metadata
- Download URL: exdrf_gen-0.1.15.tar.gz
- Upload date:
- Size: 21.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8f25a752e2e3c155d75aff76dc4e34a47f5af6845d8c7c53d2aff4b4ae3af0c7
|
|
| MD5 |
eedc9567bb2a851f4020c73a44e8f28d
|
|
| BLAKE2b-256 |
84fc509429eab83a4eac2716f626596ef947c8cc0bdac1c7ba2eb157c35c4450
|
File details
Details for the file exdrf_gen-0.1.15-py3-none-any.whl.
File metadata
- Download URL: exdrf_gen-0.1.15-py3-none-any.whl
- Upload date:
- Size: 18.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a909f1d7806e699c93af3216a609ab6c40d60da3f1dcd9a7aa43f0e7b9d8b393
|
|
| MD5 |
fe903d935cb46ce4bc4becd8f522461e
|
|
| BLAKE2b-256 |
4c8f497b7e90cc4fd568e8ce7115bd3e9d4ba169d93d4cf5bdb97b3609ada789
|