kgm 2.0.0__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.
Files changed (146) hide show
  1. kgm-2.0.0/.github/workflows/pypi.yml +29 -0
  2. kgm-2.0.0/.github/workflows/validate.yml +32 -0
  3. kgm-2.0.0/.gitignore +3 -0
  4. kgm-2.0.0/.python-version +1 -0
  5. kgm-2.0.0/LICENSE +29 -0
  6. kgm-2.0.0/PKG-INFO +486 -0
  7. kgm-2.0.0/README.md +468 -0
  8. kgm-2.0.0/Taskfile.yml +41 -0
  9. kgm-2.0.0/docker-compose.yml +15 -0
  10. kgm-2.0.0/kgm/__init__.py +13 -0
  11. kgm-2.0.0/kgm/cli/__init__.py +18 -0
  12. kgm-2.0.0/kgm/cli/app.py +60 -0
  13. kgm-2.0.0/kgm/cli/commands/__init__.py +0 -0
  14. kgm-2.0.0/kgm/cli/commands/document.py +37 -0
  15. kgm-2.0.0/kgm/cli/commands/event/__init__.py +0 -0
  16. kgm-2.0.0/kgm/cli/commands/event/asb.py +52 -0
  17. kgm-2.0.0/kgm/cli/commands/event/cli.py +19 -0
  18. kgm-2.0.0/kgm/cli/commands/event/rdf_delta.py +43 -0
  19. kgm-2.0.0/kgm/cli/commands/label.py +97 -0
  20. kgm-2.0.0/kgm/cli/commands/load.py +47 -0
  21. kgm-2.0.0/kgm/cli/commands/sync.py +75 -0
  22. kgm-2.0.0/kgm/cli/commands/validate.py +17 -0
  23. kgm-2.0.0/kgm/cli/console.py +3 -0
  24. kgm-2.0.0/kgm/definednamespaces.py +41 -0
  25. kgm-2.0.0/kgm/documentor.py +190 -0
  26. kgm-2.0.0/kgm/event/__init__.py +0 -0
  27. kgm-2.0.0/kgm/event/asb_client.py +51 -0
  28. kgm-2.0.0/kgm/event/client.py +40 -0
  29. kgm-2.0.0/kgm/event/syncer.py +293 -0
  30. kgm-2.0.0/kgm/labeller.py +104 -0
  31. kgm-2.0.0/kgm/loader.py +314 -0
  32. kgm-2.0.0/kgm/mrr.ttl +87 -0
  33. kgm-2.0.0/kgm/syncer.py +345 -0
  34. kgm-2.0.0/kgm/system-labels.ttl +6 -0
  35. kgm-2.0.0/kgm/utils.py +857 -0
  36. kgm-2.0.0/kgm/validator.py +150 -0
  37. kgm-2.0.0/kgm/validator.ttl +209 -0
  38. kgm-2.0.0/pyproject.toml +36 -0
  39. kgm-2.0.0/tests/conftest.py +66 -0
  40. kgm-2.0.0/tests/demo-vocabs/_background/labels.ttl +153 -0
  41. kgm-2.0.0/tests/demo-vocabs/catalogue-metadata.ttl +20 -0
  42. kgm-2.0.0/tests/demo-vocabs/catalogue.ttl +23 -0
  43. kgm-2.0.0/tests/demo-vocabs/labels-2.ttl +7 -0
  44. kgm-2.0.0/tests/demo-vocabs/labels-all.ttl +172 -0
  45. kgm-2.0.0/tests/demo-vocabs/labels-none.ttl +0 -0
  46. kgm-2.0.0/tests/demo-vocabs/labels-some.ttl +94 -0
  47. kgm-2.0.0/tests/demo-vocabs/language-testx.ttl +146 -0
  48. kgm-2.0.0/tests/demo-vocabs/local-validator-for-invalid.ttl +33 -0
  49. kgm-2.0.0/tests/demo-vocabs/local-validator.ttl +34 -0
  50. kgm-2.0.0/tests/demo-vocabs/manifest-cat.ttl +33 -0
  51. kgm-2.0.0/tests/demo-vocabs/manifest-conformance-all-local-invalid.ttl +40 -0
  52. kgm-2.0.0/tests/demo-vocabs/manifest-conformance-all.ttl +40 -0
  53. kgm-2.0.0/tests/demo-vocabs/manifest-conformance-invalid.ttl +40 -0
  54. kgm-2.0.0/tests/demo-vocabs/manifest-conformance-local-invalid.ttl +40 -0
  55. kgm-2.0.0/tests/demo-vocabs/manifest-conformance-local.ttl +40 -0
  56. kgm-2.0.0/tests/demo-vocabs/manifest-conformance.ttl +40 -0
  57. kgm-2.0.0/tests/demo-vocabs/manifest-invalid-01.ttl +33 -0
  58. kgm-2.0.0/tests/demo-vocabs/manifest-invalid-02.ttl +33 -0
  59. kgm-2.0.0/tests/demo-vocabs/manifest-invalid-03.ttl +33 -0
  60. kgm-2.0.0/tests/demo-vocabs/manifest-labels-all.ttl +26 -0
  61. kgm-2.0.0/tests/demo-vocabs/manifest-labels-none.ttl +18 -0
  62. kgm-2.0.0/tests/demo-vocabs/manifest-labels-some.ttl +26 -0
  63. kgm-2.0.0/tests/demo-vocabs/manifest-mainEntity-invalid.ttl +38 -0
  64. kgm-2.0.0/tests/demo-vocabs/manifest-mainEntity-invalid2.ttl +37 -0
  65. kgm-2.0.0/tests/demo-vocabs/manifest-mainEntity.ttl +38 -0
  66. kgm-2.0.0/tests/demo-vocabs/manifest-multi.ttl +35 -0
  67. kgm-2.0.0/tests/demo-vocabs/manifest-no-labels_additional-labels.ttl +136 -0
  68. kgm-2.0.0/tests/demo-vocabs/manifest-version-indicators.ttl +42 -0
  69. kgm-2.0.0/tests/demo-vocabs/manifest.ttl +33 -0
  70. kgm-2.0.0/tests/demo-vocabs/vocabs/image-test.ttl +55 -0
  71. kgm-2.0.0/tests/demo-vocabs/vocabs/language-test.ttl +134 -0
  72. kgm-2.0.0/tests/fuseki/config.ttl +145 -0
  73. kgm-2.0.0/tests/fuseki/shiro.ini +27 -0
  74. kgm-2.0.0/tests/semback/cat-01/agents.ttl +20 -0
  75. kgm-2.0.0/tests/semback/cat-01/catalogue.ttl +19 -0
  76. kgm-2.0.0/tests/semback/cat-01/item-01.ttl +15 -0
  77. kgm-2.0.0/tests/semback/cat-01/item-02.ttl +99 -0
  78. kgm-2.0.0/tests/semback/cat-01/labels.ttl +0 -0
  79. kgm-2.0.0/tests/semback/cat-01/manifest.ttl +37 -0
  80. kgm-2.0.0/tests/t.py +21 -0
  81. kgm-2.0.0/tests/test_documentor.py +210 -0
  82. kgm-2.0.0/tests/test_labeller.py +299 -0
  83. kgm-2.0.0/tests/test_loader.py +268 -0
  84. kgm-2.0.0/tests/test_sync/local/artifact4.ttl +14 -0
  85. kgm-2.0.0/tests/test_sync/local/artifact5.ttl +13 -0
  86. kgm-2.0.0/tests/test_sync/local/artifact6.ttl +10 -0
  87. kgm-2.0.0/tests/test_sync/local/artifact7.ttl +20 -0
  88. kgm-2.0.0/tests/test_sync/local/artifact9.ttl +12 -0
  89. kgm-2.0.0/tests/test_sync/local/artifacts/artifact1.ttl +12 -0
  90. kgm-2.0.0/tests/test_sync/local/artifacts/artifact2.ttl +12 -0
  91. kgm-2.0.0/tests/test_sync/local/artifacts/artifact3.ttl +14 -0
  92. kgm-2.0.0/tests/test_sync/local/catalogue.ttl +24 -0
  93. kgm-2.0.0/tests/test_sync/local/labels.ttl +83 -0
  94. kgm-2.0.0/tests/test_sync/local/manifest-sync-pred.ttl +45 -0
  95. kgm-2.0.0/tests/test_sync/local/manifest.ttl +38 -0
  96. kgm-2.0.0/tests/test_sync/manifest-cat.ttl +28 -0
  97. kgm-2.0.0/tests/test_sync/manifest-nocat.ttl +24 -0
  98. kgm-2.0.0/tests/test_sync/remote/artifact1.ttl +12 -0
  99. kgm-2.0.0/tests/test_sync/remote/artifact2.ttl +12 -0
  100. kgm-2.0.0/tests/test_sync/remote/artifact3.ttl +14 -0
  101. kgm-2.0.0/tests/test_sync/remote/artifact4.ttl +14 -0
  102. kgm-2.0.0/tests/test_sync/remote/artifact6.ttl +12 -0
  103. kgm-2.0.0/tests/test_sync/remote/artifact7.ttl +20 -0
  104. kgm-2.0.0/tests/test_sync/remote/artifact8.ttl +12 -0
  105. kgm-2.0.0/tests/test_sync/remote/artifact9.ttl +12 -0
  106. kgm-2.0.0/tests/test_sync/remote/catalogue.ttl +24 -0
  107. kgm-2.0.0/tests/test_sync/remote/http--example.com-dataset-1.ttl +10 -0
  108. kgm-2.0.0/tests/test_sync/remote/http--example.com-dataset-2.ttl +10 -0
  109. kgm-2.0.0/tests/test_sync/remote/http--example.com-dataset-3.ttl +12 -0
  110. kgm-2.0.0/tests/test_sync/remote/http--example.com-dataset-4.ttl +11 -0
  111. kgm-2.0.0/tests/test_sync/remote/http--example.com-dataset-6.ttl +10 -0
  112. kgm-2.0.0/tests/test_sync/remote/http--example.com-dataset-7.ttl +18 -0
  113. kgm-2.0.0/tests/test_sync/remote/http--example.com-dataset-8.ttl +10 -0
  114. kgm-2.0.0/tests/test_sync/remote/labels.ttl +77 -0
  115. kgm-2.0.0/tests/test_sync/remote/manifest.ttl +88 -0
  116. kgm-2.0.0/tests/test_sync/test_sync.py +293 -0
  117. kgm-2.0.0/tests/test_sync_rdf_delta/test_canonicalization.py +323 -0
  118. kgm-2.0.0/tests/test_sync_rdf_delta/test_chunking.py +306 -0
  119. kgm-2.0.0/tests/test_sync_rdf_delta/test_e2e_sync_asb/config.json +37 -0
  120. kgm-2.0.0/tests/test_sync_rdf_delta/test_e2e_sync_asb/conftest.py +48 -0
  121. kgm-2.0.0/tests/test_sync_rdf_delta/test_e2e_sync_asb/docker-compose.yml +41 -0
  122. kgm-2.0.0/tests/test_sync_rdf_delta/test_e2e_sync_asb/test_e2e_cli_asb.py +92 -0
  123. kgm-2.0.0/tests/test_sync_rdf_delta/test_e2e_sync_rdf_delta/conftest.py +53 -0
  124. kgm-2.0.0/tests/test_sync_rdf_delta/test_e2e_sync_rdf_delta/docker-compose.yml +17 -0
  125. kgm-2.0.0/tests/test_sync_rdf_delta/test_e2e_sync_rdf_delta/test_e2e_cli_rdf_delta.py +62 -0
  126. kgm-2.0.0/tests/test_sync_rdf_delta/test_e2e_sync_rdf_delta/test_e2e_icsm_vocabs.py +152 -0
  127. kgm-2.0.0/tests/test_sync_rdf_delta/test_e2e_sync_rdf_delta/test_e2e_sync_rdf_delta_function.py +54 -0
  128. kgm-2.0.0/tests/test_sync_rdf_delta/test_sync_rdf_delta_commit_hash.py +77 -0
  129. kgm-2.0.0/tests/test_utils.py +347 -0
  130. kgm-2.0.0/tests/test_validator.py +137 -0
  131. kgm-2.0.0/tests/utils/main-entity-tests/artifact-unknown-class.ttl +10 -0
  132. kgm-2.0.0/tests/utils/main-entity-tests/manifest-base.ttl +13 -0
  133. kgm-2.0.0/tests/utils/main-entity-tests/manifest-class.ttl +14 -0
  134. kgm-2.0.0/tests/utils/main-entity-tests/manifest-instance-resource.ttl +17 -0
  135. kgm-2.0.0/tests/utils/main-entity-tests/manifest-instance.ttl +17 -0
  136. kgm-2.0.0/tests/utils/main-entity-tests/sub/artifact-unknown-class.ttl +10 -0
  137. kgm-2.0.0/tests/utils/main-entity-tests/sub/manifest-instance.2.ttl +17 -0
  138. kgm-2.0.0/tests/utils/main-entity-tests/sub/manifest-instance.ttl +17 -0
  139. kgm-2.0.0/tests/utils/main-entity-tests/sub/subsub/artifact-unknown-class.ttl +9 -0
  140. kgm-2.0.0/tests/validator/cs-ok.ttl +99 -0
  141. kgm-2.0.0/tests/validator/cs-syntax-error.ttl +101 -0
  142. kgm-2.0.0/tests/validator/gki.ttl +111 -0
  143. kgm-2.0.0/tests/validator/manifest-conformance-own.ttl +17 -0
  144. kgm-2.0.0/tests/validator/manifest-syntax-error.ttl +19 -0
  145. kgm-2.0.0/tests/validator/validator-gn.ttl +44 -0
  146. kgm-2.0.0/uv.lock +999 -0
