From 56f037503de954b7c805477f85265d5625e4d72b Mon Sep 17 00:00:00 2001 From: Joshua Coffey Date: Fri, 1 Jul 2022 10:43:20 -0400 Subject: [PATCH 1/8] Raise error when block not found --- codeinclude/resolver.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/codeinclude/resolver.py b/codeinclude/resolver.py index 4fc8090..df360aa 100644 --- a/codeinclude/resolver.py +++ b/codeinclude/resolver.py @@ -27,10 +27,12 @@ def select( if block: i = 0 delim_count = 0 + found_block = False for line in text.splitlines(): first_line_of_block = False i = i + 1 if block in line and delim_count <= 0: + found_block = True delim_count = 0 first_line_of_block = True delim_count += line.count("{") @@ -42,13 +44,19 @@ def select( delim_count -= line.count("}") + if not found_block: + raise ValueError("Block {block} not found to inject") + if inside_block: delim_count = 0 inside_matching = False + found_block = False for line_number, line in enumerate(text.splitlines(), start=1): first_line_of_block = False + # Detect the block beginning if inside_block in line and delim_count <= 0: + found_block = True delim_count = 0 first_line_of_block = True inside_matching = True @@ -68,6 +76,9 @@ def select( # Append the lines inside the matching block, skipping the first matching if inside_matching and not first_line_of_block: selected_lines.append(line_number) + + if not found_block: + raise ValueError("Block {block} not found to inject") if from_token and to_token: i = 0 From 147d84ab7a1b78ff20d1662fce4ea09508946aec Mon Sep 17 00:00:00 2001 From: Joshua Coffey Date: Fri, 1 Jul 2022 11:18:57 -0400 Subject: [PATCH 2/8] Don't use `better-setuptools-git-version` This is broken on Python 3.10 as `collections.Mapping` no longer exists. --- setup.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/setup.py b/setup.py index f865b5c..9be11c1 100644 --- a/setup.py +++ b/setup.py @@ -10,10 +10,7 @@ def read_file(fname): setup( name='mkdocs-codeinclude-plugin', - version_config={ - "version_format": "{tag}.dev{sha}", - "starting_version": "0.2.0" - }, + version="1.0", description="A plugin to include code snippets into mkdocs pages", long_description=read_file('README.md'), long_description_content_type='text/markdown', @@ -27,7 +24,6 @@ def read_file(fname): 'mkdocs>=1.2', 'pygments>=2.9.0' ], - setup_requires=['better-setuptools-git-version'], classifiers=[ 'Intended Audience :: Developers', 'Intended Audience :: Information Technology', From b5143678cb93e5ee841b785c54177faed0cda0e9 Mon Sep 17 00:00:00 2001 From: Joshua Coffey Date: Fri, 1 Jul 2022 11:22:04 -0400 Subject: [PATCH 3/8] Fix error message --- codeinclude/resolver.py | 4 ++-- setup.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/codeinclude/resolver.py b/codeinclude/resolver.py index df360aa..496f988 100644 --- a/codeinclude/resolver.py +++ b/codeinclude/resolver.py @@ -45,7 +45,7 @@ def select( delim_count -= line.count("}") if not found_block: - raise ValueError("Block {block} not found to inject") + raise ValueError(f"Block {block} not found to inject") if inside_block: delim_count = 0 @@ -78,7 +78,7 @@ def select( selected_lines.append(line_number) if not found_block: - raise ValueError("Block {block} not found to inject") + raise ValueError(f"Block {inside_block} not found to inject") if from_token and to_token: i = 0 diff --git a/setup.py b/setup.py index 9be11c1..abb2059 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ def read_file(fname): setup( name='mkdocs-codeinclude-plugin', - version="1.0", + version="1.0.1", description="A plugin to include code snippets into mkdocs pages", long_description=read_file('README.md'), long_description_content_type='text/markdown', From 88871fd343a0480a24a04fa5501e8f4d2f8cfaba Mon Sep 17 00:00:00 2001 From: Joshua Coffey Date: Fri, 1 Jul 2022 11:25:22 -0400 Subject: [PATCH 4/8] Add filename to error message --- codeinclude/plugin.py | 2 +- codeinclude/resolver.py | 5 +++-- setup.py | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/codeinclude/plugin.py b/codeinclude/plugin.py index 4f43675..72fd419 100644 --- a/codeinclude/plugin.py +++ b/codeinclude/plugin.py @@ -147,7 +147,7 @@ def get_substitute(self, page, title, filename, lines, block, inside_block): content = f.read() selected_content = select( - content, lines=lines, block=block, inside_block=inside_block + content, filename, lines=lines, block=block, inside_block=inside_block ) dedented = textwrap.dedent(selected_content) diff --git a/codeinclude/resolver.py b/codeinclude/resolver.py index 496f988..1bbdef9 100644 --- a/codeinclude/resolver.py +++ b/codeinclude/resolver.py @@ -3,6 +3,7 @@ def select( text, + filename, lines=None, from_token=None, to_token=None, @@ -45,7 +46,7 @@ def select( delim_count -= line.count("}") if not found_block: - raise ValueError(f"Block {block} not found to inject") + raise ValueError(f"Block {block} not found to inject from {filename}") if inside_block: delim_count = 0 @@ -78,7 +79,7 @@ def select( selected_lines.append(line_number) if not found_block: - raise ValueError(f"Block {inside_block} not found to inject") + raise ValueError(f"Block {inside_block} not found to inject from {filename}") if from_token and to_token: i = 0 diff --git a/setup.py b/setup.py index abb2059..9be11c1 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ def read_file(fname): setup( name='mkdocs-codeinclude-plugin', - version="1.0.1", + version="1.0", description="A plugin to include code snippets into mkdocs pages", long_description=read_file('README.md'), long_description_content_type='text/markdown', From 9427ae57fdcc090599425739f5068fc3d33da737 Mon Sep 17 00:00:00 2001 From: Joshua Coffey Date: Wed, 17 Aug 2022 13:56:22 -0400 Subject: [PATCH 5/8] Add config value to control whether or not `select()` throws for blocks which are not found --- codeinclude/plugin.py | 6 +++++- codeinclude/resolver.py | 7 ++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/codeinclude/plugin.py b/codeinclude/plugin.py index 72fd419..1e58eed 100644 --- a/codeinclude/plugin.py +++ b/codeinclude/plugin.py @@ -62,6 +62,10 @@ class CodeIncludePlugin(BasePlugin): default="pymdownx.tabbed", ), ), + ( + "block_throw", + mkdocs.config.config_options.Type(bool, default=False) + ) ) def on_page_markdown(self, markdown, page, config, site_navigation=None, **kwargs): @@ -147,7 +151,7 @@ def get_substitute(self, page, title, filename, lines, block, inside_block): content = f.read() selected_content = select( - content, filename, lines=lines, block=block, inside_block=inside_block + content, filename=filename, lines=lines, block=block, inside_block=inside_block, block_throw=self.config["block_throw"] ) dedented = textwrap.dedent(selected_content) diff --git a/codeinclude/resolver.py b/codeinclude/resolver.py index 1bbdef9..84263e0 100644 --- a/codeinclude/resolver.py +++ b/codeinclude/resolver.py @@ -3,13 +3,14 @@ def select( text, - filename, + filename=None, lines=None, from_token=None, to_token=None, block=None, inside_block=None, lang=None, + block_throw=False ): selected_lines = [] @@ -45,7 +46,7 @@ def select( delim_count -= line.count("}") - if not found_block: + if block_throw and not found_block: raise ValueError(f"Block {block} not found to inject from {filename}") if inside_block: @@ -78,7 +79,7 @@ def select( if inside_matching and not first_line_of_block: selected_lines.append(line_number) - if not found_block: + if block_throw and not found_block: raise ValueError(f"Block {inside_block} not found to inject from {filename}") if from_token and to_token: From e773c679682ed532dbda7eb599fe99f5ae08424b Mon Sep 17 00:00:00 2001 From: Joshua Coffey Date: Wed, 17 Aug 2022 14:04:21 -0400 Subject: [PATCH 6/8] Add documentation for config values --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 08f72ea..00ce2e9 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ Note that: * Every line in the source file will be searched for an instance of the token (e.g. `doFoo`). If more than one line includes that token, then potentially more than one block could be targeted for inclusion. It is advisable to use a specific, unique token to avoid unexpected behaviour. +* If the specified block is not found, behavior depends on the `block_throw` config value (see [Configuration](#configuration)) When we wish to include a section of code that does not naturally appear within braces, we can simply insert our token, with matching braces, in a comment. @@ -127,6 +128,16 @@ will be rendered as: doTheThingThatWeActuallyWantToShow(); ``` +## Configuration + +This plugin takes two config values, specified in `mkdocs.yml`. + +| Name | Description | Values | Default | +|---------------|---------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------|-------------------| +| `title_mode` | Controls how titles are generated for included blocks | `none`, `legacy_pymdownx.superfences`, `pymdownx.tabbed` | `pymdownx.tabbed` | +| `block_throw` | Controls whether to include entire file (`false`) or raise an error (`true`) if included block is not found in file | `true`, `false` | `false` | + + ## Building the Project Install the dependencies: From 8093f47d548c27219c874cf253026f69d602ce53 Mon Sep 17 00:00:00 2001 From: Joshua Coffey Date: Wed, 17 Aug 2022 14:04:29 -0400 Subject: [PATCH 7/8] Add tests for `block_throws` --- tests/codeinclude/test_resolver.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/codeinclude/test_resolver.py b/tests/codeinclude/test_resolver.py index d2dec1c..c2ad7ff 100644 --- a/tests/codeinclude/test_resolver.py +++ b/tests/codeinclude/test_resolver.py @@ -28,6 +28,24 @@ def test_whole_block(self): result = select(CODE_BLOCK_EXAMPLE, block="blockstarter") self.assertEquals(("blockstarter {\n" " block content\n" "}\n"), result) + def test_block_throw(self): + # Test that entire file is returned for nonexistent block where `block_throw`=False + result = select(CODE_BLOCK_EXAMPLE, "test_file", block="nonexistent_block", block_throw=False) + self.assertEquals(CODE_BLOCK_EXAMPLE, result) + + # ...as well as for inside_block + result = select(CODE_BLOCK_EXAMPLE, "test_file", inside_block="nonexistent_block", block_throw=False) + self.assertEquals(CODE_BLOCK_EXAMPLE, result) + + # Test that throw occurs for nonexistent block + with self.assertRaises(ValueError): + result = select(CODE_BLOCK_EXAMPLE, "test_file", block="nonexistent_block", block_throw=True) + + # ...as well as for inside_block + with self.assertRaises(ValueError): + result = select(CODE_BLOCK_EXAMPLE, "test_file", inside_block="nonexistent_block", block_throw=True) + + def test_block_curly_on_same_line(self): result = select( textwrap.dedent( From 87c9ab6028d3c61a40ffc975dd9fa3ef987b4f13 Mon Sep 17 00:00:00 2001 From: Joshua Coffey Date: Wed, 17 Aug 2022 14:04:51 -0400 Subject: [PATCH 8/8] Revert "Don't use `better-setuptools-git-version`" This reverts commit 147d84ab7a1b78ff20d1662fce4ea09508946aec. --- setup.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 9be11c1..f865b5c 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,10 @@ def read_file(fname): setup( name='mkdocs-codeinclude-plugin', - version="1.0", + version_config={ + "version_format": "{tag}.dev{sha}", + "starting_version": "0.2.0" + }, description="A plugin to include code snippets into mkdocs pages", long_description=read_file('README.md'), long_description_content_type='text/markdown', @@ -24,6 +27,7 @@ def read_file(fname): 'mkdocs>=1.2', 'pygments>=2.9.0' ], + setup_requires=['better-setuptools-git-version'], classifiers=[ 'Intended Audience :: Developers', 'Intended Audience :: Information Technology',