Skip to content

Commit e7f1c05

Browse files
author
Alan Christie
committed
Initial support for manifest validation
Now uses pylint and mypy
1 parent 541f19a commit e7f1c05

File tree

9 files changed

+113
-20
lines changed

9 files changed

+113
-20
lines changed

.github/workflows/build.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ jobs:
4343
run: |
4444
pytest --cov=decoder
4545
pyroma .
46+
pylint decoder
47+
mypy decoder --install-types --non-interactive
4648
- name: Build
4749
run: |
4850
python setup.py bdist_wheel

.mypy.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[mypy]
2+
ignore_missing_imports = True

MANIFEST.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
include LICENSE
2-
include decoder/schema.yaml
2+
include decoder/job-definition-schema.yaml
3+
include decoder/manifest-schema.yaml

README.rst

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ The following encoding/decoding formats are supported: -
1818

1919
- jinja2 (3.0)
2020

21-
The package also provides a ``validate_job_schema()`` function,
22-
which can (should) be used to validate the Job definition against the
23-
built-in schema.
21+
The package also provides ``validate_job_schema()`` and
22+
``validate_manifest_schema()`` functions, which can (should) be used to
23+
validate the Manifests and Job definitions against the
24+
built-in schemas.
2425

2526
.. _jinja2: https://jinja.palletsprojects.com/en/3.0.x/
2627

@@ -36,7 +37,8 @@ Once installed you can validate the definition (expected to be a dictionary
3637
formed from the definition YAML file) with:
3738

3839
>>> from decoder import decoder
39-
>>> error = decoder.validate_job_schema(job_defintion)
40+
>>> error = decoder.validate_manifest_schema(manifest)
41+
>>> error = decoder.validate_job_schema(job_definition)
4042

4143
And run the decoder with:
4244

build-requirements.txt

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

decoder/decoder.py

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,28 @@
1515
# The modules are expected to be called 'decode_<TextEncoding.lower()>'
1616
from . import decode_jinja2_3_0
1717

18-
# The (built-in) Job Definition schema...
18+
# The (built-in) schemas...
1919
# from the same directory as us.
20-
_SCHEMA_FILE: str = os.path.join(os.path.dirname(__file__), 'schema.yaml')
20+
_JD_SCHEMA_FILE: str = os.path.join(os.path.dirname(__file__),
21+
'job-definition-schema.yaml')
22+
_MANIFEST_SCHEMA_FILE: str = os.path.join(os.path.dirname(__file__),
23+
'manifest-schema.yaml')
2124

22-
# Load the schema YAML file now.
25+
# Load the JD schema YAML file now.
2326
# This must work as the file is installed along with this module.
24-
_JOB_SCHEMA: Dict[str, Any] = {}
25-
assert os.path.isfile(_SCHEMA_FILE)
26-
with open(_SCHEMA_FILE, 'r', encoding='utf8') as schema_file:
27-
_JOB_SCHEMA = yaml.load(schema_file, Loader=yaml.FullLoader)
28-
assert _JOB_SCHEMA
27+
assert os.path.isfile(_JD_SCHEMA_FILE)
28+
with open(_JD_SCHEMA_FILE, 'r', encoding='utf8') as schema_file:
29+
_JOB_DEFINITION_SCHEMA: Dict[str, Any] =\
30+
yaml.load(schema_file, Loader=yaml.FullLoader)
31+
assert _JOB_DEFINITION_SCHEMA
32+
33+
# Load the Manifest schema YAML file now.
34+
# This must work as the file is installed along with this module.
35+
assert os.path.isfile(_MANIFEST_SCHEMA_FILE)
36+
with open(_MANIFEST_SCHEMA_FILE, 'r', encoding='utf8') as schema_file:
37+
_MANIFEST_SCHEMA: Dict[str, Any] =\
38+
yaml.load(schema_file, Loader=yaml.FullLoader)
39+
assert _MANIFEST_SCHEMA
2940

3041

3142
class TextEncoding(enum.Enum):
@@ -34,16 +45,33 @@ class TextEncoding(enum.Enum):
3445
JINJA2_3_0 = 1 # Encoding that complies with Jinja2 v3.0.x
3546

3647

48+
def validate_manifest_schema(manifest: Dict[str, Any]) -> Optional[str]:
49+
"""Checks the Job Definition Manifest (a preloaded job-definition dictionary)
50+
against the built-in schema. If there's an error the error text is
51+
returned, otherwise None.
52+
"""
53+
assert isinstance(manifest, dict)
54+
55+
# Validate the Manifest against our schema
56+
try:
57+
jsonschema.validate(manifest, schema=_MANIFEST_SCHEMA)
58+
except jsonschema.ValidationError as ex:
59+
return str(ex.message)
60+
61+
# OK if we get here
62+
return None
63+
64+
3765
def validate_job_schema(job_definition: Dict[str, Any]) -> Optional[str]:
3866
"""Checks the Job Definition (a preloaded job-definition dictionary)
3967
against the built-in schema. If there's an error the error text is
4068
returned, otherwise None.
4169
"""
42-
assert job_definition
70+
assert isinstance(job_definition, dict)
4371

4472
# Validate the Job Definition against our schema
4573
try:
46-
jsonschema.validate(job_definition, schema=_JOB_SCHEMA)
74+
jsonschema.validate(job_definition, schema=_JOB_DEFINITION_SCHEMA)
4775
except jsonschema.ValidationError as ex:
4876
return str(ex.message)
4977

decoder/schema.yaml renamed to decoder/job-definition-schema.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ properties:
2121
type: string
2222
maxLength: 80
2323
description:
24-
tyep: string
24+
type: string
2525
collection:
2626
type: string
2727
minLength: 1
@@ -107,7 +107,7 @@ definitions:
107107
name:
108108
type: string
109109
minLength: 1
110-
maxLenght: 120
110+
maxLength: 120
111111
tag:
112112
type: string
113113
minLength: 1

decoder/manifest-schema.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
# The JSONSchema for JobDefinition 'Manifest' YAML files.
3+
#
4+
# See https://json-schema.org/understanding-json-schema/index.html
5+
6+
$schema: http://json-schema.org/draft-07/schema#
7+
8+
title: Data Manager Job Definition Manifest
9+
description: >-
10+
A manifest for Job Definition files
11+
12+
type: object
13+
properties:
14+
kind:
15+
const: DataManagerManifest
16+
kind-version:
17+
enum:
18+
- '2021.1'
19+
description:
20+
type: string
21+
job-definition-files:
22+
type: array
23+
items:
24+
type: string
25+
pattern: '^.{1,}(.yaml|.yml)$'
26+
maxLength: 255
27+
minItems: 1
28+
required:
29+
- kind
30+
- kind-version
31+
- job-definition-files

tests/test_validate_manifest.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Tests for the schema validator.
2+
from typing import Any, Dict
3+
from copy import deepcopy
4+
5+
import pytest
6+
pytestmark = pytest.mark.unit
7+
8+
from decoder import decoder
9+
10+
# A minimal Job Definition.
11+
# Tests can use this and adjust accordingly.
12+
_MINIMAL: Dict[str, Any] = {
13+
'kind': 'DataManagerManifest',
14+
'kind-version': '2021.1',
15+
'job-definition-files': ['blob.yaml',
16+
'blob.yml']}
17+
18+
19+
def test_validate_minimal():
20+
# Arrange
21+
22+
# Act
23+
error = decoder.validate_manifest_schema(_MINIMAL)
24+
25+
# Assert
26+
assert error is None

0 commit comments

Comments
 (0)