Skip to content

Commit 99d0529

Browse files
committed
Merge branch 'develop' into use_temporal_sorting_hints
2 parents 50d45da + 78dcbf3 commit 99d0529

File tree

79 files changed

+5036
-2601
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+5036
-2601
lines changed

.github/workflows/cicd.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ jobs:
3131
strategy:
3232
matrix:
3333
python-version:
34-
- '3.7'
35-
- '3.10'
34+
- '3.8'
35+
- '3.11'
3636

3737
steps:
3838
- uses: actions/checkout@v2

.github/workflows/supply-chain.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# This software was developed at the National Institute of Standards
2+
# and Technology by employees of the Federal Government in the course
3+
# of their official duties. Pursuant to title 17 Section 105 of the
4+
# United States Code this software is not subject to copyright
5+
# protection and is in the public domain. NIST assumes no
6+
# responsibility whatsoever for its use by other parties, and makes
7+
# no guarantees, expressed or implied, about its quality,
8+
# reliability, or any other characteristic.
9+
#
10+
# We would appreciate acknowledgement if the software is used.
11+
12+
# This workflow uses Make to review direct dependencies of this
13+
# repository.
14+
15+
name: Continuous Integration
16+
17+
on:
18+
schedule:
19+
- cron: '15 5 * * 1,2,3,4,5'
20+
21+
jobs:
22+
build:
23+
24+
runs-on: ubuntu-latest
25+
strategy:
26+
matrix:
27+
python-version:
28+
- '3.8'
29+
- '3.11'
30+
31+
steps:
32+
- uses: actions/checkout@v3
33+
- name: Set up Python ${{ matrix.python-version }}
34+
uses: actions/setup-python@v4
35+
with:
36+
python-version: ${{ matrix.python-version }}
37+
- name: Review dependencies
38+
run: make check-supply-chain

.pre-commit-config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111

1212
repos:
1313
- repo: https://github.com/psf/black
14-
rev: 22.3.0
14+
rev: 23.3.0
1515
hooks:
1616
- id: black
1717
- repo: https://github.com/pycqa/flake8
18-
rev: 4.0.1
18+
rev: 6.0.0
1919
hooks:
2020
- id: flake8
2121
- repo: https://github.com/pycqa/isort
22-
rev: 5.10.1
22+
rev: 5.12.0
2323
hooks:
2424
- id: isort
2525
name: isort (python)

Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ all: \
2525
--directory figures
2626

2727
.PHONY: \
28+
check-supply-chain \
29+
check-supply-chain-pre-commit \
2830
clean-figures \
2931
clean-tests
3032

@@ -72,6 +74,18 @@ check: \
7274
--directory tests \
7375
check
7476

