Skip to content

Commit

Permalink
"extends" property and circular dependency detection
Browse files Browse the repository at this point in the history
  • Loading branch information
avillar committed Aug 2, 2023
1 parent 69ae2b7 commit 2d061c6
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 0 deletions.
19 changes: 19 additions & 0 deletions ogc/bblocks/metadata-schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,22 @@ properties:
type: array
items:
type: string
extends:
description: |
Used to declare that the schema for this Building Block extends another one. The schemas will be joined
with an "allOf" declaration.
oneOf:
- description: Identifier of the base Building Block to extend
type: string
- type: object
required:
- itemIdentifier
properties:
itemIdentifier:
description: Identifier of the base Building Block to extend
type: string
path:
description: |
Property path where the schema for this Building Block will be inserted, in the format "a.b.c.d".
If a property is an array, "prop[]" notation can be used (e.g., "a.b[].c.d[]").
type: string
17 changes: 17 additions & 0 deletions ogc/bblocks/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from typing import Any, Sequence, Callable

import jsonschema
import networkx as nx
from ogc.na.annotate_schema import SchemaAnnotator, ContextBuilder
from ogc.na.util import load_yaml, dump_yaml, is_url

Expand Down Expand Up @@ -149,6 +150,7 @@ def jsonld_context_contents(self):
self._lazy_properties['jsonld_context_contents'] = load_file(self.jsonld_context)
return self._lazy_properties['jsonld_context_contents']


class BuildingBlockRegister:

def __init__(self,
Expand Down Expand Up @@ -191,15 +193,23 @@ def __init__(self,
print('=========', file=sys.stderr)

if find_dependencies:
dep_graph = nx.DiGraph()

for bblock in self.bblocks.values():
found_deps = self.find_dependencies(bblock)
dep_graph.add_edges_from([(d, bblock.identifier) for d in found_deps])
deps = bblock.metadata.get('dependsOn')
if isinstance(deps, str):
found_deps.add(deps)
elif isinstance(deps, list):
found_deps.update(deps)
if found_deps:
bblock.metadata['dependsOn'] = list(found_deps)
cycles = list(nx.simple_cycles(dep_graph))
if cycles:
cycles_str = '\n - '.join(' -> '.join(reversed(c)) + ' -> ' + c[-1] for c in cycles)
raise BuildingBlockError(f"Circular dependencies found: \n - {cycles_str}")
self.bblocks = {b: self.bblocks[b] for b in nx.topological_sort(dep_graph) if b in self.bblocks}

def find_dependencies(self, bblock: BuildingBlock) -> set[str]:
if not bblock.schema.is_file():
Expand Down Expand Up @@ -230,6 +240,13 @@ def walk_schema(schema):

walk_schema(bblock_schema)

extends = bblock.metadata.get('extends')
if extends:
if isinstance(extends, str):
deps.add(extends)
elif isinstance(extends, dict):
deps.add(extends['itemIdentifier'])

return deps


Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ pyparsing~=3.0.9
pyshacl~=0.21.0
rdflib~=6.3.2
jsonref~=1.1.0
networkx

0 comments on commit 2d061c6

Please sign in to comment.