@@ -0,0 +1,29 @@
1
+ name: pypi
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ pypi-publish:
9
+ name: upload release to PyPI
10
+ runs-on: ubuntu-latest
11
+ # Specifying a GitHub environment is optional, but strongly encouraged
12
+ environment: pypi
13
+ permissions:
14
+ # IMPORTANT: this permission is mandatory for Trusted Publishing
15
+ id-token: write
16
+ steps:
17
+ - uses: actions/checkout@v5
18
+
19
+ - name: Install uv
20
+ uses: astral-sh/setup-uv@v7
21
+
22
+ - name: Install dependencies
23
+ run: uv sync
24
+
25
+ - name: Build package
26
+ run: uv build
27
+
28
+ - name: Publish package distributions to PyPI
29
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,32 @@
1
+ name: Validate
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ types: [ opened, edited, synchronize ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - name: Checkout code
15
+ uses: actions/checkout@v6
16
+
17
+ - name: Set up Python
18
+ uses: actions/setup-python@v6
19
+ with:
20
+ python-version: "3.12"
21
+
22
+ - name: Install uv
23
+ uses: astral-sh/setup-uv@v7
24
+
25
+ - name: Install Taskfile
26
+ uses: arduino/setup-task@v2
27
+
28
+ - name: Install dependencies
29
+ run: uv sync --extra azure
30
+
31
+ - name: Run tests
32
+ run: task test
kgm-2.0.0/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ .idea/
2
+ **/__pycache__/
3
+ fuseki-data/
@@ -0,0 +1 @@
1
+ 3.12
kgm-2.0.0/LICENSE ADDED
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2024-2025, KurrawongAI
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
kgm-2.0.0/PKG-INFO ADDED
@@ -0,0 +1,486 @@
1
+ Metadata-Version: 2.4
2
+ Name: kgm
3
+ Version: 2.0.0
4
+ Summary: A Python package that provides a series of functions to work with KGs & RDF files.
5
+ Author-email: Nicholas Car <nick@kurrawong.ai>
6
+ License-Expression: BSD-3-Clause
7
+ License-File: LICENSE
8
+ Requires-Python: <4.0,>=3.12
9
+ Requires-Dist: dateutils>=0.6.12
10
+ Requires-Dist: gitpython>=3.1.45
11
+ Requires-Dist: kurra>=3.0.4
12
+ Requires-Dist: rdf-delta>=0.2.5
13
+ Requires-Dist: rdflib>=7.6.0
14
+ Requires-Dist: typer<0.16,>=0.15.1
15
+ Provides-Extra: azure
16
+ Requires-Dist: azure-servicebus>=7.14.3; extra == 'azure'
17
+ Description-Content-Type: text/markdown
18
+
19
+ # KGM
20
+
21
+ KGM is a tool that performs data management functions for [Knowledge Graphs](https://en.wikipedia.org/wiki/Knowledge_graph)and with [RDF](https://en.wikipedia.org/wiki/Resource_Description_Framework) data files. These include synchronising
22
+ data loaded into KGs with RDF files in directories, obtaining labels for IRIs in KGs and more
23
+
24
+ The tool is implemented as a Python command line application and code library.
25
+
26
+ ## Contents
27
+
28
+ * [What is a KGM Manifest?](#what-is-a-kgm-manifest)
29
+ * [Functions](#functions)
30
+ * [Installation](#installation)
31
+ * [Use](#use)
32
+ * [Testing](#testing)
33
+ * [Extending](#extending)
34
+ * [License](#license)
35
+ * [Contact](#contact)
36
+ * [Case Studies](#case-studies)
37
+ * [Manifest Data Model](#manifest-data-model)
38
+
39
+ ## What is a kgm Manifest?
40
+
41
+ A KGM _Manifest_ is an RDF file that describes and links to a set of files, usually stored in version control, that can
42
+ be validated and managed by the KGM tool. Usual management goals are:
43
+
44
+ * **validation** - checking content conforms to [SHACL Shapes Graphs](https://www.w3.org/TR/shacl12-core/#shapes-graph)
45
+ * **synchronisation** - maintaining data in an RDF DB up-to-date with files
46
+ * **labelling** - finding things that are missing labels and proving labels
47
+
48
+ A simple Manifest file, for [Geoscience Australia's vocabularies]() online at <https://github.com/GeoscienceAustralia/ga-vocabs/blob/master/manifest.ttl>, looks like this:
49
+
50
+ ```turtle
51
+ PREFIX dcterms: <http://purl.org/dc/terms/>
52
+ PREFIX mrr: <https://prez.dev/ManifestResourceRoles/>
53
+ PREFIX prez: <https://prez.dev/>
54
+ PREFIX prof: <http://www.w3.org/ns/dx/prof/>
55
+ PREFIX schema: <https://schema.org/>
56
+
57
+ []
58
+ a prez:Manifest ;
59
+ prof:hasResource
60
+ [
61
+ prof:hasartefact "catalogue.ttl" ;
62
+ prof:hasRole mrr:CatalogueData ;
63
+ schema:name "Catalogue Definition" ;
64
+ ] ,
65
+ [
66
+ prof:hasartefact "vocabularies/*.ttl" ;
67
+ prof:hasRole mrr:ResourceData ;
68
+ schema:name "Resource Data" ;
69
+ dcterms:conformsTo <https://linked.data.gov.au/def/vocpub/validator> ;
70
+ ] ,
71
+ [
72
+ prof:hasartefact "labels.ttl" ;
73
+ prof:hasRole mrr:CompleteCatalogueAndResourceLabels ;
74
+ schema:name "Labels" ;
75
+ ] ;
76
+ .
77
+ ```
78
+
79
+ In the file above, we have a `prez:Manifest` object which has 3 `prof:resource` instances, one for the "Catalogue
80
+ Definition", the vocabularies - "Resource Data" - and "Labels". The vocabularies are shown to be conformant to the
81
+ [VocPub profile of SKOS](https://linked.data.gov.au/def/vocpub/spec) which they will be validated against before any
82
+ data synchronisation.
83
+
84
+ The complete data model of a KGM Manifest file is online at: <https://prez.dev/manifest/>.
85
+
86
+ ## Functions
87
+
88
+ The functions provided by KGM are discoverable by running the tool as a command line application - see [Command Line](#command-line) below - and are:
89
+
90
+ * **validate**
91
+ * performs SHACL validation on the Manifest, followed by existence checking for each resource - are they reachable
92
+ by this script on the file system or over the Internet? Will also check
93
+ any [Conformance Claims](#conformance-claims) given in the Manifest)
94
+ * **label**
95
+ * lists all the IRIs for elements within a Manifest's resources that don't have labels. Given a source of additional
96
+ labels, it can try to extract any
97
+ missing labels and insert them into a Manifest as an additional labelling resource
98
+ * [KurrawongAI's Semantic Background](#kurrawongai-semantic-background) is included as a source of labels be default
99
+ * **document**
100
+ * **table**: can create a Markdown or ASCIIDOC table of Resources from a KGM file for use in README files
101
+ in repositories
102
+ * **catalogue**: add the IRIs of resources within a Manifest's 'Resource Data' object to a catalogue RDF file
103
+ * **sync**
104
+ * synchronises resources listed in a Manifest with versions of them in a SPARQL Endpoint
105
+ * acts as `load` if run against an empty SPARQL Endpoint
106
+ * does not yet load background resources
107
+ * **event**
108
+ * event-based KGMs actions - for advanced systems use
109
+
110
+ ## Installation
111
+
112
+ This Python package is intended to be used as a Python library, called directly from other Python code, or on the
113
+ command line on Linux/UNIX-like systems.
114
+
115
+ ### Library
116
+
117
+ It is available on [PyPI](https://pypi.org) at <https://pypi.org/project/kgm/> so can be installed
118
+ using [Poetry](https://python-poetry.org) or PIP etc. We do recommend [UV](https://github.com/astral-sh/uv) as that's
119
+ the package manager we find easiest to work with.
120
+
121
+ ### Command Line
122
+
123
+ To make available the command line script `kgm` you need to first install `UV`, see
124
+ the [uv installation instructions](https://docs.astral.sh/uv/getting-started/installation/), then:
125
+
126
+ ```bash
127
+ uv tool install kgm
128
+ ```
129
+
130
+ Now you can invoke `kgm` anywhere in your terminal as long as `/local/bin/` is in your `PATH`.
131
+
132
+ ### Latest
133
+
134
+ You can also always install the latest, unstable, release from its version control
135
+ repository: <https://github.com/Kurrawong/kgm/>, but we make KGM releases often, so the latest
136
+ shouldn't ever be too far ahead of the most recent release.
137
+
138
+ ## Use
139
+
140
+ > [!TIP]
141
+ > See the [Case Study: Establish](#case-study-establish) below for a short description of the
142
+ > establishment of a new catalogue using KGM.
143
+
144
+ ### Library
145
+
146
+ Install as above and then, in your Python code, import the functions you want to use. Currently, these are the public
147
+ functions:
148
+
149
+ ```python
150
+ from kgm.validator import validate
151
+ from kgm.labeller import LabellerOutputTypes, label
152
+ from kgm.documentor import table, catalogue
153
+ from kgm.loader import load
154
+ from kgm.syncer import sync
155
+ ```
156
+
157
+ ### Command Line
158
+
159
+ All the functions of the library are made available as a command line application called `kgm`. After installation, as
160
+ above, you can inspect the command line tool by asking for "help" like this:
161
+
162
+ ```bash
163
+ kgm -h
164
+ ```
165
+
166
+ Which will print something like this:
167
+
168
+ ```bash
169
+ Usage: kgm [OPTIONS] COMMAND [ARGS]...
170
+
171
+ KGM top-level Command Line Interface. Ask for help (-h) for each Command
172
+
173
+ ╭─ Options ────────────────────────────────────────────────────────────────────────╮
174
+ │ --version -v │
175
+ │ --help -h Show this message and exit. │
176
+ ╰──────────────────────────────────────────────────────────────────────────────────╯
177
+ ╭─ Commands ───────────────────────────────────────────────────────────────────────╮
178
+ │ validate Validate the structure and content of a KGM │
179
+ │ sync Synchronize a KGM's resources with loaded copies of them in │
180
+ │ a SPARQL Endpoint │
181
+ │ label Discover labels missing from data in a in a KGM and patch │
182
+ │ them │
183
+ │ document Create documentation from a KGM │
184
+ │ load Load a KGM's content into a file or DB │
185
+ │ event Event-based KGMs actions │
186
+ ╰──────────────────────────────────────────────────────────────────────────────────╯
187
+ ```
188
+
189
+ To find out more about each Command, ask for helo like this - for load:
190
+
191
+ ```bash
192
+ kgm load -h
193
+ ```
194
+
195
+ > [!NOTE]
196
+ > If (when?) KGM runs into problems such as trying to synchronise resources between files and an RDF DB with missmatching version numbers, you can always run [kurra](https://github.com/kurrawong.kurra) commands to directly manage DB resources.
197
+ >
198
+ > For example, you can run `kurra db gsp put {FILE} {SPARQL-ENDPOINT} -g {GRAPH-NAME}` to force a replacement of the grapf, `GRAPH-NAME`, in the RDF DB with the contents of the `FILE`.
199
+
200
+ #### Logging
201
+
202
+ You can control the verbosity of the command line tool by setting the `KGM_LOG_LEVEL` environment variable to one of
203
+ Python's standard logging levels: `DEBUG`, `INFO`, `WARNING`, `ERROR`, or `CRITICAL`. The default level is `WARNING`.
204
+
205
+ For example, to see detailed debug output:
206
+
207
+ ```bash
208
+ KGM_LOG_LEVEL=DEBUG kgm load file my-manifest.ttl output.trig
209
+ ```
210
+
211
+ Or for informational messages:
212
+
213
+ ```bash
214
+ KGM_LOG_LEVEL=INFO kgm validate my-manifest.ttl
215
+ ```
216
+
217
+ > [!TIP]
218
+ > See the [Case Study: Sync](#case-study-sync) below for a description of the different ways to sync
219
+
220
+ ## Testing
221
+
222
+ Run `uv run pytest`, or Poetry etc. equivalents, to execute pytest. You must have Docker Desktop running to allow all
223
+ loader tests to be executed as some use temporary test containers.
224
+
225
+ ## Extending
226
+
227
+ Many functions have been placed into `kgm/utils.py` and hopefully extensions can be made to individual
228
+ functions there.
229
+
230
+ For example, to extend the criteria `kgm` uses to judge the newness of a local v. a remote artefacts for the
231
+ `sync` function, see the [`compare_version_indicators()`](kgm/utils.py#L397)
232
+
233
+ ## License
234
+
235
+ This code is available for reuse according to the [BSD 3-Clause License](https://opensource.org/license/bsd-3-clause).
236
+
237
+ &copy; 2024-2025 KurrawongAI
238
+
239
+ ## Contact
240
+
241
+ For all matters, please contact:
242
+
243
+ **KurrawongAI**
244
+ <info@kurrawong.ai>
245
+ <https://kurrawong.ai>
246
+
247
+ ## Case Studies
248
+
249
+ ### Case Study: Establish
250
+
251
+ The Indigenous Studies Unit Catalogue is a new catalogue of resources - books, articles, boxes of archived documents -
252
+ produced by
253
+ the [Indigenous Studies Unit](https://mspgh.unimelb.edu.au/centres-institutes/onemda/research-group/indigenous-studies-unit)
254
+ at the [University of Melbourne](https://www.unimelb.edu.au).
255
+
256
+ The catalogue is available online via an instance of the [Prez](https://prez.dev) system at <https://data.idnau.org/pid/isu-catalogue>
257
+ and the content is managed in the GitHub repository <https://github.com/idn-au/isu-catalogue>.
258
+
259
+ The catalogue container object is constructed as a `schema:DataCatalog` (and also a `dcat:Catalog`, for compatibility
260
+ with legacy systems) containing multiple `schema:CreativeWork` instances with subtyping to indicate 'book', 'artwork'
261
+ etc.
262
+
263
+ The source of the catalogue metadata is the static RDF file `_background/catalogue-metadata.ttl` that was made by hand.
264
+
265
+ The source of the resources' information is the CSV file `_background/datasets.csv` which was created by hand during a
266
+ visit to the Indigenous Studies Unit. This CSV information was converted to RDF files in `resources/` using the custom
267
+ script `_background/resources_make.py`.
268
+
269
+ After creation of the catalogue container object's metadata and the primary resource information, KGM was used
270
+ to improve the presentation of the data in Prez in the following ways:
271
+
272
+ 1. A manifest files was created
273
+ * based on the example in this repository in `tests/demo-vocabs/manifest.ttl`
274
+ * the example was copy 'n pasted with only minor changes, see `manifest.ttl` in the ISU catalogue repo
275
+ * the initial manifest file was validated with kgm/validator: `kgm validate isu-catalogue/manifest.ttl`
276
+ 2. A labels file was automatically generated using kgm/labeller
277
+ * using the [KurrawongAI Semantic Background](https://github.com/Kurrawong/semantic-background) as a source of
278
+ labels
279
+ * using the command `kgm label rdf isu-catalogue/manifest.ttl http://demo.dev.kurrawong.ai/sparql > labels.ttl`
280
+ * the file, `labels.ttl` was stored in the ISU Catalogue repo `_background/` folder and indicated in the manifest
281
+ file with the role of _Incomplete Catalogue And Resource Labels_ as it doesn't provide all missing labels
282
+ * note that this storage could have been done automatically using the `kgm label manifest` command
283
+ 3. IRIs still missing labels were determined
284
+ * using kgm/labeller again with the command `kgm label iris isu-catalogue/manifest.ttl > iris.txt`, all IRIs
285
+ still missing labels were listed
286
+ 4. Labels for remaining IRIs were manually created
287
+ * there were only 7 important IRIs (as opposed to system objects that don't need labels) that still needed labels.
288
+ These where manually created in the file `_background/labels-manual.ttl`
289
+ * the manual labels file was added to the catalogue's manifest, also with a role of _Incomplete Catalogue And
290
+ Resource Labels_
291
+ 5. A final missing labels test was performed
292
+ * running `kgm label iris isu-catalogue/manifest.ttl > iris.txt` again indicated no important IRIs were still missing
293
+ labels
294
+ 6. The catalogue was enhanced
295
+ * `kgm document catalogue isu-catalogue/manifest.ttl` was run to add all the resources of the catalogue to the
296
+ `catalogue.ttl` file
297
+ 7. The manifest was documented
298
+ * using kgm/documentor, a Markdown table of the manifest's content was created using the command
299
+ `kgm document table isu-catalogue/manifest.ttl`
300
+ * the output of this command - a Markdown table - is visible in the ISU Catalogue repo's README file.
301
+ 8. The catalogue was prepared for upload
302
+ * `kgm load file isu-catalogue/manifest.ttl isu-catalogue.trig` was run
303
+ * it produced a single _trig_ file `isu-catalogue.trig` containing RDF graphs which was one-time uploaded to the
304
+ database delivering the catalogue
305
+ 9. The catalogue and repo were synchronised
306
+ * `kgm sync` was then used repeatedly to synchronise updates to the files in version control with the RDF BY read by Prez
307
+
308
+ ### Case Study: Sync
309
+
310
+ If I have a manifest locally, I can load it into a remote SPARQL Endpoint like this:
311
+
312
+ ```bash
313
+ kgm load sparql {PATH-TO-MANIFEST} {SPARQL-ENDPOINT}
314
+ ```
315
+
316
+ Going forward, I don't have to blow away all the content in the SPARQL Endpoint and reload everything whenever I have
317
+ content changes, instead I can use the `sync` command.
318
+
319
+ `sync` compares "version indicators" per artefact, determines which is more recent and then reports on whether the local
320
+ artefact should be uploaded, teh remote one downloaded or whether there are new artefacts present locally or remotely.
321
+
322
+ The `tests/test_sync/` directory in this repository contains a _local_ and a _remote_ manifest and content. Following
323
+ the logic in the testing function `tests/test_sync/test_sync.py::test_sync`, if the _remote_ manifest is loaded, as per
324
+ `kgm load sparql tests/test_sync/remote/manifest.ttl {SPARQL-ENDPOINT}` and then `sync` is run like this:
325
+
326
+ ```bash
327
+ kgm sync tests/test_sync/local/manifest.ttl {SPARQL-ENDPOINT}
328
+ ```
329
+
330
+ You will see a report like this:
331
+
332
+ ```
333
+ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
334
+ ┃ artefact ┃ Main Entity ┃ Direction ┃
335
+ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━┩
336
+ │ /../../../artefact4.ttl │ http://example.com/dataset/4 │ upload │
337
+ │ /../../../artefact5.ttl │ http://example.com/dataset/5 │ add-remotely │
338
+ │ /../../../artefact6.ttl │ http://example.com/dataset/6 │ download │
339
+ │ /../../../artefact7.ttl │ http://example.com/dataset/7 │ upload │
340
+ │ /../../../artefact9.ttl │ http://example.com/dataset/9 │ same │
341
+ │ /../../../artefacts/artefact1.ttl │ http://example.com/dataset/1 │ same │
342
+ │ /../../../artefacts/artefact2.ttl │ http://example.com/dataset/2 │ upload │
343
+ │ /../../../artefacts/artefact3.ttl │ http://example.com/dataset/3 │ upload │
344
+ │ /../../../catalogue.ttl │ https://example.com/sync-test │ same │
345
+ │ http://example.com/dataset/8 │ http://example.com/dataset/8 │ add-locally │
346
+ └───────────────────────────────────┴───────────────────────────────┴──────────────┘
347
+ ```
348
+
349
+ This is telling you, per artefact, what `sync` will do.
350
+
351
+ * the local copy of `artefact4.ttl` is newer than the remote one, so it wants to "upload"
352
+ * the remote location is missing `artefact5.ttl`, so it wants to upload that too
353
+ * `artefact9` is the "same" - no action required
354
+ * `artefact6.ttl` is newer remotely, it should be downloaded
355
+
356
+ You can choose to have `sync` carry out all these actions or only some - default is all - by setting the `update_remote`
357
+ and so on input parameters. Setting all to `False` will cause `sync` to do nothing and report only what it _would_ do if
358
+ they were not set, e.g.:
359
+
360
+ ```bash
361
+ kgm sync tests/test_sync/local/manifest.ttl http://localhost:3030/test/ False False False False
362
+ ```
363
+
364
+ Other than doing all this "manually" - interactively, on the command line - I might want to use `sync` in Python
365
+ application code or cloud _infracode_ scriptin.
366
+
367
+ For use in Python applications, just import KGM - `uv add kgm` etc. - and use, as per the use of
368
+ `sync` in `tests/test_sync/test_sync.py::test_sync`.
369
+
370
+ For use in _infracode_, note that the `kgm sync` function can return the table above in JSON by setting the
371
+ `response format` input parameter, `-f`.
372
+
373
+ ## Manifest Data Model
374
+
375
+ ``` mermaid
376
+ graph LR
377
+ Manifest --1:1-N--> Resource;
378
+ Resource --1:1--> artifact;
379
+ Resource --1:1--> role;
380
+ Resource --1:0-1--> name;
381
+ Resource --1:0-1--> decription;
382
+ ```
383
+
384
+ The Manifest Model is simply a Manifest class, `prez:Manifest`, which MUST have 1 or more Resource Descriptors, `prof:ResourceDescriptor` indicated by the `prof:hasResource` predicate.
385
+
386
+ Each Resource Descriptor MUST have exactly one `prof:hasArtifact` predicate indicating an RDF literal resource (string) giving a file path or path pattern containing the resource information, relative to the manifest.
387
+
388
+ Each Resource Descriptor MUST also have exactly one `prof:hasRole` predicate indicating a Concept from the _Manifest Resource Roles Vocabulary_.
389
+
390
+ Each Resource Descriptor MAY have a `schema:name` and/r a `schema:description` predicate indicating literal resources naming and describing it.
391
+
392
+ ### Manifest Resource Roles Vocabulary
393
+
394
+ This roles vocabulary contains the allowed roles that a resource can play with respect to a Manifest.
395
+
396
+ The IRI of this vocabulary is:
397
+
398
+ * `https://prez.dev/ManifestResourceRoles`
399
+ * the vocab namespace is `https://prez.dev/ManifestResourceRoles/`
400
+ * recommended namespace prefix is `mrr`
401
+
402
+ Human-readable form:
403
+
404
+ | Concept IRI | Label | Definition | Parent |
405
+ |-------------------------------------------|-----------------------------------------|---------------------------------------------------------------------------------------------------------------------|--------------------------------|
406
+ | `mrr:ContainerData` | Container Data | Data for the container, usually a Catalogue, including the identity of it and each item fo content | - |
407
+ | `mrr:ContentData` | Content Data | Data for the content of the container | - |
408
+ | `mrr:ContainerAndContentModel` | Container & Content Model | The default model for the container and the content. Must be a set of SAHCL Shapes | - |
409
+ | `mrr:ContainerModel` | Container Model | The default model for the container. Must be a set of SAHCL Shapes | `mrr:containerAndContentModel` |
410
+ | `mrr:ContentModel` | Content Model | The default model for the content. Must be a set of SAHCL Shapes | `mrr:containerAndContentModel` |
411
+ | `mrr:CompleteContainerAndContentLabels` | Complete Content and Container Labels | All the labels - possibly indluding names, descriptions & seeAlso links - for the Container and Content objects | - |
412
+ | `mrr:IncompleteContainerAndContentLabels` | Incomplete Content and Container Labels | Some of the labels - possibly indluding names, descriptions & seeAlso links - for the Container and Content objects | - |
413
+
414
+ * <https://github.com/Kurrawong/kgm/blob/main/kgm/mrr.ttl>
415
+
416
+ ### Validation
417
+
418
+ #### SHACL Validation
419
+
420
+ This [SHACL](https://www.w3.org/TR/shacl/) validator Shapes Graph file can be used by SHACL validation software such as
421
+ [pySHACL](https://pypi.org/project/pyshacl/), to test the validity of a Manifest's RDF file with respect to this model:
422
+
423
+ * <https://github.com/Kurrawong/kgm/blob/main/kgm/validator.ttl>
424
+
425
+ This Shapes Graph is also loaded in to KurrawongAI's Semantic Background and is available via their validator tool
426
+ online and can be selected there for use via the "Use Validators" button:
427
+
428
+ * <https://tools.kurrawong.ai/validate>
429
+
430
+ #### KGM validation
431
+
432
+ Validation beyond just SHACL is needed for an effective manifest as the `manifest.ttl` file necessarily indicates
433
+ other resources that must be present and correct for the whole manifest to work. To validate all aspects of a manifest,
434
+ use the in-build KGM command: `kgm validate {PATH-TO-MANIFEST-FILE}`.
435
+
436
+ This function also validates the contents linked to in the manifest as per their [Conformance Claims](#conformance-claims).
437
+
438
+ This KGM validation is automatically performed before other KGM commands like `sync`.
439
+
440
+ #### Conformance Claims
441
+
442
+ A claim that some data conforms to a standard or a profile. In KGM, this is about indicating that a Resource
443
+ is expected to conform to a standard.
444
+
445
+ In the [Geoscience Australia Vocabs' manifest](https://github.com/GeoscienceAustralia/ga-vocabs/blob/master/manifest.ttl),
446
+ there is a conformance claim for the vocabs to the [VocPub Profile's Validator](https://linked.data.gov.au/def/vocpub/validator)
447
+ which looks like this:
448
+
449
+ ```turtle
450
+ #...
451
+ PREFIX dcterms: <http://purl.org/dc/terms/>
452
+ PREFIX mrr: <https://prez.dev/ManifestResourceRoles/>
453
+ PREFIX prof: <http://www.w3.org/ns/dx/prof/>
454
+
455
+ [
456
+ prof:hasArtifact "vocabularies/*.ttl" ;
457
+ prof:hasRole mrr:ResourceData ;
458
+ dcterms:conformsTo <https://linked.data.gov.au/def/vocpub/validator> ;
459
+ ] .
460
+ #...
461
+ ```
462
+
463
+ `kgm validate` will acquire validators indicated in conformance claims, either from KurrawongAI's Semantic Background, or
464
+ from a locally-supplied SHACL validator Shapes Graph, and will validate all resources within that manifest resource with
465
+ it. In the GA Vocabs above, all vocabulary files in the path `"vocabularies/*.ttl"` will be validated with VocPub.
466
+
467
+ ### Semantic Background
468
+
469
+ [KurrawongAI](https://kurrawong.ai) makes available about 100 well-known ontologies, 50 or so Shapes GRaph validators
470
+ and many vocabularies within its _Semantic Background_, an online reference dataset of RDF content that KGM can
471
+ access. this allows KGM to acquire many labels for RDF elements within a manifest's resources and to validate resource
472
+ without the user needing to supply anything.
473
+
474
+ You can see exactly what's in the Semantic Background, which is set up using KGM manifests, here:
475
+
476
+ * <https://github.com/Kurrawong/semantic-background>
477
+
478
+ ## Release Procedure
479
+
480
+ * format code: `task format`
481
+ * pass tests: `task test`
482
+ * update version in pyproject.toml
483
+ * commit all updates: `git commit -a "..."`
484
+ * make GitHub release
485
+ * this will trigger pypi.yml workflow to publish to PyPI
486
+ * update version in pyproject.toml to next release alpha and push