ogc-na 0.2.9__tar.gz → 0.2.11__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ogc-na might be problematic. Click here for more details.
- {ogc_na-0.2.9 → ogc_na-0.2.11}/PKG-INFO +1 -1
- {ogc_na-0.2.9 → ogc_na-0.2.11}/ogc/na/annotate_schema.py +77 -53
- {ogc_na-0.2.9 → ogc_na-0.2.11}/ogc_na.egg-info/PKG-INFO +1 -1
- {ogc_na-0.2.9 → ogc_na-0.2.11}/.github/workflows/python-publish.yml +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/.gitignore +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/MANIFEST.in +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/README.md +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/docs/examples.md +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/docs/gen_ref_pages.py +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/docs/index.md +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/docs/tutorials.md +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/mkdocs.yml +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/ogc/na/__init__.py +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/ogc/na/domain_config.py +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/ogc/na/download.py +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/ogc/na/ingest_json.py +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/ogc/na/input_filters/__init__.py +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/ogc/na/input_filters/csv.py +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/ogc/na/profile.py +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/ogc/na/provenance.py +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/ogc/na/update_vocabs.py +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/ogc/na/util.py +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/ogc/na/validation.py +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/ogc_na.egg-info/SOURCES.txt +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/ogc_na.egg-info/dependency_links.txt +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/ogc_na.egg-info/requires.txt +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/ogc_na.egg-info/top_level.txt +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/pyproject.toml +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/rdf/catalog-v001.xml +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/rdf/domaincfg.vocab.ttl +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/requirements.txt +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/setup.cfg +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/setup.py +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/test/__init__.py +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/test/data/empty.ttl +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/test/data/headers.csv +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/test/data/no-headers.csv +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/test/data/profile_tree.ttl +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/test/data/profile_tree_cyclic.ttl +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/test/data/sample-context.jsonld +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/test/data/sample-schema-prop-c.yml +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/test/data/sample-schema.yml +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/test/data/uplift_context_valid.yml +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/test/test_annotate_schema.py +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/test/test_ingest_json.py +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/test/test_input_filters_csv.py +0 -0
- {ogc_na-0.2.9 → ogc_na-0.2.11}/test/test_profile.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ogc_na
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.11
|
|
4
4
|
Summary: OGC Naming Authority tools
|
|
5
5
|
Author-email: Rob Atkinson <ratkinson@ogc.org>, Piotr Zaborowski <pzaborowski@ogc.org>, Alejandro Villar <avillar@ogc.org>
|
|
6
6
|
Project-URL: Homepage, https://github.com/opengeospatial/ogc-na-tools/
|
|
@@ -323,7 +323,8 @@ class SchemaAnnotator:
|
|
|
323
323
|
|
|
324
324
|
def __init__(self, fn: Path | str | None = None, url: str | None = None,
|
|
325
325
|
follow_refs: bool = True, ref_root: Path | str | None = None,
|
|
326
|
-
context: str | Path | dict | None = None
|
|
326
|
+
context: str | Path | dict | None = None,
|
|
327
|
+
ref_mapper: Callable[[str], str] | None = None):
|
|
327
328
|
"""
|
|
328
329
|
:param fn: file path to load (root schema)
|
|
329
330
|
:param url: URL to load (root schema)
|
|
@@ -334,9 +335,29 @@ class SchemaAnnotator:
|
|
|
334
335
|
self.ref_root = Path(ref_root) if ref_root else None
|
|
335
336
|
self._follow_refs = follow_refs
|
|
336
337
|
self._provided_context = context
|
|
338
|
+
self._ref_mapper = ref_mapper
|
|
337
339
|
|
|
338
340
|
self._process_schema(fn, url)
|
|
339
341
|
|
|
342
|
+
def _follow_ref(self, subschema, schema_fn: Path, schema_url: str, base_url: str | None):
|
|
343
|
+
if not isinstance(subschema, dict) or '$ref' not in subschema:
|
|
344
|
+
return
|
|
345
|
+
|
|
346
|
+
if self._ref_mapper:
|
|
347
|
+
subschema['$ref'] = self._ref_mapper(subschema['$ref'])
|
|
348
|
+
|
|
349
|
+
if not self._follow_refs:
|
|
350
|
+
return
|
|
351
|
+
|
|
352
|
+
ref_fn, ref_url = resolve_ref(subschema['$ref'], schema_fn, schema_url, base_url)
|
|
353
|
+
ref = ref_fn or ref_url
|
|
354
|
+
|
|
355
|
+
if ref in self.schemas:
|
|
356
|
+
logger.info(' >> Found $ref to already-processed schema: %s', ref)
|
|
357
|
+
else:
|
|
358
|
+
logger.info(' >> Found $ref to new schema: %s', ref)
|
|
359
|
+
self._process_schema(url=ref_url, fn=ref_fn)
|
|
360
|
+
|
|
340
361
|
def _process_schema(self, fn: Path | str | None = None, url: str | None = None):
|
|
341
362
|
contents, base_url = read_contents(fn, url)
|
|
342
363
|
schema, is_json = load_json_yaml(contents)
|
|
@@ -381,24 +402,26 @@ class SchemaAnnotator:
|
|
|
381
402
|
prop_value[ANNOTATION_ID] = terms[prop]
|
|
382
403
|
if prop in types:
|
|
383
404
|
prop_value[ANNOTATION_TYPE] = types[prop]
|
|
384
|
-
if '$ref' in prop_value and self._follow_refs:
|
|
385
|
-
|
|
386
|
-
ref_fn, ref_url = resolve_ref(prop_value['$ref'], fn, url, base_url)
|
|
387
|
-
ref = ref_fn or ref_url
|
|
388
405
|
|
|
389
|
-
|
|
390
|
-
logger.info(' >> Found $ref to already-processed schema: %s', ref)
|
|
391
|
-
else:
|
|
392
|
-
logger.info(' >> Found $ref to new schema: %s', prop_value['$ref'])
|
|
393
|
-
if ref_url:
|
|
394
|
-
self._process_schema(url=ref)
|
|
395
|
-
else:
|
|
396
|
-
self._process_schema(fn=ref)
|
|
406
|
+
process_subschema(prop_value)
|
|
397
407
|
|
|
398
408
|
properties.update({p: {ANNOTATION_ID: terms[p]} for p in empty_properties if p in terms})
|
|
399
409
|
|
|
400
410
|
def process_subschema(subschema):
|
|
401
411
|
|
|
412
|
+
if not subschema:
|
|
413
|
+
return
|
|
414
|
+
|
|
415
|
+
self._follow_ref(subschema, fn, url, base_url)
|
|
416
|
+
|
|
417
|
+
# Annotate oneOf, allOf, anyOf
|
|
418
|
+
for p in ('oneOf', 'allOf', 'anyOf'):
|
|
419
|
+
collection = subschema.get(p)
|
|
420
|
+
if collection and isinstance(collection, list):
|
|
421
|
+
for entry in collection:
|
|
422
|
+
process_subschema(entry)
|
|
423
|
+
|
|
424
|
+
# Annotate main schema
|
|
402
425
|
schema_type = subschema.get('type')
|
|
403
426
|
if not schema_type and 'properties' in subschema:
|
|
404
427
|
schema_type = 'object'
|
|
@@ -407,8 +430,9 @@ class SchemaAnnotator:
|
|
|
407
430
|
process_properties(subschema)
|
|
408
431
|
elif schema_type == 'array':
|
|
409
432
|
for k in ('prefixItems', 'items', 'contains'):
|
|
410
|
-
|
|
433
|
+
process_subschema(subschema.get(k))
|
|
411
434
|
|
|
435
|
+
# Annotate $defs
|
|
412
436
|
for defs_prop in ('$defs', 'definitions'):
|
|
413
437
|
defs_value = subschema.get(defs_prop)
|
|
414
438
|
if isinstance(defs_value, dict):
|
|
@@ -433,7 +457,7 @@ class ContextBuilder:
|
|
|
433
457
|
"""
|
|
434
458
|
|
|
435
459
|
def __init__(self, fn: Path | str | None = None, url: str | None = None,
|
|
436
|
-
compact: bool = True):
|
|
460
|
+
compact: bool = True, ref_mapper: Callable[[str], str] | None = None):
|
|
437
461
|
"""
|
|
438
462
|
:param fn: file to load the annotated schema from
|
|
439
463
|
:param url: URL to load the annotated schema from
|
|
@@ -441,6 +465,7 @@ class ContextBuilder:
|
|
|
441
465
|
self.context = {'@context': {}}
|
|
442
466
|
self._parsed_schemas: dict[str | Path, dict] = {}
|
|
443
467
|
self.compact = compact
|
|
468
|
+
self._ref_mapper = ref_mapper
|
|
444
469
|
|
|
445
470
|
context = self._build_context(fn, url)
|
|
446
471
|
self.context = {'@context': context}
|
|
@@ -482,7 +507,7 @@ class ContextBuilder:
|
|
|
482
507
|
if prefixes:
|
|
483
508
|
own_context.update(prefixes)
|
|
484
509
|
|
|
485
|
-
def read_properties(where: dict):
|
|
510
|
+
def read_properties(where: dict, into_context: dict):
|
|
486
511
|
if not isinstance(where, dict):
|
|
487
512
|
return
|
|
488
513
|
for prop, prop_val in where.get('properties', {}).items():
|
|
@@ -493,57 +518,56 @@ class ContextBuilder:
|
|
|
493
518
|
if ANNOTATION_TYPE in prop_val:
|
|
494
519
|
prop_context['@type'] = compact_uri(prop_val[ANNOTATION_TYPE])
|
|
495
520
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
521
|
+
process_subschema(prop_val, prop_context.setdefault('@context', {}))
|
|
522
|
+
|
|
523
|
+
if not prop_context['@context']:
|
|
524
|
+
prop_context.pop('@context', None)
|
|
499
525
|
|
|
500
|
-
if len(prop_context) == 1:
|
|
526
|
+
if isinstance(prop_context, dict) and len(prop_context) == 1:
|
|
501
527
|
# shorten to just the id
|
|
502
528
|
prop_context = next(iter(prop_context.values()))
|
|
503
529
|
|
|
504
|
-
|
|
530
|
+
into_context[prop] = prop_context
|
|
531
|
+
|
|
532
|
+
def process_subschema(ss, into_context: dict):
|
|
505
533
|
|
|
506
|
-
def process_subschema(ss):
|
|
507
534
|
if isinstance(ss, dict):
|
|
508
535
|
if '$ref' in ss:
|
|
509
536
|
ref_fn, ref_url = resolve_ref(ss['$ref'], fn, url, base_url)
|
|
510
537
|
merge_dicts(self._build_context(ref_fn, ref_url), own_context)
|
|
511
|
-
|
|
512
|
-
read_properties(ss)
|
|
538
|
+
read_properties(ss, into_context)
|
|
513
539
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
540
|
+
for i in ('allOf', 'anyOf', 'oneOf'):
|
|
541
|
+
l = ss.get(i)
|
|
542
|
+
if isinstance(l, list):
|
|
543
|
+
for sub_schema in l:
|
|
544
|
+
process_subschema(sub_schema, into_context)
|
|
519
545
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
546
|
+
for i in ('$defs', 'definitions'):
|
|
547
|
+
d = ss.get(i)
|
|
548
|
+
if isinstance(d, dict):
|
|
549
|
+
for sub_schema in d.values():
|
|
550
|
+
process_subschema(sub_schema, into_context)
|
|
525
551
|
|
|
526
|
-
|
|
552
|
+
process_subschema(schema, own_context)
|
|
527
553
|
|
|
528
554
|
if self.compact:
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
own_context = compact_context
|
|
555
|
+
|
|
556
|
+
def compact_branch(branch, existing_terms):
|
|
557
|
+
|
|
558
|
+
for term in list(branch.keys()):
|
|
559
|
+
if term[0] == '@':
|
|
560
|
+
# skip special terms
|
|
561
|
+
continue
|
|
562
|
+
if term in existing_terms and existing_terms[term] == branch[term]:
|
|
563
|
+
# same term exists in ancestor -> delete
|
|
564
|
+
del branch[term]
|
|
565
|
+
|
|
566
|
+
for term, term_value in branch.items():
|
|
567
|
+
if isinstance(term_value, dict) and '@context' in term_value:
|
|
568
|
+
compact_branch(term_value['@context'], {**existing_terms, **branch})
|
|
569
|
+
|
|
570
|
+
compact_branch(own_context, {})
|
|
547
571
|
|
|
548
572
|
self._parsed_schemas[fn or url] = own_context
|
|
549
573
|
return own_context
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ogc-na
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.11
|
|
4
4
|
Summary: OGC Naming Authority tools
|
|
5
5
|
Author-email: Rob Atkinson <ratkinson@ogc.org>, Piotr Zaborowski <pzaborowski@ogc.org>, Alejandro Villar <avillar@ogc.org>
|
|
6
6
|
Project-URL: Homepage, https://github.com/opengeospatial/ogc-na-tools/
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|