2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-27 11:06:44 +00:00

feat(backend): improve tag docs (#8960)

* add admindocs

* add tag export command

* add filter export

* switch to yaml

* upload meta info to artifacts

* format workflow file

* fix creation command

* keep all artifacts in schema repo

* fix namespace

* use one command for export

* include tags and filters in docs

* change default filename

* fix call

* fix itteration syntax

* clean up rendering

* fix formatting

* simple escape
This commit is contained in:
Matthias Mair 2025-01-27 23:42:13 +01:00 committed by GitHub
parent 16b03a7371
commit f7f6e27c6e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 216 additions and 9 deletions

View File

@ -170,9 +170,9 @@ jobs:
id: breaking_changes id: breaking_changes
uses: oasdiff/oasdiff-action/diff@1c611ffb1253a72924624aa4fb662e302b3565d3 # pin@main uses: oasdiff/oasdiff-action/diff@1c611ffb1253a72924624aa4fb662e302b3565d3 # pin@main
with: with:
base: 'api.yaml' base: "api.yaml"
revision: 'src/backend/InvenTree/schema.yml' revision: "src/backend/InvenTree/schema.yml"
format: 'html' format: "html"
- name: Echoing diff to step - name: Echoing diff to step
env: env:
DIFF: ${{ steps.breaking_changes.outputs.diff }} DIFF: ${{ steps.breaking_changes.outputs.diff }}
@ -194,6 +194,23 @@ jobs:
version="$(python3 .github/scripts/version_check.py only_version 2>&1)" version="$(python3 .github/scripts/version_check.py only_version 2>&1)"
echo "Version: $version" echo "Version: $version"
echo "version=$version" >> "$GITHUB_OUTPUT" echo "version=$version" >> "$GITHUB_OUTPUT"
- name: Extract settings / tags
run: invoke int.export-definitions
- name: Upload settings
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # pin@v4.6.0
with:
name: inventree_settings.json
path: src/backend/InvenTree/inventree_settings.json
- name: Upload tags
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # pin@v4.6.0
with:
name: inventree_tags.yml
path: src/backend/InvenTree/inventree_tags.yml
- name: Upload filters
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # pin@v4.6.0
with:
name: inventree_filters.yml
path: src/backend/InvenTree/inventree_filters.yml
schema-push: schema-push:
name: Push new schema name: Push new schema
@ -210,15 +227,20 @@ jobs:
repository: inventree/schema repository: inventree/schema
token: ${{ secrets.SCHEMA_PAT }} token: ${{ secrets.SCHEMA_PAT }}
persist-credentials: true persist-credentials: true
- name: Create artifact directory
run: mkdir -p artifact
- name: Download schema artifact - name: Download schema artifact
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # pin@v4.1.8 uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # pin@v4.1.8
with: with:
name: schema.yml path: artifact
- name: Move schema to correct location - name: Move files to correct location
run: | run: |
echo "Version: $version" echo "Version: $version"
mkdir export/${version} mkdir export/${version}
mv schema.yml export/${version}/api.yaml mv artifact/schema.yml export/${version}/api.yaml
mv artifact/inventree_settings.json export/${version}/inventree_settings.json
mv artifact/inventree_tags.yml export/${version}/inventree_tags.yml
mv artifact/inventree_filters.yml export/${version}/inventree_filters.yml
- uses: stefanzweifel/git-auto-commit-action@e348103e9026cc0eee72ae06630dbe30c8bf7a79 # pin@v5.1.0 - uses: stefanzweifel/git-auto-commit-action@e348103e9026cc0eee72ae06630dbe30c8bf7a79 # pin@v5.1.0
name: Commit schema changes name: Commit schema changes
with: with:
@ -518,7 +540,6 @@ jobs:
chmod +rw /home/runner/work/InvenTree/db.sqlite3 chmod +rw /home/runner/work/InvenTree/db.sqlite3
invoke migrate invoke migrate
platform_ui: platform_ui:
name: Tests - Platform UI name: Tests - Platform UI
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
@ -609,7 +630,7 @@ jobs:
zizmor: zizmor:
name: Security [Zizmor] name: Security [Zizmor]
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
needs: ['pre-commit', 'paths-filter'] needs: ["pre-commit", "paths-filter"]
if: needs.paths-filter.outputs.cicd == 'true' || needs.paths-filter.outputs.force == 'true' if: needs.paths-filter.outputs.cicd == 'true' || needs.paths-filter.outputs.force == 'true'
permissions: permissions:

View File

@ -512,3 +512,9 @@ A [Part Parameter](../part/parameter.md) has the following available attributes:
| Data | The *value* of the parameter (e.g. "123.4") | | Data | The *value* of the parameter (e.g. "123.4") |
| Units | The *units* of the parameter (e.g. "km") | | Units | The *units* of the parameter (e.g. "km") |
| Template | A reference to a [PartParameterTemplate](../part/parameter.md#parameter-templates) | | Template | A reference to a [PartParameterTemplate](../part/parameter.md#parameter-templates) |
## List of tags and filters
The following tags and filters are available.
{{ tags_and_filters() }}

View File

@ -31,6 +31,8 @@ for key in [
# Cached settings dict values # Cached settings dict values
global GLOBAL_SETTINGS global GLOBAL_SETTINGS
global USER_SETTINGS global USER_SETTINGS
global TAGS
global FILTERS
# Read in the InvenTree settings file # Read in the InvenTree settings file
here = os.path.dirname(__file__) here = os.path.dirname(__file__)
@ -42,6 +44,13 @@ with open(settings_file, encoding='utf-8') as sf:
GLOBAL_SETTINGS = settings['global'] GLOBAL_SETTINGS = settings['global']
USER_SETTINGS = settings['user'] USER_SETTINGS = settings['user']
# Tags
with open(os.path.join(here, 'inventree_tags.yml'), encoding='utf-8') as f:
TAGS = yaml.load(f, yaml.BaseLoader)
# Filters
with open(os.path.join(here, 'inventree_filters.yml'), encoding='utf-8') as f:
FILTERS = yaml.load(f, yaml.BaseLoader)
def get_repo_url(raw=False): def get_repo_url(raw=False):
"""Return the repository URL for the current project.""" """Return the repository URL for the current project."""
@ -303,3 +312,25 @@ def define_env(env):
setting = USER_SETTINGS[key] setting = USER_SETTINGS[key]
return rendersetting(key, setting) return rendersetting(key, setting)
@env.macro
def tags_and_filters():
"""Return a list of all tags and filters."""
global TAGS
global FILTERS
ret_data = ''
for ref in [['Tags', TAGS], ['Filters', FILTERS]]:
ret_data += f'### {ref[0]}\n\n| Namespace | Name | Description |\n| --- | --- | --- |\n'
for value in ref[1]:
title = (
value['title']
.replace('\n', ' ')
.replace('<', '&lt;')
.replace('>', '&gt;')
)
ret_data += f'| {value["library"]} | {value["name"]} | {title} |\n'
ret_data += '\n'
ret_data += '\n'
return ret_data

View File

@ -17,6 +17,6 @@ build:
- echo "Generating API schema file" - echo "Generating API schema file"
- pip install -U invoke - pip install -U invoke
- invoke migrate - invoke migrate
- invoke int.export-settings-definitions --filename docs/inventree_settings.json --overwrite - invoke int.export-definitions --basedir "docs"
- invoke dev.schema --filename docs/schema.yml --ignore-warnings - invoke dev.schema --filename docs/schema.yml --ignore-warnings
- python docs/extract_schema.py docs/schema.yml - python docs/extract_schema.py docs/schema.yml

View File

@ -0,0 +1,58 @@
"""Custom management command to export all filters.
This is used to generate a YAML file which contains all of the filters available in InvenTree.
"""
from django.contrib.admindocs import utils
from django.core.exceptions import ImproperlyConfigured
from django.core.management.base import BaseCommand
from django.template.engine import Engine
import yaml
class Command(BaseCommand):
"""Extract filter information, and export to a YAML file."""
def add_arguments(self, parser):
"""Add custom arguments for this command."""
parser.add_argument(
'filename', type=str, help='Output filename for filter definitions'
)
def handle(self, *args, **kwargs):
"""Export filter information to a YAML file."""
filters = discover_filters()
# Write
filename = kwargs.get('filename', 'inventree_filters.yml')
with open(filename, 'w', encoding='utf-8') as f:
yaml.dump(filters, f, indent=4)
print(f"Exported InvenTree filter definitions to '{filename}'")
def discover_filters():
"""Discover all available filters.
This function is a copy of a function from the Django 'admindocs' module in django.contrib.admindocs.views.TemplateFilterIndexView
"""
filters = []
try:
engine = Engine.get_default()
except ImproperlyConfigured:
# Non-trivial TEMPLATES settings aren't supported (#24125).
pass
else:
app_libs = sorted(engine.template_libraries.items())
builtin_libs = [('', lib) for lib in engine.template_builtins]
for module_name, library in builtin_libs + app_libs:
for filter_name, filter_func in library.filters.items():
title, body, metadata = utils.parse_docstring(filter_func.__doc__)
tag_library = module_name.split('.')[-1]
filters.append({
'name': filter_name,
'title': title,
'body': body,
'meta': metadata,
'library': tag_library,
})
return filters

View File

@ -0,0 +1,59 @@
"""Custom management command to export all tags.
This is used to generate a YAML file which contains all of the tags available in InvenTree.
"""
from django.contrib.admindocs import utils
from django.core.exceptions import ImproperlyConfigured
from django.core.management.base import BaseCommand
from django.template.engine import Engine
import yaml
class Command(BaseCommand):
"""Extract tag information, and export to a YAML file."""
def add_arguments(self, parser):
"""Add custom arguments for this command."""
parser.add_argument(
'filename', type=str, help='Output filename for tag definitions'
)
def handle(self, *args, **kwargs):
"""Export tag information to a YAML file."""
tags = discover_tags()
# Write
filename = kwargs.get('filename', 'inventree_tags.yml')
with open(filename, 'w', encoding='utf-8') as f:
yaml.dump(tags, f, indent=4)
print(f"Exported InvenTree tag definitions to '{filename}'")
def discover_tags():
"""Discover all available tags.
This function is a copy of a function from the Django 'admindocs' module in django.contrib.admindocs.views.TemplateTagIndexView
"""
tags = []
try:
engine = Engine.get_default()
except ImproperlyConfigured:
# Non-trivial TEMPLATES settings aren't supported (#24125).
pass
else:
app_libs = sorted(engine.template_libraries.items())
builtin_libs = [('', lib) for lib in engine.template_builtins]
for module_name, library in builtin_libs + app_libs:
for tag_name, tag_func in library.tags.items():
title, body, metadata = utils.parse_docstring(tag_func.__doc__)
tag_library = module_name.split('.')[-1]
tags.append({
'name': tag_name,
'title': title,
'body': body,
'meta': metadata,
'library': tag_library,
})
return tags

View File

@ -255,6 +255,7 @@ INVENTREE_ADMIN_URL = get_setting(
INSTALLED_APPS = [ INSTALLED_APPS = [
# Admin site integration # Admin site integration
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.admindocs',
# InvenTree apps # InvenTree apps
'build.apps.BuildConfig', 'build.apps.BuildConfig',
'common.apps.CommonConfig', 'common.apps.CommonConfig',

View File

@ -188,6 +188,7 @@ if settings.INVENTREE_ADMIN_ENABLED:
urlpatterns += [ urlpatterns += [
path(f'{admin_url}/error_log/', include('error_report.urls')), path(f'{admin_url}/error_log/', include('error_report.urls')),
path(f'{admin_url}/doc/', include('django.contrib.admindocs.urls')),
path(f'{admin_url}/', admin.site.urls, name='inventree-admin'), path(f'{admin_url}/', admin.site.urls, name='inventree-admin'),
] ]

View File

@ -33,6 +33,7 @@ djangorestframework-simplejwt[crypto] # JWT authentication
django-xforwardedfor-middleware # IP forwarding metadata django-xforwardedfor-middleware # IP forwarding metadata
dj-rest-auth==7.0.0 # Authentication API endpoints # FIXED 2024-12-22 due to https://github.com/inventree/InvenTree/issues/8707 dj-rest-auth==7.0.0 # Authentication API endpoints # FIXED 2024-12-22 due to https://github.com/inventree/InvenTree/issues/8707
dulwich # pure Python git integration dulwich # pure Python git integration
docutils # Documentation utilities for auto admin docs
drf-spectacular # DRF API documentation drf-spectacular # DRF API documentation
feedparser # RSS newsfeed parser feedparser # RSS newsfeed parser
gunicorn # Gunicorn web server gunicorn # Gunicorn web server

View File

@ -546,6 +546,10 @@ djangorestframework-simplejwt[crypto]==5.4.0 \
--hash=sha256:7aec953db9ed4163430c16d086eecb0f028f814ce6bba62b06c25919261e9077 \ --hash=sha256:7aec953db9ed4163430c16d086eecb0f028f814ce6bba62b06c25919261e9077 \
--hash=sha256:cccecce1a0e1a4a240fae80da73e5fc23055bababb8b67de88fa47cd36822320 --hash=sha256:cccecce1a0e1a4a240fae80da73e5fc23055bababb8b67de88fa47cd36822320
# via -r src/backend/requirements.in # via -r src/backend/requirements.in
docutils==0.21.2 \
--hash=sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f \
--hash=sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2
# via -r src/backend/requirements.in
drf-spectacular==0.28.0 \ drf-spectacular==0.28.0 \
--hash=sha256:2c778a47a40ab2f5078a7c42e82baba07397bb35b074ae4680721b2805943061 \ --hash=sha256:2c778a47a40ab2f5078a7c42e82baba07397bb35b074ae4680721b2805943061 \
--hash=sha256:856e7edf1056e49a4245e87a61e8da4baff46c83dbc25be1da2df77f354c7cb4 --hash=sha256:856e7edf1056e49a4245e87a61e8da4baff46c83dbc25be1da2df77f354c7cb4

View File

@ -1194,6 +1194,30 @@ def export_settings_definitions(c, filename='inventree_settings.json', overwrite
manage(c, f'export_settings_definitions {filename}', pty=True) manage(c, f'export_settings_definitions {filename}', pty=True)
@task(help={'basedir': 'Export to a base directory (default = False)'})
def export_definitions(c, basedir: str = ''):
"""Export various definitions."""
if basedir != '' and basedir.endswith('/') is False:
basedir += '/'
filenames = [
Path(basedir + 'inventree_settings.json').resolve(),
Path(basedir + 'inventree_tags.yml').resolve(),
Path(basedir + 'inventree_filters.yml').resolve(),
]
info('Exporting definitions...')
export_settings_definitions(c, overwrite=True, filename=filenames[0])
check_file_existence(filenames[1], overwrite=True)
manage(c, f'export_tags {filenames[1]}', pty=True)
check_file_existence(filenames[2], overwrite=True)
manage(c, f'export_filters {filenames[2]}', pty=True)
info('Exporting definitions complete')
@task(default=True) @task(default=True)
def version(c): def version(c):
"""Show the current version of InvenTree.""" """Show the current version of InvenTree."""
@ -1584,6 +1608,7 @@ internal = Collection(
clean_settings, clean_settings,
clear_generated, clear_generated,
export_settings_definitions, export_settings_definitions,
export_definitions,
frontend_build, frontend_build,
frontend_check, frontend_check,
frontend_compile, frontend_compile,