Skip to content

Commit 97a2e3f

Browse files
authored
Merge pull request #84 from INCATools/list_issue
Bug fixes
2 parents bbdfbdb + aac5318 commit 97a2e3f

File tree

12 files changed

+272
-7
lines changed

12 files changed

+272
-7
lines changed

.github/workflows/publish_to_pypi.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Publish Python distributions to PyPI
1+
name: Publish to PyPI
22

33
on:
44
# Allows you to run this workflow manually from the Actions tab
@@ -40,4 +40,4 @@ jobs:
4040
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
4141
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
4242
run: |
43-
twine upload --repository-url https://test.pypi.org/legacy/ dist/*
43+
twine upload dist/*
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Publish to test PyPI
2+
3+
# Expect this action to be triggered manually before
4+
5+
on:
6+
# Allows you to run this workflow manually from the Actions tab
7+
workflow_dispatch:
8+
9+
jobs:
10+
build-and-publish:
11+
name: Publish Python distributions to PyPI
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v2
15+
- name: Set up Python 3.8
16+
uses: actions/setup-python@v2
17+
with:
18+
python-version: 3.8
19+
- name: Install Deployment Tools
20+
run: |
21+
python -m pip install --upgrade pip
22+
pip install setuptools wheel twine
23+
- name: Install Project Dependencies
24+
run: |
25+
pip install -r requirements.txt
26+
- name: Auto-Generate schema documentation
27+
run: PYTHONPATH=./src:$PYTHONPATH python -m dosdp document --schema -o ./src/schema/
28+
- name: Package Distribution
29+
run: >-
30+
python
31+
setup.py
32+
sdist
33+
bdist_wheel
34+
- name: Deploy Package
35+
env:
36+
TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
37+
TWINE_PASSWORD: ${{ secrets.PYPI_TEST_PASSWORD }}
38+
run: |
39+
twine upload --repository-url https://test.pypi.org/legacy/ dist/*

.github/workflows/tester.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,7 @@ jobs:
2525
run: |
2626
python -m pip install --upgrade pip
2727
pip install -r requirements.txt
28+
- name: Validate DOSDP Schema
29+
run: python ./src/schema/schema_validator.py
2830
- name: Run Test
2931
run: PYTHONPATH=./src:$PYTHONPATH python -m unittest discover -s src -p '*_test.py'

setup.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,32 @@
11
import pathlib
22
from setuptools import setup
33

4+
READTHEDOCS = "(http://incatools.github.io/dead_simple_owl_design_patterns/"
5+
relative_link_mapping = {"(docs/dosdp_schema.md)": READTHEDOCS + "dosdp_schema/)",
6+
"(docs/validator.md)": READTHEDOCS + "validator/)",
7+
"(docs/document.md)": READTHEDOCS + "document/)"}
8+
9+
10+
def update_relative_links(readme_content):
11+
"""
12+
Relative links are broken in the pypi home page. So replace them with read the docs absolute links.
13+
"""
14+
for key, value in relative_link_mapping.items():
15+
readme_content = readme_content.replace(key, value)
16+
return readme_content
17+
18+
419
# The directory containing this file
520
HERE = pathlib.Path(__file__).parent
621

722
# The text of the README file
823
README = (HERE / "README.md").read_text()
24+
README = update_relative_links(README)
925

1026
# This call to setup() does all the work
1127
setup(
1228
name="dosdp",
13-
version="0.1.7.dev1",
29+
version="0.1.9.dev1",
1430
description="The aim of this project is to specify a simple OWL design pattern system that can easily be consumed, whatever your code base.",
1531
long_description=README,
1632
long_description_content_type="text/markdown",

src/dosdp/validator.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def test_jschema(validator, pattern):
2727
if not validator.is_valid(pattern):
2828
es = validator.iter_errors(pattern)
2929
for e in es:
30-
warnings.warn(" => ".join([str(e.schema_path), str(e.message), str(e.context)]))
30+
warnings.warn(str(e.message))
3131
is_valid = False
3232

3333
return is_valid
@@ -200,6 +200,29 @@ def test_multi_clause_multi_list(pattern):
200200
return stat
201201

202202

203+
def test_annotation_properties(pattern):
204+
"""
205+
Structurally tests whether an annotation property is declared before use.
206+
Args:
207+
pattern: schema in yaml format to validate
208+
209+
Returns: True if all used annotation properties are declared, False otherwise.
210+
"""
211+
declared_annotations = set()
212+
if 'annotationProperties' in pattern.keys(): declared_annotations.update(set(pattern['annotationProperties'].keys()))
213+
expr = parse('annotations.[*].annotationProperty')
214+
used_annotations = [match for match in expr.find(pattern)]
215+
216+
stat = True
217+
if used_annotations:
218+
for annotation_prop in used_annotations:
219+
val = annotation_prop.value
220+
if val not in declared_annotations:
221+
warnings.warn("Annotation property '%s' didn't declared before use." % val)
222+
stat = False
223+
return stat
224+
225+
203226
def format_warning(message, category, filename, lineno, line=None):
204227
return '%s:%s: %s:%s\n' % (filename, lineno, category.__name__, message)
205228

@@ -239,7 +262,8 @@ def validate(pattern):
239262

240263
stat = True
241264
for pattern_doc in pattern_docs:
242-
logging.info("Checking %s" % pattern_doc)
265+
if len(pattern_docs) > 1:
266+
logging.info("Checking %s" % pattern_doc)
243267
with open(pattern_doc, "r") as stream:
244268
try:
245269
pattern = ryaml.load(stream)
@@ -249,6 +273,7 @@ def validate(pattern):
249273
if not test_clause_nesting(pattern): stat = False
250274
if not test_axiom_separator(pattern): stat = False
251275
if not test_multi_clause_multi_list(pattern): stat = False
276+
if not test_annotation_properties(pattern): stat = False
252277
except YAMLError as exc:
253278
stat = False
254279
logging.error('Failed to load pattern file: ' + pattern_doc)

src/schema/dosdp_schema.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ properties:
334334
doc_type: root
335335

336336
examples:
337-
type: list
337+
type: array
338338
items: { type: string }
339339
description: "A list of example terms implementing this pattern."
340340
doc_type: root
@@ -348,7 +348,7 @@ properties:
348348
doc_type: root
349349

350350
tags:
351-
type: list
351+
type: array
352352
items: { type: string }
353353
description: >
354354
A list of strings used to tag a pattern for the purposes of arbitrary,

src/schema/schema_validator.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import os
2+
from ruamel.yaml import YAML
3+
from jsonschema import Draft7Validator
4+
5+
SCHEMA_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../schema/dosdp_schema.yaml")
6+
7+
8+
ryaml = YAML(typ='safe')
9+
with open(SCHEMA_PATH) as stream:
10+
dosdp_schema = ryaml.load(stream)
11+
12+
Draft7Validator.check_schema(dosdp_schema)

src/schema/test/generic_test/schema_test.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
"../positive_test_set/patterns/acute.yaml")
1111
POSITIVE_PATTERN_2 = os.path.join(os.path.dirname(os.path.realpath(__file__)),
1212
"../positive_test_set/patterns/multi_clause_schema.yaml")
13+
POSITIVE_PATTERN_3 = os.path.join(os.path.dirname(os.path.realpath(__file__)),
14+
"../positive_test_set/patterns/abnormallyHyperplasticAnatomicalEntity.yaml")
1315
NEGATIVE_PATTERN_1 = os.path.join(os.path.dirname(os.path.realpath(__file__)),
1416
"../negative_test_set/acute_negative.yaml")
1517

@@ -38,6 +40,13 @@ def test_schema_validity1(self):
3840
# failing because def does not have a text
3941
self.assertEqual("{'vars': ['disease']} is not valid under any of the given schemas", next(es).message)
4042

43+
def test_array_validity(self):
44+
self.assertTrue(pathlib.Path(SCHEMA).exists())
45+
46+
validator = Draft4Validator(self.read_yaml(SCHEMA))
47+
48+
self.assertTrue(validator.is_valid(self.read_yaml(POSITIVE_PATTERN_3)))
49+
4150
def read_yaml(self, yaml_path):
4251
with open(yaml_path, "r") as stream:
4352
try:

src/schema/test/generic_test/validator_test.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
"../negative_test_set/multi_clause_with_multi_list.yaml")
2929
NEGATIVE_PATTERN_MULTI_CLAUSE_MULTI_LIST2 = os.path.join(os.path.dirname(os.path.realpath(__file__)),
3030
"../negative_test_set/multi_clause_with_multi_list2.yaml")
31+
NEGATIVE_PATTERN_UNDECLARED_ANNOT_PROP = os.path.join(os.path.dirname(os.path.realpath(__file__)),
32+
"../negative_test_set/undeclared_annotation_prop.yaml")
33+
NEGATIVE_PATTERN_SCHEMA = os.path.join(os.path.dirname(os.path.realpath(__file__)),
34+
"../negative_test_set/not_schema_compliant.yaml")
3135

3236

3337
class ValidatorTest(unittest.TestCase):
@@ -60,3 +64,9 @@ def test_axiom_separator(self):
6064
def test_single_list_per_multi_clause(self):
6165
self.assertFalse(validate(NEGATIVE_PATTERN_MULTI_CLAUSE_MULTI_LIST))
6266
self.assertFalse(validate(NEGATIVE_PATTERN_MULTI_CLAUSE_MULTI_LIST2))
67+
68+
def test_undeclared_annotation_prop(self):
69+
self.assertFalse(validate(NEGATIVE_PATTERN_UNDECLARED_ANNOT_PROP))
70+
71+
def test_schema_validation(self):
72+
self.assertFalse(validate(NEGATIVE_PATTERN_SCHEMA))
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
pattern_name: acute
2+
3+
pattern_iri: http://purl.obolibrary.org/obo/mondo/patterns/acute.yaml
4+
5+
description: 'This pattern is applied to diseases that are described as having an acute onset, i.e. the sudden appearance of disease manifestations over a short period of time.
6+
7+
Examples: [acute bronchiolitis](http://purl.obolibrary.org/obo/MONDO_0020680),
8+
[acute liver failure](http://purl.obolibrary.org/obo/MONDO_0019542)'
9+
10+
contributors:
11+
- https://orcid.org/0000-0002-6601-2165
12+
- https://orcid.org/0000-0001-5208-3432
13+
14+
classes:
15+
acute: PATO:0000389
16+
disease: MONDO:0000001
17+
18+
relations:
19+
has modifier: RO:0002573
20+
21+
annotationProperties:
22+
exact_synonym: oio:hasExactSynonym
23+
related_synonym: oio:hasRelatedSynonym
24+
25+
vars:
26+
disease: '''disease'''
27+
28+
name:
29+
text: acute %s
30+
vars:
31+
- disease
32+
33+
# axioms is not valid
34+
axioms:
35+
- annotationProperty: exact_synonym
36+
text: '%s, acute'
37+
vars:
38+
- disease
39+
40+
annotations:
41+
# property is not valid
42+
- property: exact_synonym
43+
text: '%s, acute'
44+
vars:
45+
- disease
46+
47+
def:
48+
text: Acute form of %s.
49+
vars:
50+
- disease
51+
52+
equivalentTo:
53+
text: '%s and ''has modifier'' some ''acute'''
54+
vars:
55+
- disease

0 commit comments

Comments
 (0)