Skip to content

Commit 5d5e8ff

Browse files
author
Alan Christie
committed
Initial logic
1 parent 161d20e commit 5d5e8ff

19 files changed

+431
-1
lines changed

.github/workflows/build.yaml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
name: build
3+
4+
# -----------------
5+
# Control variables (GitHub Secrets)
6+
# -----------------
7+
#
8+
# At the GitHub 'organisation' or 'project' level you must have the following
9+
# GitHub 'Repository Secrets' defined (i.e. via 'Settings -> Secrets'): -
10+
#
11+
# (none)
12+
#
13+
# -----------
14+
# Environment (GitHub Environments)
15+
# -----------
16+
#
17+
# Environment (none)
18+
19+
on:
20+
- push
21+
22+
jobs:
23+
build:
24+
runs-on: ubuntu-latest
25+
strategy:
26+
matrix:
27+
python-version:
28+
- '3.10'
29+
steps:
30+
- name: Checkout
31+
uses: actions/checkout@v2
32+
- name: Set up Python ${{ matrix.python-version }}
33+
uses: actions/setup-python@v2
34+
with:
35+
python-version: ${{ matrix.python-version }}
36+
- name: Install requirements
37+
run: |
38+
python -m pip install --upgrade pip
39+
pip install -r build-requirements.txt
40+
pip install -r package-requirements.txt
41+
- name: Test
42+
run: |
43+
pytest --cov=decoder
44+
pyroma .
45+
- name: Build
46+
run: |
47+
python setup.py bdist_wheel

.github/workflows/publish.yaml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
---
2+
name: publish
3+
4+
# Actions for any tag.
5+
6+
# -----------------
7+
# Control variables (GitHub Secrets)
8+
# -----------------
9+
#
10+
# At the GitHub 'organisation' or 'project' level you must have the following
11+
# GitHub 'Repository Secrets' defined (i.e. via 'Settings -> Secrets'): -
12+
#
13+
# PYPI_USERNAME
14+
# PYPI_TOKEN
15+
#
16+
# -----------
17+
# Environment (GitHub Environments)
18+
# -----------
19+
#
20+
# Environment (none)
21+
22+
on:
23+
push:
24+
tags:
25+
- '**'
26+
27+
jobs:
28+
build-and-publish:
29+
runs-on: ubuntu-latest
30+
steps:
31+
- name: Checkout
32+
uses: actions/checkout@v2
33+
- name: Inject slug/short variables
34+
uses: rlespinasse/[email protected]
35+
- name: Set up Python
36+
uses: actions/setup-python@v2
37+
with:
38+
python-version: '3.10'
39+
- name: Install dependencies
40+
run: |
41+
python -m pip install --upgrade pip
42+
pip install -r build-requirements.txt
43+
pip install -r package-requirements.txt
44+
- name: Build
45+
run: |
46+
pyroma .
47+
python setup.py bdist_wheel
48+
- name: Publish
49+
uses: pypa/gh-action-pypi-publish@release/v1
50+
with:
51+
user: ${{ secrets.PYPI_USERNAME }}
52+
password: ${{ secrets.PYPI_TOKEN }}

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.idea
2+
.pytest_cache
3+
.coverage
4+
*.egg-info
5+
**/__pycache__
6+
venv
7+
build
8+
dist
9+

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 Informatics Matters Ltd
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include LICENSE

README.md

Lines changed: 0 additions & 1 deletion
This file was deleted.

README.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Informatics Matters Data Manager Job Decoder
2+
============================================
3+
4+
.. image:: https://badge.fury.io/py/im-dm-job-decoder.svg
5+
:target: https://badge.fury.io/py/im-dm-job-decoder
6+
:alt: PyPI package (latest)
7+
8+
Installation (Python)
9+
=====================
10+
11+
The Job decoder is published on `PyPI`_ and can be installed from
12+
there::
13+
14+
pip install im-dm-job-decoder
15+
16+
.. _PyPI: https://pypi.org/project/im-dm-job-decoder
17+
18+
Get in touch
19+
============
20+
21+
- Report bugs, suggest features or view the source code `on GitHub`_.
22+
23+
.. _on GitHub: https://github.com/informaticsmatters/data-manager-job-decoder

build-requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pyroma == 3.2
2+
pytest == 6.2.5
3+
pytest-cov == 3.0.0

decoder/__init__.py

Whitespace-only changes.

decoder/decode_jinja2_3_0.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""A decoder for jinja2 3.0.x formatted strings.
2+
"""
3+
from typing import Dict, Optional, Set, Tuple
4+
5+
import jinja2
6+
from jinja2.exceptions import TemplateSyntaxError
7+
from jinja2.meta import find_undeclared_variables
8+
9+
10+
def decode(template_text: str,
11+
variable_map: Optional[Dict[str, str]],
12+
subject: str) -> Tuple[str, bool]:
13+
"""Decodes text expected to conform to Jinja2 (v3.0.x)
14+
"""
15+
assert template_text
16+
assert subject
17+
18+
# Make a template from the text
19+
env: jinja2.Environment = jinja2.\
20+
Environment(undefined=jinja2.DebugUndefined)
21+
try:
22+
template: jinja2.Template = env.from_string(template_text)
23+
except TemplateSyntaxError as ex:
24+
msg: str = f'TemplateSyntaxError with {subject}: {ex}'
25+
return msg, False
26+
27+
# Render (this works even if there are variables in the rendered text
28+
# The rendered text, when stripped of whitespace, must not be empty.
29+
rendered_text = template.render(variable_map).strip()
30+
if len(rendered_text) == 0:
31+
msg = f'Rendered text for {subject} is blank'
32+
return msg, False
33+
34+
# Check if rendering was done correctly.
35+
# It's a little odd with Jinja2 - as undefined variables are not
36+
# considered errors. See https://stackoverflow.com/a/55699590 in the
37+
# StackOverflow topic: -
38+
# How to get ALL undefined variables from a Jinja2 template?
39+
abstract_syntax_tree = env.parse(rendered_text)
40+
undefined: Set[str] = find_undeclared_variables(abstract_syntax_tree)
41+
if undefined:
42+
# We
43+
msg = f'Undefined template variables for {subject}:'
44+
for variable in undefined:
45+
msg += f' {variable},'
46+
# Return the message, stripping the last comma from it
47+
return msg[:-1], False
48+
49+
# OK if we get here.
50+
# Just return the rendered text
51+
return rendered_text, True

0 commit comments

Comments
 (0)