77+
# This target's dependencies potentially modify the working directory's Git state, so it is intentionally not a dependency of check.
78+
check-supply-chain: \
79+
check-supply-chain-pre-commit
80+
81+
check-supply-chain-pre-commit: \
82+
.venv-pre-commit/var/.pre-commit-built.log
83+
source .venv-pre-commit/bin/activate \
84+
&& pre-commit autoupdate
85+
git diff \
86+
--exit-code \
87+
.pre-commit-config.yaml
88+
7589
clean: \
7690
clean-figures \
7791
clean-tests

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ This project follows [SEMVER 2.0.0](https://semver.org/) where versions are decl
6868

6969
This repository supports the CASE and UCO ontology versions that are distributed with the [CASE-Utilities-Python repository](https://github.com/casework/CASE-Utilities-Python), at the newest version below a ceiling-pin in [setup.cfg](setup.cfg). Currently, those ontology versions are:
7070

71-
* CASE 1.0.0
72-
* UCO 1.0.0
71+
* CASE 1.2.0
72+
* UCO 1.2.0
7373

7474

7575
## Repository locations

case_prov/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@
1111
#
1212
# We would appreciate acknowledgement if the software is used.
1313

14-
__version__ = "0.5.0"
14+
__version__ = "0.7.0"

case_prov/case_prov_dot.py

Lines changed: 98 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
# get quoted. This turns out to be a dot syntax error. Need to report
2222
# this upstream to pydot.
2323

24-
__version__ = "0.3.0"
24+
__version__ = "0.4.1"
2525

2626
import argparse
2727
import collections
@@ -41,7 +41,7 @@
4141

4242
_logger = logging.getLogger(os.path.basename(__file__))
4343

44-
NS_PROV = rdflib.Namespace("http://www.w3.org/ns/prov#")
44+
NS_PROV = rdflib.PROV
4545
NS_RDFS = rdflib.RDFS
4646
NS_TIME = rdflib.TIME
4747

@@ -140,7 +140,7 @@ def main() -> None:
140140
filter_iris: typing.Optional[typing.Set[str]] = None
141141
if args.from_empty_set:
142142
filter_iris = set()
143-
filter_iris.add("http://www.w3.org/ns/prov#EmptyCollection")
143+
filter_iris.add(str(NS_PROV.EmptyCollection))
144144
select_query_actions_text = """\
145145
SELECT ?nDerivingAction
146146
WHERE {
@@ -171,7 +171,7 @@ def main() -> None:
171171
?nEntity prov:wasDerivedFrom prov:EmptyCollection .
172172
}
173173
"""
174-
for (select_query_label, select_query_text) in [
174+
for select_query_label, select_query_text in [
175175
("activities", select_query_actions_text),
176176
("agents", select_query_agents_text),
177177
("entities", select_query_entities_text),
@@ -181,7 +181,9 @@ def main() -> None:
181181
select_query_text, initNs=nsdict
182182
)
183183
for record in graph.query(select_query_object):
184-
(n_include,) = record
184+
assert isinstance(record, rdflib.query.ResultRow)
185+
assert isinstance(record[0], rdflib.term.IdentifiedNode)
186+
n_include = record[0]
185187
filter_iri = n_include.toPython()
186188
filter_iris.add(filter_iri)
187189
_logger.debug("len(filter_iris) = %d.", len(filter_iris))
@@ -201,6 +203,7 @@ def main() -> None:
201203
query_ancestry_text, initNs=nsdict
202204
)
203205
for result in graph.query(query_ancestry_object):
206+
assert isinstance(result, rdflib.query.ResultRow)
204207
for result_member in result:
205208
if not isinstance(result_member, rdflib.URIRef):
206209
raise ValueError(
@@ -246,7 +249,7 @@ def main() -> None:
246249
?nEndIRI prov:wasDerivedFrom* ?nPrecedingEntity .
247250
}
248251
"""
249-
for (select_query_label, select_query_text) in [
252+
for select_query_label, select_query_text in [
250253
("activities", select_query_actions_text),
251254
("agents", select_query_agents_text),
252255
("entities", select_query_entities_text),
@@ -261,7 +264,9 @@ def main() -> None:
261264
select_query_object,
262265
initBindings={"nEndIRI": rdflib.URIRef(terminal_iri)},
263266
):
264-
(n_include,) = record
267+
assert isinstance(record, rdflib.query.ResultRow)
268+
assert isinstance(record[0], rdflib.term.IdentifiedNode)
269+
n_include = record[0]
265270
filter_iri = n_include.toPython()
266271
filter_iris.add(filter_iri)
267272
_logger.debug("len(filter_iris) = %d.", len(filter_iris))
@@ -317,8 +322,14 @@ def main() -> None:
317322
select_query_object = rdflib.plugins.sparql.processor.prepareQuery(
318323
select_query_text, initNs=nsdict
319324
)
320-
for record in graph.query(select_query_object):
321-
(n_agent, l_label, l_comment) = record
325+
for result in graph.query(select_query_object):
326+
assert isinstance(result, rdflib.query.ResultRow)
327+
assert isinstance(result[0], rdflib.term.IdentifiedNode)
328+
assert result[1] is None or isinstance(result[1], rdflib.Literal)
329+
assert result[2] is None or isinstance(result[2], rdflib.Literal)
330+
n_agent = result[0]
331+
l_label = result[1]
332+
l_comment = result[2]
322333
agent_iri = n_agent.toPython()
323334
dot_label = "ID - " + graph.namespace_manager.qname(agent_iri)
324335
if l_label is not None:
@@ -328,13 +339,13 @@ def main() -> None:
328339
kwargs = clone_style(prov.constants.PROV_AGENT)
329340
kwargs["label"] = dot_label
330341
# _logger.debug("Agent %r.", agent_iri)
331-
record = (iri_to_gv_node_id(agent_iri), kwargs)
332-
nodes[agent_iri] = record
333-
nodes_agents[agent_iri] = record
342+
node_record = (iri_to_gv_node_id(agent_iri), kwargs)
343+
nodes[agent_iri] = node_record
344+
nodes_agents[agent_iri] = node_record
334345
# _logger.debug("nodes = %s." % pprint.pformat(nodes))
335346

336347
# Find Collections, to adjust Entity rendering in the next block.
337-
collection_iris = {"http://www.w3.org/ns/prov#EmptyCollection"}
348+
collection_iris: typing.Set[str] = {str(NS_PROV.EmptyCollection)}
338349
select_query_text = """\
339350
SELECT ?nCollection
340351
WHERE {
@@ -345,16 +356,25 @@ def main() -> None:
345356
select_query_text, initNs=nsdict
346357
)
347358
for record in graph.query(select_query_object):
348-
(n_collection,) = record
359+
assert isinstance(record, rdflib.query.ResultRow)
360+
assert isinstance(record[0], rdflib.term.IdentifiedNode)
361+
n_collection = record[0]
349362
collection_iri = n_collection.toPython()
350363
collection_iris.add(collection_iri)
351364
# _logger.debug("len(collection_iris) = %d.", len(collection_iris))
352365

353366
# Render Entities.
354367
# This loop operates differently from the others, to insert prov:EmptyCollection.
355-
entity_iri_to_label_comment = dict()
368+
entity_iri_to_label_comment: typing.Dict[
369+
str,
370+
typing.Tuple[
371+
typing.Optional[rdflib.Literal],
372+
typing.Optional[rdflib.Literal],
373+
typing.Optional[rdflib.Literal],
374+
],
375+
] = dict()
356376
if not args.omit_empty_set:
357-
entity_iri_to_label_comment["http://www.w3.org/ns/prov#EmptyCollection"] = (
377+
entity_iri_to_label_comment[str(NS_PROV.EmptyCollection)] = (
358378
None,
359379
None,
360380
None,
@@ -380,28 +400,48 @@ def main() -> None:
380400
select_query_object = rdflib.plugins.sparql.processor.prepareQuery(
381401
select_query_text, initNs=nsdict
382402
)
403+
l_entity_label: typing.Optional[rdflib.Literal]
404+
l_entity_comment: typing.Optional[rdflib.Literal]
405+
l_entity_exhibit_number: typing.Optional[rdflib.Literal]
383406
for record in graph.query(select_query_object):
384-
(n_entity, l_label, l_comment, l_exhibit_number) = record
407+
assert isinstance(record, rdflib.query.ResultRow)
408+
assert isinstance(record[0], rdflib.term.IdentifiedNode)
409+
assert record[1] is None or isinstance(record[1], rdflib.Literal)
410+
assert record[2] is None or isinstance(record[2], rdflib.Literal)
411+
assert record[3] is None or isinstance(record[3], rdflib.Literal)
412+
n_entity = record[0]
413+
l_entity_label = record[1]
414+
l_entity_comment = record[2]
415+
l_entity_exhibit_number = record[3]
416+
385417
entity_iri = n_entity.toPython()
386-
entity_iri_to_label_comment[entity_iri] = (l_label, l_comment, l_exhibit_number)
418+
entity_iri_to_label_comment[entity_iri] = (
419+
l_entity_label,
420+
l_entity_comment,
421+
l_entity_exhibit_number,
422+
)
387423
for entity_iri in sorted(entity_iri_to_label_comment):
388-
(l_label, l_comment, l_exhibit_number) = entity_iri_to_label_comment[entity_iri]
424+
(
425+
l_entity_label,
426+
l_entity_comment,
427+
l_entity_exhibit_number,
428+
) = entity_iri_to_label_comment[entity_iri]
389429
dot_label = "ID - " + graph.namespace_manager.qname(entity_iri)
390-
if l_exhibit_number is not None:
391-
dot_label += "\nExhibit - " + l_exhibit_number.toPython()
392-
if l_label is not None:
393-
dot_label += "\n" + l_label.toPython()
394-
if l_comment is not None:
395-
dot_label += "\n\n" + "\n".join(wrapper.wrap((l_comment.toPython())))
430+
if l_entity_exhibit_number is not None:
431+
dot_label += "\nExhibit - " + l_entity_exhibit_number.toPython()
432+
if l_entity_label is not None:
433+
dot_label += "\n" + l_entity_label.toPython()
434+
if l_entity_comment is not None:
435+
dot_label += "\n\n" + "\n".join(wrapper.wrap((l_entity_comment.toPython())))
396436
if entity_iri in collection_iris:
397437
kwargs = clone_style(PROV_COLLECTION)
398438
else:
399439
kwargs = clone_style(prov.constants.PROV_ENTITY)
400440
kwargs["label"] = dot_label
401441
# _logger.debug("Entity %r.", entity_iri)
402-
record = (iri_to_gv_node_id(entity_iri), kwargs)
403-
nodes[entity_iri] = record
404-
nodes_entities[entity_iri] = record
442+
entity_record = (iri_to_gv_node_id(entity_iri), kwargs)
443+
nodes[entity_iri] = entity_record
444+
nodes_entities[entity_iri] = entity_record
405445

406446
# Render Activities.
407447
select_query_text = """\
@@ -430,7 +470,18 @@ def main() -> None:
430470
select_query_text, initNs=nsdict
431471
)
432472
for record in graph.query(select_query_object):
433-
(n_activity, l_label, l_comment, l_start_time, l_end_time) = record
473+
assert isinstance(record, rdflib.query.ResultRow)
474+
assert isinstance(record[0], rdflib.term.IdentifiedNode)
475+
assert record[1] is None or isinstance(record[1], rdflib.Literal)
476+
assert record[2] is None or isinstance(record[2], rdflib.Literal)
477+
assert record[3] is None or isinstance(record[3], rdflib.Literal)
478+
assert record[4] is None or isinstance(record[4], rdflib.Literal)
479+
n_activity = record[0]
480+
l_label = record[1]
481+
l_comment = record[2]
482+
l_start_time = record[3]
483+
l_end_time = record[4]
484+
434485
activity_iri = n_activity.toPython()
435486
dot_label = "ID - " + graph.namespace_manager.qname(activity_iri)
436487
if l_label is not None:
@@ -449,9 +500,9 @@ def main() -> None:
449500
kwargs = clone_style(prov.constants.PROV_ACTIVITY)
450501
kwargs["label"] = dot_label
451502
# _logger.debug("Activity %r.", activity_iri)
452-
record = (iri_to_gv_node_id(activity_iri), kwargs)
453-
nodes[activity_iri] = record
454-
nodes_activities[activity_iri] = record
503+
activity_record = (iri_to_gv_node_id(activity_iri), kwargs)
504+
nodes[activity_iri] = activity_record
505+
nodes_activities[activity_iri] = activity_record
455506

456507
def _render_edges(
457508
select_query_text: str,
@@ -463,15 +514,22 @@ def _render_edges(
463514
select_query_text, initNs=nsdict
464515
)
465516
for record in graph.query(select_query_object):
466-
(n_thing_1, n_thing_2) = record
517+
assert isinstance(record, rdflib.query.ResultRow)
518+
assert isinstance(record[0], rdflib.term.IdentifiedNode)
519+
assert isinstance(record[1], rdflib.term.IdentifiedNode)
520+
n_thing_1 = record[0]
521+
n_thing_2 = record[1]
522+
467523
thing_1_iri = n_thing_1.toPython()
468524
thing_2_iri = n_thing_2.toPython()
469525
gv_node_id_1 = iri_to_gv_node_id(thing_1_iri)
470526
gv_node_id_2 = iri_to_gv_node_id(thing_2_iri)
471-
record = (gv_node_id_1, gv_node_id_2, kwargs)
472-
edges[thing_1_iri][thing_2_iri][short_edge_label] = record
527+
edge_record = (gv_node_id_1, gv_node_id_2, kwargs)
528+
edges[thing_1_iri][thing_2_iri][short_edge_label] = edge_record
473529
if supplemental_dict is not None:
474-
supplemental_dict[thing_1_iri][thing_2_iri][short_edge_label] = record
530+
supplemental_dict[thing_1_iri][thing_2_iri][
531+
short_edge_label
532+
] = edge_record
475533

476534
# Render actedOnBehalfOf.
477535
select_query_text = """\
@@ -766,10 +824,10 @@ def _render_edges(
766824
continue
767825
for short_edge_label in sorted(edges[iri_1][iri_2]):
768826
# short_edge_label is intentionally not used aside from as a selector. Edge labelling is left to pydot.
769-
record = edges[iri_1][iri_2][short_edge_label]
770-
node_id_1 = record[0]
771-
node_id_2 = record[1]
772-
kwargs = record[2]
827+
edge_record = edges[iri_1][iri_2][short_edge_label]
828+
node_id_1 = edge_record[0]
829+
node_id_2 = edge_record[1]
830+
kwargs = edge_record[2]
773831
dot_edge = pydot.Edge(node_id_1, node_id_2, **kwargs)
774832
dot_graph.add_edge(dot_edge)
775833

0 commit comments

Comments
 (0)