ya-tagscript 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ya_tagscript-1.0.0/.github/workflows/black.yml +22 -0
- ya_tagscript-1.0.0/.github/workflows/publish.yml +121 -0
- ya_tagscript-1.0.0/.github/workflows/test.yml +32 -0
- ya_tagscript-1.0.0/.gitignore +27 -0
- ya_tagscript-1.0.0/.pre-commit-config.yaml +33 -0
- ya_tagscript-1.0.0/.python-version +1 -0
- ya_tagscript-1.0.0/.readthedocs.yaml +14 -0
- ya_tagscript-1.0.0/LICENSE.md +1 -0
- ya_tagscript-1.0.0/PKG-INFO +104 -0
- ya_tagscript-1.0.0/README.md +82 -0
- ya_tagscript-1.0.0/docs/Makefile +23 -0
- ya_tagscript-1.0.0/docs/_ext/glossary_backlink_checker.py +173 -0
- ya_tagscript-1.0.0/docs/_ext/styled_list_directive.py +33 -0
- ya_tagscript-1.0.0/docs/adapters.rst +67 -0
- ya_tagscript-1.0.0/docs/blocks.rst +151 -0
- ya_tagscript-1.0.0/docs/code_examples/adapters/int_adapter_example.py +15 -0
- ya_tagscript-1.0.0/docs/code_examples/adapters/member_adapter_example.py +32 -0
- ya_tagscript-1.0.0/docs/code_examples/nested_blocks_example.py +55 -0
- ya_tagscript-1.0.0/docs/code_examples/quickstart_example.py +51 -0
- ya_tagscript-1.0.0/docs/conf.py +93 -0
- ya_tagscript-1.0.0/docs/credits.rst +43 -0
- ya_tagscript-1.0.0/docs/exceptions.rst +7 -0
- ya_tagscript-1.0.0/docs/glossary.rst +124 -0
- ya_tagscript-1.0.0/docs/index.rst +112 -0
- ya_tagscript-1.0.0/docs/interfaces.rst +37 -0
- ya_tagscript-1.0.0/docs/interpreter.rst +21 -0
- ya_tagscript-1.0.0/docs/intro.rst +110 -0
- ya_tagscript-1.0.0/docs/make.bat +35 -0
- ya_tagscript-1.0.0/docs/numeric_parser.rst +14 -0
- ya_tagscript-1.0.0/docs/quickstart.rst +7 -0
- ya_tagscript-1.0.0/docs/requirements.txt +5 -0
- ya_tagscript-1.0.0/pyproject.toml +69 -0
- ya_tagscript-1.0.0/src/__init__.py +0 -0
- ya_tagscript-1.0.0/src/ya_tagscript/__init__.py +6 -0
- ya_tagscript-1.0.0/src/ya_tagscript/adapters/__init__.py +21 -0
- ya_tagscript-1.0.0/src/ya_tagscript/adapters/discord_adapters/__init__.py +11 -0
- ya_tagscript-1.0.0/src/ya_tagscript/adapters/discord_adapters/attribute_adapter.py +62 -0
- ya_tagscript-1.0.0/src/ya_tagscript/adapters/discord_adapters/channel_adapter.py +54 -0
- ya_tagscript-1.0.0/src/ya_tagscript/adapters/discord_adapters/guild_adapter.py +63 -0
- ya_tagscript-1.0.0/src/ya_tagscript/adapters/discord_adapters/member_adapter.py +60 -0
- ya_tagscript-1.0.0/src/ya_tagscript/adapters/function_adapter.py +24 -0
- ya_tagscript-1.0.0/src/ya_tagscript/adapters/int_adapter.py +17 -0
- ya_tagscript-1.0.0/src/ya_tagscript/adapters/object_adapter.py +49 -0
- ya_tagscript-1.0.0/src/ya_tagscript/adapters/string_adapter.py +93 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/__init__.py +70 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/actions/__init__.py +15 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/actions/command_block.py +66 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/actions/delete_block.py +68 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/actions/override_block.py +81 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/actions/react_block.py +106 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/actions/redirect_block.py +79 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/actions/silence_block.py +53 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/conditional/__init__.py +11 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/conditional/all_block.py +95 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/conditional/any_block.py +95 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/conditional/if_block.py +114 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/conditional/python_block.py +81 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/discord/__init__.py +7 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/discord/cooldown_block.py +122 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/discord/embed_block.py +358 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/flow/__init__.py +9 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/flow/break_block.py +54 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/flow/shortcutredirect_block.py +64 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/flow/stop_block.py +56 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/limiters/__init__.py +7 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/limiters/blacklist_block.py +84 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/limiters/require_block.py +86 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/lists/__init__.py +7 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/lists/cycle_block.py +65 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/lists/list_block.py +63 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/math/__init__.py +7 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/math/math_block.py +350 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/math/ordinal_block.py +79 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/meta/__init__.py +7 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/meta/comment_block.py +47 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/meta/debug_block.py +140 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/rng/__init__.py +9 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/rng/fiftyfifty_block.py +36 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/rng/random_block.py +96 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/rng/range_block.py +95 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/strings/__init__.py +15 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/strings/case_block.py +55 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/strings/join_block.py +47 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/strings/replace_block.py +64 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/strings/substring_block.py +78 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/strings/urldecode_block.py +54 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/strings/urlencode_block.py +52 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/time/__init__.py +7 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/time/strf_block.py +102 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/time/timedelta_block.py +171 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/variables/__init__.py +9 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/variables/assign_block.py +48 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/variables/loose_variable_getter_block.py +80 -0
- ya_tagscript-1.0.0/src/ya_tagscript/blocks/variables/strict_variable_getter_block.py +80 -0
- ya_tagscript-1.0.0/src/ya_tagscript/exceptions/__init__.py +19 -0
- ya_tagscript-1.0.0/src/ya_tagscript/exceptions/exceptions.py +111 -0
- ya_tagscript-1.0.0/src/ya_tagscript/interfaces/__init__.py +12 -0
- ya_tagscript-1.0.0/src/ya_tagscript/interfaces/adapterabc.py +28 -0
- ya_tagscript-1.0.0/src/ya_tagscript/interfaces/blockabc.py +151 -0
- ya_tagscript-1.0.0/src/ya_tagscript/interfaces/interpreterabc.py +107 -0
- ya_tagscript-1.0.0/src/ya_tagscript/interfaces/nodeabc.py +124 -0
- ya_tagscript-1.0.0/src/ya_tagscript/interpreter/__init__.py +11 -0
- ya_tagscript-1.0.0/src/ya_tagscript/interpreter/context.py +47 -0
- ya_tagscript-1.0.0/src/ya_tagscript/interpreter/interpreter.py +196 -0
- ya_tagscript-1.0.0/src/ya_tagscript/interpreter/node.py +75 -0
- ya_tagscript-1.0.0/src/ya_tagscript/interpreter/parse_state.py +96 -0
- ya_tagscript-1.0.0/src/ya_tagscript/interpreter/response.py +75 -0
- ya_tagscript-1.0.0/src/ya_tagscript/interpreter/ts_parser.py +364 -0
- ya_tagscript-1.0.0/src/ya_tagscript/py.typed +0 -0
- ya_tagscript-1.0.0/src/ya_tagscript/util/__init__.py +9 -0
- ya_tagscript-1.0.0/src/ya_tagscript/util/conditionals.py +83 -0
- ya_tagscript-1.0.0/src/ya_tagscript/util/escaping.py +13 -0
- ya_tagscript-1.0.0/src/ya_tagscript/util/splitter.py +40 -0
- ya_tagscript-1.0.0/tests/.coveragerc +10 -0
- ya_tagscript-1.0.0/tests/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/adapters/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/adapters/discord_adapters/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/adapters/discord_adapters/test_attribute_adapter.py +104 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/adapters/discord_adapters/test_channel_adapter.py +131 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/adapters/discord_adapters/test_guild_adapter.py +234 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/adapters/discord_adapters/test_member_adapter.py +247 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/adapters/test_function_adapter.py +47 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/adapters/test_int_adapter.py +41 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/adapters/test_object_adapter.py +103 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/adapters/test_string_adapter.py +194 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/actions/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/actions/test_command_block.py +105 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/actions/test_delete_block.py +73 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/actions/test_override_block.py +100 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/actions/test_react_block.py +301 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/actions/test_redirect_block.py +104 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/actions/test_silence_block.py +25 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/conditional/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/conditional/test_all_block.py +228 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/conditional/test_any_block.py +234 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/conditional/test_if_block.py +297 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/conditional/test_python_block.py +174 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/discord/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/discord/test_cooldown_block.py +286 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/discord/test_embed_block.py +2129 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/flow/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/flow/test_break_block.py +105 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/flow/test_shortcutredirect_block.py +57 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/flow/test_stop_block.py +151 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/limiters/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/limiters/test_blacklist_block.py +156 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/limiters/test_require_block.py +156 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/lists/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/lists/test_cycle_block.py +152 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/lists/test_list_block.py +151 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/math/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/math/test_math_block.py +1350 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/math/test_ordinal_block.py +227 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/meta/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/meta/test_comment_block.py +60 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/meta/test_debug_block.py +304 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/rng/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/rng/test_fiftyfifty_block.py +70 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/rng/test_random_block.py +193 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/rng/test_range_block.py +336 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/strings/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/strings/test_case_block.py +121 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/strings/test_join_block.py +82 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/strings/test_replace_block.py +166 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/strings/test_substring_block.py +222 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/strings/test_urldecode_block.py +79 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/strings/test_urlencode_block.py +75 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/time/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/time/test_strf_block.py +236 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/time/test_timedelta_block.py +598 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/variables/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/variables/test_assign_block.py +103 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/variables/test_loose_variable_getter_block.py +99 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/blocks/variables/test_strict_variable_getter_block.py +100 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/interpreter/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/interpreter/test_interpreter.py +212 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/interpreter/test_node.py +72 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/interpreter/test_parse_state.py +56 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/interpreter/test_ts_parser.py +263 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/util/__init__.py +0 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/util/test_conditionals.py +213 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/util/test_escaping.py +29 -0
- ya_tagscript-1.0.0/tests/ya_tagscript/util/test_splitter.py +46 -0
- ya_tagscript-1.0.0/uv.lock +1745 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: Lint
|
|
2
|
+
|
|
3
|
+
on: [ push, pull_request ]
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
lint:
|
|
7
|
+
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
strategy:
|
|
10
|
+
fail-fast: false
|
|
11
|
+
matrix:
|
|
12
|
+
python-version: [ "3.11", "3.12", "3.13" ]
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Lint with black
|
|
18
|
+
uses: psf/black@stable
|
|
19
|
+
with:
|
|
20
|
+
options: '--check --diff'
|
|
21
|
+
src: '.'
|
|
22
|
+
version: '~= 25.0'
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
name: Publish Python 🐍 distribution 📦 to PyPI and TestPyPI
|
|
2
|
+
|
|
3
|
+
on: push
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
build:
|
|
7
|
+
name: Build distribution 📦
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
|
|
13
|
+
- name: Install uv
|
|
14
|
+
uses: astral-sh/setup-uv@v5
|
|
15
|
+
|
|
16
|
+
- name: Set up Python
|
|
17
|
+
uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version-file: ".python-version"
|
|
20
|
+
|
|
21
|
+
- name: Install the project
|
|
22
|
+
run: uv sync --all-extras --dev
|
|
23
|
+
|
|
24
|
+
- name: Build a binary wheel and a source tarball
|
|
25
|
+
run: uv build
|
|
26
|
+
|
|
27
|
+
- name: Store the distribution packages
|
|
28
|
+
uses: actions/upload-artifact@v4
|
|
29
|
+
with:
|
|
30
|
+
name: python-package-distributions
|
|
31
|
+
path: dist/
|
|
32
|
+
|
|
33
|
+
publish-to-pypi:
|
|
34
|
+
name: Publish Python 🐍 distribution 📦 to PyPI
|
|
35
|
+
if: startsWith(github.ref, 'refs/tags/') # only publish to PyPI on tag pushes
|
|
36
|
+
needs:
|
|
37
|
+
- build
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
environment:
|
|
40
|
+
name: pypi
|
|
41
|
+
url: https://pypi.org/p/ya_tagscript
|
|
42
|
+
permissions:
|
|
43
|
+
id-token: write
|
|
44
|
+
|
|
45
|
+
steps:
|
|
46
|
+
- name: Download all the dists
|
|
47
|
+
uses: actions/download-artifact@v4
|
|
48
|
+
with:
|
|
49
|
+
name: python-package-distributions
|
|
50
|
+
path: dist/
|
|
51
|
+
|
|
52
|
+
- name: Publish distribution 📦 to PyPI
|
|
53
|
+
uses: pypa/gh-action-pypi-publish@76f52bc884231f62b9a034ebfe128415bbaabdfc
|
|
54
|
+
|
|
55
|
+
github-release:
|
|
56
|
+
name: >-
|
|
57
|
+
Sign the Python 🐍 distribution 📦 with Sigstore
|
|
58
|
+
and upload them to GitHub Release
|
|
59
|
+
needs:
|
|
60
|
+
- publish-to-pypi
|
|
61
|
+
runs-on: ubuntu-latest
|
|
62
|
+
|
|
63
|
+
permissions:
|
|
64
|
+
contents: write
|
|
65
|
+
id-token: write
|
|
66
|
+
|
|
67
|
+
steps:
|
|
68
|
+
- name: Download all the dists
|
|
69
|
+
uses: actions/download-artifact@v4
|
|
70
|
+
with:
|
|
71
|
+
name: python-package-distributions
|
|
72
|
+
path: dist/
|
|
73
|
+
|
|
74
|
+
- name: Sign the dists with Sigstore
|
|
75
|
+
uses: sigstore/gh-action-sigstore-python@f514d46b907ebcd5bedc05145c03b69c1edd8b46
|
|
76
|
+
with:
|
|
77
|
+
inputs: >-
|
|
78
|
+
./dist/*.tar.gz
|
|
79
|
+
./dist/*.whl
|
|
80
|
+
|
|
81
|
+
- name: Create GitHub Release
|
|
82
|
+
env:
|
|
83
|
+
GITHUB_TOKEN: ${{ github.token }}
|
|
84
|
+
run: >-
|
|
85
|
+
gh release create
|
|
86
|
+
"$GITHUB_REF_NAME"
|
|
87
|
+
--repo "$GITHUB_REPOSITORY"
|
|
88
|
+
--notes ""
|
|
89
|
+
|
|
90
|
+
- name: Upload artifact signatures to GitHub Release
|
|
91
|
+
env:
|
|
92
|
+
GITHUB_TOKEN: ${{ github.token }}
|
|
93
|
+
run: >-
|
|
94
|
+
gh release upload
|
|
95
|
+
"$GITHUB_REF_NAME" dist/**
|
|
96
|
+
--repo "$GITHUB_REPOSITORY"
|
|
97
|
+
|
|
98
|
+
publish-to-testpypi:
|
|
99
|
+
name: Publish Python 🐍 distribution 📦 to TestPyPI
|
|
100
|
+
needs:
|
|
101
|
+
- build
|
|
102
|
+
runs-on: ubuntu-latest
|
|
103
|
+
|
|
104
|
+
environment:
|
|
105
|
+
name: testpypi
|
|
106
|
+
url: https://test.pypi.org/p/ya_tagscript
|
|
107
|
+
|
|
108
|
+
permissions:
|
|
109
|
+
id-token: write
|
|
110
|
+
|
|
111
|
+
steps:
|
|
112
|
+
- name: Download all the dists
|
|
113
|
+
uses: actions/download-artifact@v4
|
|
114
|
+
with:
|
|
115
|
+
name: python-package-distributions
|
|
116
|
+
path: dist/
|
|
117
|
+
|
|
118
|
+
- name: Publish distribution 📦 to TestPyPI
|
|
119
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
120
|
+
with:
|
|
121
|
+
repository-url: https://test.pypi.org/legacy/
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Test
|
|
2
|
+
|
|
3
|
+
on: [ push, pull_request ]
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
test:
|
|
7
|
+
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
strategy:
|
|
10
|
+
fail-fast: false
|
|
11
|
+
matrix:
|
|
12
|
+
python-version: [ "3.11", "3.12", "3.13" ]
|
|
13
|
+
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@v5
|
|
19
|
+
with:
|
|
20
|
+
enable-cache: true
|
|
21
|
+
cache-dependency-glob: "uv.lock"
|
|
22
|
+
|
|
23
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
24
|
+
uses: actions/setup-python@v5
|
|
25
|
+
with:
|
|
26
|
+
python-version: ${{ matrix.python-version }}
|
|
27
|
+
|
|
28
|
+
- name: Install dependencies
|
|
29
|
+
run: uv sync --all-extras --dev
|
|
30
|
+
|
|
31
|
+
- name: Run tests
|
|
32
|
+
run: uv run pytest tests
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
|
|
3
|
+
# Distribution / packaging
|
|
4
|
+
dist/
|
|
5
|
+
|
|
6
|
+
# Unit test / coverage reports
|
|
7
|
+
htmlcov/
|
|
8
|
+
.coverage
|
|
9
|
+
.coverage.*
|
|
10
|
+
coverage.xml
|
|
11
|
+
|
|
12
|
+
# Sphinx documentation
|
|
13
|
+
docs/_build/
|
|
14
|
+
# Environments
|
|
15
|
+
.env
|
|
16
|
+
.venv
|
|
17
|
+
env/
|
|
18
|
+
venv/
|
|
19
|
+
ENV/
|
|
20
|
+
env.bak/
|
|
21
|
+
venv.bak/
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
.DS_Store
|
|
25
|
+
|
|
26
|
+
.idea/
|
|
27
|
+
.local/
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
default_language_version:
|
|
2
|
+
python: python3.11
|
|
3
|
+
fail_fast: false
|
|
4
|
+
repos:
|
|
5
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
6
|
+
rev: v5.0.0
|
|
7
|
+
hooks:
|
|
8
|
+
- id: check-toml
|
|
9
|
+
- id: check-yaml
|
|
10
|
+
- id: end-of-file-fixer
|
|
11
|
+
- id: trailing-whitespace
|
|
12
|
+
- id: check-builtin-literals
|
|
13
|
+
- id: check-ast
|
|
14
|
+
- id: check-json
|
|
15
|
+
- id: detect-private-key
|
|
16
|
+
- id: requirements-txt-fixer
|
|
17
|
+
- id: trailing-whitespace
|
|
18
|
+
args: [ --markdown-linebreak-ext=md ]
|
|
19
|
+
|
|
20
|
+
- repo: https://github.com/psf/black
|
|
21
|
+
rev: 25.1.0
|
|
22
|
+
hooks:
|
|
23
|
+
- id: black
|
|
24
|
+
|
|
25
|
+
- repo: https://github.com/pycqa/isort
|
|
26
|
+
rev: 6.0.1
|
|
27
|
+
hooks:
|
|
28
|
+
- id: isort
|
|
29
|
+
|
|
30
|
+
- repo: https://github.com/astral-sh/uv-pre-commit
|
|
31
|
+
rev: 0.7.3
|
|
32
|
+
hooks:
|
|
33
|
+
- id: uv-lock
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
This work is licensed under the Creative Commons Attribution 4.0 International License. To view a copy of this license, visit https://creativecommons.org/licenses/by/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ya_tagscript
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Yet Another TagScript fork. An easy drop in user-provided Templating system.
|
|
5
|
+
Project-URL: GitHub, https://github.com/MajorTanya/ya_tagscript
|
|
6
|
+
Project-URL: Issues, https://github.com/MajorTanya/ya_tagscript/issues
|
|
7
|
+
Author-email: MajorTanya <tanya@majortanya.eu>
|
|
8
|
+
License-Expression: CC-BY-4.0
|
|
9
|
+
License-File: LICENSE.md
|
|
10
|
+
Keywords: tagscript
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Requires-Python: <3.14,>=3.11
|
|
18
|
+
Requires-Dist: discord-py>=2.5.2
|
|
19
|
+
Requires-Dist: pyparsing>=3.2.3
|
|
20
|
+
Requires-Dist: python-dateutil>=2.9.0.post0
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# ya_tagscript - Yet Another TagScript fork
|
|
24
|
+
|
|
25
|
+
## Information
|
|
26
|
+
|
|
27
|
+
This is a fork of PhenoM4n4n's [TagScript](https://github.com/phenom4n4n/TagScript),
|
|
28
|
+
which itself is a fork of JonSnowbd's
|
|
29
|
+
[TagScript](https://github.com/JonSnowbd/TagScript), a string templating language.
|
|
30
|
+
|
|
31
|
+
The main purpose of this fork is to align the Discord-specific blocks with the most
|
|
32
|
+
recent Discord and discord.py changes (new username system, etc.).
|
|
33
|
+
|
|
34
|
+
## What?
|
|
35
|
+
|
|
36
|
+
TagScript is a drop-in, easy-to-use string interpreter that lets you provide users with
|
|
37
|
+
ways of customizing their profiles or chat rooms with interactive text.
|
|
38
|
+
|
|
39
|
+
For example TagScript comes out of the box with a random block that would let users
|
|
40
|
+
provide a template that produces a new result each time its ran, or assign math and
|
|
41
|
+
variables for later use.
|
|
42
|
+
|
|
43
|
+
## Changes in v1
|
|
44
|
+
|
|
45
|
+
The newly released v1 includes a complete rewrite of the entire parsing and
|
|
46
|
+
interpretation performed by the TagScriptInterpreter class. This comes with some subtle
|
|
47
|
+
behavioural changes but great care was taken to keep v1 behaviourally similar to v0 and
|
|
48
|
+
PhenoM4n4n's fork. Most simple uses *should* behave the same but especially deeply
|
|
49
|
+
nested scripts or dynamically assembled ones will most likely require adjustments.
|
|
50
|
+
Some documentation examples were also outright wrong, so those were also adjusted to
|
|
51
|
+
reflect the actual behaviour of the pre-existing interpreter.
|
|
52
|
+
|
|
53
|
+
### Oh, no! Behaviour changes?!
|
|
54
|
+
|
|
55
|
+
To remove the need for dynamically assembled blocks (e.g. command blocks that only
|
|
56
|
+
happen under some circumstances), v1 only performs interpretation of branches that were
|
|
57
|
+
actually hit (to the best of its ability).
|
|
58
|
+
|
|
59
|
+
Take this (very bad) password check script:
|
|
60
|
+
|
|
61
|
+
```tagscript
|
|
62
|
+
{if({args}==123):{command:echo password accepted!}|something else}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
If `{args}` is not in fact equal to `123`, the interpreter WILL NOT interpret the
|
|
66
|
+
command block AT ALL. It jumps straight to the `else` section after the `|` and only
|
|
67
|
+
interprets that. This means that for any incorrect values of `{args}`, the `echo`
|
|
68
|
+
command is NOT included in the list of commands in `response.actions.get("commands")`.
|
|
69
|
+
|
|
70
|
+
Other blocks with some conditional executions (like `all` or `any`) do the same.
|
|
71
|
+
|
|
72
|
+
## Installation
|
|
73
|
+
|
|
74
|
+
Download the latest version through pip:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
pip3 install ya_tagscript
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
or
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
pip3 install git+https://github.com/MajorTanya/ya_tagscript.git@v1.0.0.alpha03
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Download from a commit:
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
pip3 install git+https://github.com/MajorTanya/ya_tagscript.git@<COMMIT_HASH>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Install for editing/development:
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
git clone https://github.com/MajorTanya/ya_tagscript.git
|
|
96
|
+
pip3 install -e ./TagScript
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Dependencies
|
|
100
|
+
|
|
101
|
+
- `Python>=3.11`
|
|
102
|
+
- `discord.py>=2.5.2`
|
|
103
|
+
- `pyparsing>=3.2.3`
|
|
104
|
+
- `python-dateutil>=2.9.0.post0`
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# ya_tagscript - Yet Another TagScript fork
|
|
2
|
+
|
|
3
|
+
## Information
|
|
4
|
+
|
|
5
|
+
This is a fork of PhenoM4n4n's [TagScript](https://github.com/phenom4n4n/TagScript),
|
|
6
|
+
which itself is a fork of JonSnowbd's
|
|
7
|
+
[TagScript](https://github.com/JonSnowbd/TagScript), a string templating language.
|
|
8
|
+
|
|
9
|
+
The main purpose of this fork is to align the Discord-specific blocks with the most
|
|
10
|
+
recent Discord and discord.py changes (new username system, etc.).
|
|
11
|
+
|
|
12
|
+
## What?
|
|
13
|
+
|
|
14
|
+
TagScript is a drop-in, easy-to-use string interpreter that lets you provide users with
|
|
15
|
+
ways of customizing their profiles or chat rooms with interactive text.
|
|
16
|
+
|
|
17
|
+
For example TagScript comes out of the box with a random block that would let users
|
|
18
|
+
provide a template that produces a new result each time its ran, or assign math and
|
|
19
|
+
variables for later use.
|
|
20
|
+
|
|
21
|
+
## Changes in v1
|
|
22
|
+
|
|
23
|
+
The newly released v1 includes a complete rewrite of the entire parsing and
|
|
24
|
+
interpretation performed by the TagScriptInterpreter class. This comes with some subtle
|
|
25
|
+
behavioural changes but great care was taken to keep v1 behaviourally similar to v0 and
|
|
26
|
+
PhenoM4n4n's fork. Most simple uses *should* behave the same but especially deeply
|
|
27
|
+
nested scripts or dynamically assembled ones will most likely require adjustments.
|
|
28
|
+
Some documentation examples were also outright wrong, so those were also adjusted to
|
|
29
|
+
reflect the actual behaviour of the pre-existing interpreter.
|
|
30
|
+
|
|
31
|
+
### Oh, no! Behaviour changes?!
|
|
32
|
+
|
|
33
|
+
To remove the need for dynamically assembled blocks (e.g. command blocks that only
|
|
34
|
+
happen under some circumstances), v1 only performs interpretation of branches that were
|
|
35
|
+
actually hit (to the best of its ability).
|
|
36
|
+
|
|
37
|
+
Take this (very bad) password check script:
|
|
38
|
+
|
|
39
|
+
```tagscript
|
|
40
|
+
{if({args}==123):{command:echo password accepted!}|something else}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
If `{args}` is not in fact equal to `123`, the interpreter WILL NOT interpret the
|
|
44
|
+
command block AT ALL. It jumps straight to the `else` section after the `|` and only
|
|
45
|
+
interprets that. This means that for any incorrect values of `{args}`, the `echo`
|
|
46
|
+
command is NOT included in the list of commands in `response.actions.get("commands")`.
|
|
47
|
+
|
|
48
|
+
Other blocks with some conditional executions (like `all` or `any`) do the same.
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
Download the latest version through pip:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
pip3 install ya_tagscript
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
or
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
pip3 install git+https://github.com/MajorTanya/ya_tagscript.git@v1.0.0.alpha03
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Download from a commit:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
pip3 install git+https://github.com/MajorTanya/ya_tagscript.git@<COMMIT_HASH>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Install for editing/development:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
git clone https://github.com/MajorTanya/ya_tagscript.git
|
|
74
|
+
pip3 install -e ./TagScript
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Dependencies
|
|
78
|
+
|
|
79
|
+
- `Python>=3.11`
|
|
80
|
+
- `discord.py>=2.5.2`
|
|
81
|
+
- `pyparsing>=3.2.3`
|
|
82
|
+
- `python-dateutil>=2.9.0.post0`
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Minimal makefile for Sphinx documentation
|
|
2
|
+
#
|
|
3
|
+
|
|
4
|
+
# You can set these variables from the command line, and also
|
|
5
|
+
# from the environment for the first two.
|
|
6
|
+
SPHINXOPTS ?=
|
|
7
|
+
SPHINXBUILD ?= sphinx-build
|
|
8
|
+
SOURCEDIR = .
|
|
9
|
+
BUILDDIR = _build
|
|
10
|
+
|
|
11
|
+
# Put it first so that "make" without argument is like "make help".
|
|
12
|
+
help:
|
|
13
|
+
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
14
|
+
|
|
15
|
+
.PHONY: help Makefile
|
|
16
|
+
|
|
17
|
+
livehtml:
|
|
18
|
+
sphinx-autobuild --watch ../src --re-ignore "\.py(?:c|c\.*)|__pycache__" "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
19
|
+
|
|
20
|
+
# Catch-all target: route all unknown targets to Sphinx using the new
|
|
21
|
+
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
|
22
|
+
%: Makefile
|
|
23
|
+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import dataclasses
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from docutils import nodes
|
|
5
|
+
from sphinx.addnodes import desc, desc_signature, pending_xref
|
|
6
|
+
from sphinx.application import Sphinx
|
|
7
|
+
from sphinx.util import logging as sphinx_logging
|
|
8
|
+
|
|
9
|
+
logger = sphinx_logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def setup(app: Sphinx) -> dict[str, Any]:
|
|
13
|
+
collector = GlossaryRefChecker()
|
|
14
|
+
# Capture pending cross-refs before resolution
|
|
15
|
+
app.connect("doctree-read", collector.process_doc_read)
|
|
16
|
+
app.connect("doctree-resolved", collector.check_glossary_refs)
|
|
17
|
+
return {
|
|
18
|
+
"version": "1.0",
|
|
19
|
+
"parallel_read_safe": True,
|
|
20
|
+
"parallel_write_safe": True,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclasses.dataclass
|
|
25
|
+
class MismatchedTermData:
|
|
26
|
+
found_undeclared: set[str]
|
|
27
|
+
declared_not_found: set[str]
|
|
28
|
+
ref_col_seen: bool
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class GlossaryRefChecker:
|
|
32
|
+
"""
|
|
33
|
+
A Sphinx extension to validate glossary term references and their back-references.
|
|
34
|
+
|
|
35
|
+
This extension ensures that all glossary terms referenced in the documentation
|
|
36
|
+
are properly declared and that their "Referenced by" sections are consistent.
|
|
37
|
+
It helps maintain the integrity of cross-references in the documentation,
|
|
38
|
+
improving its accuracy and reliability for users.
|
|
39
|
+
|
|
40
|
+
This validation approach allows for all references to be resolved fully before
|
|
41
|
+
checking their validity without a need to modify the documents in progress, which
|
|
42
|
+
would spawn further reference objects.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def process_doc_read(self, app: Sphinx, doctree: nodes.document) -> None:
|
|
46
|
+
docname = app.env.docname
|
|
47
|
+
if not hasattr(app.env, "glossary_term_refs"):
|
|
48
|
+
app.env.glossary_term_refs = {} # type: ignore
|
|
49
|
+
|
|
50
|
+
for node in doctree.findall(
|
|
51
|
+
lambda n: isinstance(n, (pending_xref, nodes.reference))
|
|
52
|
+
):
|
|
53
|
+
if node.get("reftype") != "term":
|
|
54
|
+
continue
|
|
55
|
+
|
|
56
|
+
term = node.get("reftarget", "")
|
|
57
|
+
anchor = None
|
|
58
|
+
|
|
59
|
+
# Check if inside an autodoc class directive
|
|
60
|
+
parent = node
|
|
61
|
+
while parent and not (
|
|
62
|
+
isinstance(parent, desc) and parent.get("objtype") == "class"
|
|
63
|
+
):
|
|
64
|
+
parent = parent.parent
|
|
65
|
+
|
|
66
|
+
if parent:
|
|
67
|
+
# It's inside a class doc
|
|
68
|
+
sig_node = parent.next_node(desc_signature)
|
|
69
|
+
if sig_node and sig_node.get("ids"):
|
|
70
|
+
anchor = sig_node["ids"][0]
|
|
71
|
+
else:
|
|
72
|
+
# fallback: use nearest parent with an ID (like a section)
|
|
73
|
+
parent = node
|
|
74
|
+
while parent:
|
|
75
|
+
if parent.get("ids"):
|
|
76
|
+
anchor = parent["ids"][0]
|
|
77
|
+
break
|
|
78
|
+
parent = parent.parent
|
|
79
|
+
|
|
80
|
+
if not anchor:
|
|
81
|
+
# fallback to synthetic anchor if no ID found (should be rare)
|
|
82
|
+
anchor = f"auto-ref-{hash(node.astext()) % 100000}"
|
|
83
|
+
|
|
84
|
+
logger.verbose(
|
|
85
|
+
f"[GlossaryRefCheck] Glossary term reference found: term=%r, doc=%r, anchor=%r",
|
|
86
|
+
term,
|
|
87
|
+
docname,
|
|
88
|
+
anchor,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
app.env.glossary_term_refs.setdefault(term, set()).add((docname, anchor)) # type: ignore
|
|
92
|
+
|
|
93
|
+
def check_glossary_refs(self, app: Sphinx, doctree: nodes.document, docname: str):
|
|
94
|
+
if docname != "glossary":
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
mismatched_terms: dict[str, MismatchedTermData] = {}
|
|
98
|
+
|
|
99
|
+
for node in doctree.findall(nodes.definition_list_item):
|
|
100
|
+
term_definitions: set[str] = set()
|
|
101
|
+
for child in node.findall(nodes.term):
|
|
102
|
+
child_text = child.astext()
|
|
103
|
+
term_definitions.add(child_text)
|
|
104
|
+
mismatched_terms[child_text] = MismatchedTermData(
|
|
105
|
+
set(),
|
|
106
|
+
set(),
|
|
107
|
+
ref_col_seen=False,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
refs_map: dict[str, set[tuple[str, str]]] = getattr(
|
|
111
|
+
app.env,
|
|
112
|
+
"glossary_term_refs",
|
|
113
|
+
{},
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
for ul in node.findall(nodes.bullet_list):
|
|
117
|
+
if "x-ref-col" not in ul.get("classes", []):
|
|
118
|
+
continue
|
|
119
|
+
|
|
120
|
+
listed_refs: set[str] = set()
|
|
121
|
+
for ul_li in ul.findall(nodes.list_item):
|
|
122
|
+
for para in ul_li.findall(nodes.paragraph):
|
|
123
|
+
for ref in para.findall(nodes.reference):
|
|
124
|
+
refuri = ref.attributes.get("refuri")
|
|
125
|
+
listed_refs.add(str(refuri).split("#")[-1])
|
|
126
|
+
|
|
127
|
+
combined_found_refs = set()
|
|
128
|
+
for t_def in term_definitions:
|
|
129
|
+
if (refs := refs_map.get(t_def)) is None:
|
|
130
|
+
continue
|
|
131
|
+
combined_found_refs.update({rm_entry[1] for rm_entry in refs})
|
|
132
|
+
|
|
133
|
+
found_but_undeclared = combined_found_refs.difference(listed_refs)
|
|
134
|
+
declared_but_not_found = listed_refs.difference(combined_found_refs)
|
|
135
|
+
for t_def in term_definitions:
|
|
136
|
+
mismatched_terms[t_def] = MismatchedTermData(
|
|
137
|
+
found_but_undeclared,
|
|
138
|
+
declared_but_not_found,
|
|
139
|
+
ref_col_seen=True,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
if any(
|
|
143
|
+
(
|
|
144
|
+
not term_data.ref_col_seen
|
|
145
|
+
or len(term_data.found_undeclared) != 0
|
|
146
|
+
or len(term_data.declared_not_found) != 0
|
|
147
|
+
)
|
|
148
|
+
for term_data in mismatched_terms.values()
|
|
149
|
+
):
|
|
150
|
+
problem_terms: dict[str, MismatchedTermData] = {}
|
|
151
|
+
for term, term_data in mismatched_terms.items():
|
|
152
|
+
if not term_data.ref_col_seen:
|
|
153
|
+
problem_terms[term] = term_data
|
|
154
|
+
logger.error(
|
|
155
|
+
"[GlossaryRefCheck] Could not find a 'Referenced by' "
|
|
156
|
+
"section with an 'x-ref-col' class for term %r",
|
|
157
|
+
term,
|
|
158
|
+
)
|
|
159
|
+
elif (
|
|
160
|
+
len(term_data.found_undeclared) != 0
|
|
161
|
+
or len(term_data.declared_not_found) != 0
|
|
162
|
+
):
|
|
163
|
+
problem_terms[term] = term_data
|
|
164
|
+
logger.error(
|
|
165
|
+
"[GlossaryRefCheck] 'Referenced by' section mismatch for "
|
|
166
|
+
"term %r: %r",
|
|
167
|
+
term,
|
|
168
|
+
term_data,
|
|
169
|
+
)
|
|
170
|
+
else:
|
|
171
|
+
logger.info(
|
|
172
|
+
"[GlossaryRefCheck] All glossary term references back-referenced correctly!"
|
|
173
|
+
)
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from docutils import nodes
|
|
2
|
+
from docutils.parsers.rst import Directive
|
|
3
|
+
from docutils.parsers.rst.directives import class_option
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class StyledList(Directive):
|
|
7
|
+
has_content = True
|
|
8
|
+
option_spec = {
|
|
9
|
+
"class": class_option,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
def run(self) -> list[nodes.Node]:
|
|
13
|
+
node = nodes.Element()
|
|
14
|
+
self.state.nested_parse(self.content, self.content_offset, node)
|
|
15
|
+
|
|
16
|
+
list_node = next(
|
|
17
|
+
(
|
|
18
|
+
child
|
|
19
|
+
for child in node
|
|
20
|
+
if isinstance(child, (nodes.bullet_list, nodes.enumerated_list))
|
|
21
|
+
),
|
|
22
|
+
None,
|
|
23
|
+
)
|
|
24
|
+
if list_node is None:
|
|
25
|
+
error = self.state_machine.reporter.error(
|
|
26
|
+
"Expected a bullet list or enumerated list in 'styled-list' content.",
|
|
27
|
+
nodes.literal_block(self.block_text, self.block_text),
|
|
28
|
+
line=self.lineno,
|
|
29
|
+
)
|
|
30
|
+
return [error]
|
|
31
|
+
|
|
32
|
+
list_node["classes"] += self.options.get("class", [])
|
|
33
|
+
return [list_node]
|