diff options
author | David Luevano Alvarado <david@luevano.xyz> | 2023-02-17 01:06:26 -0600 |
---|---|---|
committer | David Luevano Alvarado <david@luevano.xyz> | 2023-02-17 01:06:26 -0600 |
commit | a5d9664a9264f45b088cc363331b391a40779b40 (patch) | |
tree | b3d94b185706a60dc3159b405ee04068d1b93a2c | |
parent | b0d48558606fabfb582358077c3c909c2bbb63e1 (diff) |
finish testing and polishing, add readmev1.0.0
-rw-r--r-- | README.md | 48 | ||||
-rw-r--r-- | pyproject.toml | 3 | ||||
-rw-r--r-- | requirements_dev.txt | 1 | ||||
-rw-r--r-- | setup.cfg | 24 | ||||
-rw-r--r-- | src/pymdvar/__init__.py | 9 | ||||
-rw-r--r-- | src/pymdvar/pymdvar.py | 24 | ||||
-rw-r--r-- | tests/conftest.py | 14 | ||||
-rw-r--r-- | tests/test_pymdvar.py | 61 |
8 files changed, 153 insertions, 31 deletions
@@ -1,2 +1,46 @@ -# pymdvar -Python's Markdown extension to insert variables +# pymdvar - Python-Markdown Variable extension + +Simple extension meant to be used to convert variables to their corresponding values. Works with environment variables too. + +It uses the `${variable}` syntax. For example, given `variable=value`, the following text: + +```md +Foo ${variable} bar +``` + +Becomes: + +```html +<p>Foo value bar</p> +``` + +## Install + +`pymdvar` can be installed via `pip`: + +```sh +python -m pip install pymdvar +``` + +## Usage + +The basic usage requires a dictionary with the variables to be passed to the `VariableExtension`: + +```py +>>> import markdown +>>> from pymdvar import VariableExtension +>>> markdown.markdown('foo *${test}* bar', extensions=[VariableExtension(variables={'test': 'value'})]) +'<p>foo <em>value</em> bar</p>' +``` + +if `enable_env=True` is passed, then it will read environment variables, too. Variables in `variables` take preference. + +Only `a-z`, `A-Z`, `_` and `0-9` characters are accepted. + +Passing the extension as a string is supported: + +```py +>>> import markdown +>>> markdown.markdown('foo *${test}* bar', extensions=['pymdvar'], extension_configs={'pymdvar': {'variables': {'test': 'value'}}}) +'<p>foo <em>value</em> bar</p>' +```
\ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index dcaca35..7744d62 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,6 +7,9 @@ addopts = "--cov-report term-missing --cov=pymdvar" testpaths = [ "tests", ] +env = [ + "PYMDVAR_TEST_1=1" +] [tool.mypy] mypy_path = "src" diff --git a/requirements_dev.txt b/requirements_dev.txt index 9979866..87baa83 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,5 +1,6 @@ pytest>=7.2.1 pytest-cov>=4.0.0 +pytest-env>=0.8.1 mypy>=1.0.0 flake8>=6.0.0 types-Markdown>=3.4.2.4
\ No newline at end of file @@ -2,19 +2,35 @@ name = pymdvar author = David Luevano Alvarado author_email = david@luevano.xyz -summary = Python-Markdown extension to insert variables +summary = Python-Markdown extension for key-value pair conversion description_file = README.md license = GPLv3 home_page = https://github.com/luevano/pymdvar classifiers = - Programming Language :: Python :: 3 License :: OSI Approved :: GNU General Public License v3 (GPLv3) - Operating System :: Unix - Topic :: Text Processing :: Markup :: HTML + Operating System :: OS Independent, + Programming Language :: Python, + Programming Language :: Python :: 3, + Programming Language :: Python :: 3.7, + Programming Language :: Python :: 3.8, + Programming Language :: Python :: 3.9, + Programming Language :: Python :: 3.10, + Programming Language :: Python :: 3.11, + Programming Language :: Python :: 3 :: Only, + Topic :: Communications :: Email :: Filters, + Topic :: Internet :: WWW/HTTP :: Dynamic Content :: CGI Tools/Libraries, + Topic :: Internet :: WWW/HTTP :: Site Management, + Topic :: Software Development :: Documentation, + Topic :: Software Development :: Libraries :: Python Modules, + Topic :: Text Processing :: Filters, + Topic :: Text Processing :: Markup :: HTML, Topic :: Text Processing :: Markup :: Markdown keywords = python + extension + plugin markdown + website [files] packages = diff --git a/src/pymdvar/__init__.py b/src/pymdvar/__init__.py index b64a3b6..d8d4d4e 100644 --- a/src/pymdvar/__init__.py +++ b/src/pymdvar/__init__.py @@ -1,3 +1,10 @@ +from typing import Any from .pymdvar import VariableExtension -__all__ = ['VariableExtension']
\ No newline at end of file +__all__ = ['VariableExtension'] + + +# this should be in pymdvar.py, but since there is only one extension, +# it is fine in here +def makeExtension(*args: Any, **kwargs: Any): + return VariableExtension(*args, **kwargs) diff --git a/src/pymdvar/pymdvar.py b/src/pymdvar/pymdvar.py index d81f785..2dcdf96 100644 --- a/src/pymdvar/pymdvar.py +++ b/src/pymdvar/pymdvar.py @@ -1,4 +1,4 @@ -from os import getenv +import os from re import Match from typing import Any from xml.etree.ElementTree import Element @@ -6,7 +6,7 @@ from markdown import Markdown from markdown.extensions import Extension from markdown.inlinepatterns import Pattern -VAR_RE: str = r'(\$\{)([a-zA-Z_]*)(\})' +VAR_RE: str = r'(\$\{)([a-zA-Z_0-9]*)(\})' class VarPattern(Pattern): @@ -22,14 +22,12 @@ class VarPattern(Pattern): def handleMatch(self, m: Match[str]) -> str | Element | None: # for some reason the group is offest by 1 var: str | Any = m.group(3) - value: str = '' - if var in self.vars: - value = self.vars[var] - else: - if self.enable_env: - value = getenv(var, '') - return value + return self.vars[var] + if self.enable_env: + if var in os.environ: + return os.environ[var] + return '' class VariableExtension(Extension): @@ -41,11 +39,7 @@ class VariableExtension(Extension): super().__init__(**kwargs) def extendMarkdown(self, md: Markdown) -> None: - vars: dict[str, str] | Any = self.getConfig('variables', dict()) - enable_env: bool = self.getConfig('enable_env', False) + vars: dict[str, str] | Any = self.getConfig('variables') + enable_env: bool = self.getConfig('enable_env') var_pattern: VarPattern = VarPattern(VAR_RE, vars, enable_env) md.inlinePatterns.register(var_pattern, 'variable', 175) - - -def makeExtension(*args: Any, **kwargs: Any): - return VariableExtension(*args, **kwargs) diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..df33848 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,14 @@ +import pytest + + +@pytest.fixture +def single_var_dict(): + return {'test': 'value'} + + +@pytest.fixture +def multi_var_dict(): + return {'ext': 'jpg', + 'test': 'value', + 'TEST': 'VALUE', + 'SOMETHING_ELSE': 'something_else'} diff --git a/tests/test_pymdvar.py b/tests/test_pymdvar.py index 91a97d0..a4c4439 100644 --- a/tests/test_pymdvar.py +++ b/tests/test_pymdvar.py @@ -1,3 +1,4 @@ +import os import pytest from markdown import markdown from pymdvar import VariableExtension @@ -5,31 +6,73 @@ from pymdvar import VariableExtension def test_empty_input(): in_str: str = '' + exp_str: str = markdown(in_str) out_str: str = markdown(in_str, extensions=[VariableExtension()]) - assert in_str == out_str + assert out_str == exp_str @pytest.mark.parametrize('in_str, exp_str', [ ('foo bar', '<p>foo bar</p>'), ('foo *test* bar', '<p>foo <em>test</em> bar</p>'), - ('foo **test** bar', '<p>foo <strong>test</strong> bar</p>'), + ('foo *PYMDVAR_TEST_1* bar', '<p>foo <em>PYMDVAR_TEST_1</em> bar</p>'), ('foo $test bar', '<p>foo $test bar</p>'), - ('foo *${test* bar', '<p>foo <em>${test</em> bar</p>'), ('foo **$test}** bar', '<p>foo <strong>$test}</strong> bar</p>'), + ('foo **$PYMDVAR_TEST_2}** bar', '<p>foo <strong>$PYMDVAR_TEST_2}</strong> bar</p>'), + ('foo [link](${test/a.html) bar', '<p>foo <a href="${test/a.html">link</a> bar</p>'), + ('foo ![image]($test}/a.jpg) bar', '<p>foo <img alt="image" src="$test}/a.jpg" /> bar</p>') +]) +def test_no_replacements_config(in_str: str, exp_str: str, single_var_dict: dict[str, str]): + out_str: str = markdown(in_str, extensions=[VariableExtension(variables=single_var_dict, enable_env=True)]) + assert out_str == exp_str + + +@pytest.mark.parametrize('in_str, exp_str', [ + ('foo *${test}* bar', '<p>foo <em></em> bar</p>'), + ('foo *${PYMDVAR_TEST_1}* bar', '<p>foo <em></em> bar</p>'), + ('foo [link](${test}/a.html) bar', '<p>foo <a href="/a.html">link</a> bar</p>'), ]) -def test_non_replacements(in_str, exp_str): +def test_replacements_no_config(in_str: str, exp_str: str): out_str: str = markdown(in_str, extensions=[VariableExtension()]) assert out_str == exp_str @pytest.mark.parametrize('in_str, exp_str', [ - ('foo ${test} bar', '<p>foo value bar</p>'), ('foo *${test}* bar', '<p>foo <em>value</em> bar</p>'), - ('foo **${test}** bar', '<p>foo <strong>value</strong> bar</p>'), + ('foo *${PYMDVAR_TEST_1}* bar', '<p>foo <em>1</em> bar</p>'), + ('foo ${value} bar', '<p>foo bar</p>'), + ('foo **${PYMDVAR_TEST_2}** bar', '<p>foo <strong></strong> bar</p>'), ('foo [link](${test}/a.html) bar', '<p>foo <a href="value/a.html">link</a> bar</p>'), - ('foo ![image](${test}/a.jpg) bar', '<p>foo <img alt="image" src="value/a.jpg" /> bar</p>'), + ('foo ![image](${PYMDVAR_TEST_1}/a.jpg) bar', '<p>foo <img alt="image" src="1/a.jpg" /> bar</p>'), + ('foo [link](${PYMDVAR_TEST_2}/a.html) bar', '<p>foo <a href="/a.html">link</a> bar</p>') ]) -def test_simple_replacements(in_str, exp_str): - out_str: str = markdown(in_str, extensions=[VariableExtension(variables={'test':'value'})]) +def test_simple_replacements(in_str: str, exp_str: str, single_var_dict: dict[str, str]): + out_str: str = markdown(in_str, extensions=[VariableExtension(variables=single_var_dict, enable_env=True)]) assert out_str == exp_str + +@pytest.mark.parametrize('in_str, exp_str', [ + ('foo *${test}* bar', '<p>foo <em>value</em> bar</p>'), + ('foo *${TEST}* bar', '<p>foo <em>VALUE</em> bar</p>'), + ('foo **${SOMETHING_ELSE}** bar', '<p>foo <strong>something_else</strong> bar</p>') +]) +def test_multivar_replacements(in_str: str, exp_str: str, multi_var_dict: dict[str, str]): + out_str: str = markdown(in_str, extensions=[VariableExtension(variables=multi_var_dict)]) + assert out_str == exp_str + + +@pytest.mark.parametrize('in_str, exp_str', [ + ('foo *${test}* and **${TEST}** bar', '<p>foo <em>value</em> and <strong>VALUE</strong> bar</p>'), + ('foo ![image](${PYMDVAR_TEST_1}/a.${ext}) bar', '<p>foo <img alt="image" src="/a.jpg" /> bar</p>') +]) +def test_text_multivar_replacements(in_str: str, exp_str: str, multi_var_dict: dict[str, str]): + out_str: str = markdown(in_str, extensions=[VariableExtension(variables=multi_var_dict)]) + assert out_str == exp_str + + +@pytest.mark.parametrize('in_str, exp_str', [ + ('foo *${test}* and **${TEST}** bar', '<p>foo <em>value</em> and <strong>VALUE</strong> bar</p>'), + ('foo ![image](${PYMDVAR_TEST_1}/a.${ext}) bar', '<p>foo <img alt="image" src="/a.jpg" /> bar</p>') +]) +def test_extension_text_mode(in_str: str, exp_str: str, multi_var_dict: dict[str, str]): + out_str: str = markdown(in_str, extensions=['pymdvar'], extension_configs={'pymdvar': {'variables': multi_var_dict}}) + assert out_str == exp_str |