rdf-construct 0.4.0__py3-none-any.whl → 0.4.2__py3-none-any.whl

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.
rdf_construct/__init__.py CHANGED
@@ -4,7 +4,7 @@ Named after the ROM construct from William Gibson's Neuromancer -
4
4
  preserved, structured knowledge that can be queried and transformed.
5
5
  """
6
6
 
7
- __version__ = "0.4.0"
7
+ __version__ = "0.4.2"
8
8
 
9
9
  from . import core, uml
10
10
  from .cli import cli
rdf_construct/cli.py CHANGED
@@ -33,7 +33,7 @@ from rdf_construct.lint import (
33
33
  LintConfig,
34
34
  load_lint_config,
35
35
  find_config_file,
36
- get_formatter,
36
+ get_formatter as get_lint_formatter,
37
37
  list_rules,
38
38
  get_all_rules,
39
39
  )
@@ -691,7 +691,7 @@ def lint(
691
691
 
692
692
  # Format and output results
693
693
  use_colour = not no_colour and output_format == "text"
694
- formatter = get_formatter(output_format, use_colour=use_colour)
694
+ formatter = get_lint_formatter(output_format, use_colour=use_colour)
695
695
 
696
696
  output = formatter.format_summary(summary)
697
697
  click.echo(output)
@@ -3,7 +3,7 @@
3
3
  from .ordering import sort_subjects, topo_sort_subset, sort_with_roots
4
4
  from .profile import OrderingConfig, OrderingProfile, load_yaml
5
5
  from .selector import select_subjects
6
- from .serialiser import serialise_turtle, build_section_graph
6
+ from .serialiser import collect_used_namespaces, serialise_turtle, build_section_graph
7
7
  from .utils import (
8
8
  expand_curie,
9
9
  extract_prefix_map,
@@ -23,6 +23,7 @@ __all__ = [
23
23
  # Selector
24
24
  "select_subjects",
25
25
  # Serialiser
26
+ "collect_used_namespaces",
26
27
  "serialise_turtle",
27
28
  "build_section_graph",
28
29
  # Utils
@@ -30,4 +31,4 @@ __all__ = [
30
31
  "extract_prefix_map",
31
32
  "qname_sort_key",
32
33
  "rebind_prefixes",
33
- ]
34
+ ]
@@ -26,6 +26,54 @@ except ImportError:
26
26
  )
27
27
 
28
28
 
29
+ def collect_used_namespaces(
30
+ graph: Graph,
31
+ namespace_source: Graph | None = None,
32
+ ) -> set[str]:
33
+ """Collect namespace URIs that are actually used in the graph's triples.
34
+
35
+ Scans all subjects, predicates, and objects (including Literal datatype
36
+ URIs) to find which registered namespace URIs are referenced. Uses
37
+ longest-match-first ordering to correctly handle overlapping namespaces
38
+ (e.g. ``dc:`` vs ``dcterms:``).
39
+
40
+ Args:
41
+ graph: RDF graph whose triples to scan.
42
+ namespace_source: Optional graph whose namespace registry to match
43
+ against. Defaults to *graph* itself. Use this when the graph
44
+ being scanned has a stripped namespace manager (e.g. built
45
+ with ``bind_namespaces="none"``).
46
+
47
+ Returns:
48
+ Set of namespace URI strings that appear in the graph's triples.
49
+ """
50
+ ns_graph = namespace_source if namespace_source is not None else graph
51
+
52
+ used_ns: set[str] = set()
53
+ # Sort namespaces longest-first so we match the most specific prefix
54
+ ns_uris = sorted(
55
+ [str(uri) for _, uri in ns_graph.namespace_manager.namespaces()],
56
+ key=len,
57
+ reverse=True,
58
+ )
59
+
60
+ def _match_uri(uri_str: str) -> None:
61
+ """Add the best-matching namespace for *uri_str* to used_ns."""
62
+ for ns_uri in ns_uris:
63
+ if uri_str.startswith(ns_uri):
64
+ used_ns.add(ns_uri)
65
+ return
66
+
67
+ for s, p, o in graph:
68
+ for term in (s, p, o):
69
+ if isinstance(term, URIRef):
70
+ _match_uri(str(term))
71
+ elif isinstance(term, Literal) and term.datatype is not None:
72
+ _match_uri(str(term.datatype))
73
+
74
+ return used_ns
75
+
76
+
29
77
  def format_term(graph: Graph, term, use_prefixes: bool = True) -> str:
30
78
  """Format an RDF term as a Turtle string.
31
79
 
@@ -79,8 +127,11 @@ def serialise_turtle(
79
127
  This custom serialiser respects the exact order of subjects provided,
80
128
  unlike rdflib's built-in serialisers which always sort alphabetically.
81
129
 
130
+ Only prefix declarations for namespaces actually used in the graph's
131
+ triples are emitted, filtering out rdflib's built-in defaults.
132
+
82
133
  Formatting features:
83
- - Prefixes sorted alphabetically at top
134
+ - Prefixes sorted alphabetically at top (used namespaces only)
84
135
  - Subjects in specified order
85
136
  - rdf:type predicate listed first for each subject
86
137
  - Predicates ordered according to predicate_order config (or alphabetically)
@@ -95,10 +146,11 @@ def serialise_turtle(
95
146
  """
96
147
  lines = []
97
148
 
98
- # Write prefixes
149
+ # Write prefixes — only those actually used in the graph
150
+ used_ns = collect_used_namespaces(graph)
99
151
  prefixes = sorted(graph.namespace_manager.namespaces(), key=lambda x: x[0])
100
152
  for prefix, namespace in prefixes:
101
- if prefix: # Skip the default namespace
153
+ if prefix and str(namespace) in used_ns:
102
154
  lines.append(f"PREFIX {prefix}: <{namespace}>")
103
155
  lines.append("") # Blank line after prefixes
104
156
 
@@ -208,8 +260,9 @@ def build_section_graph(base: Graph, subjects_ordered: list) -> Graph:
208
260
  """Build a new graph containing only the specified subjects and their triples.
209
261
 
210
262
  Creates a filtered view of the base graph that includes all triples
211
- where the subject is in the provided list. Preserves all namespace
212
- bindings from the base graph.
263
+ where the subject is in the provided list. Only namespace bindings
264
+ that are actually used by the included triples are carried over;
265
+ rdflib's built-in well-known namespace defaults are suppressed.
213
266
 
214
267
  Args:
215
268
  base: Source RDF graph to filter
@@ -218,15 +271,20 @@ def build_section_graph(base: Graph, subjects_ordered: list) -> Graph:
218
271
  Returns:
219
272
  New graph containing only triples for the specified subjects
220
273
  """
221
- sg = Graph()
222
-
223
- # Copy namespace bindings
224
- for pfx, uri in base.namespace_manager.namespaces():
225
- sg.namespace_manager.bind(pfx, uri, override=True, replace=True)
274
+ # Suppress rdflib's automatic well-known namespace bindings so the
275
+ # sub-graph starts with a clean namespace manager.
276
+ sg = Graph(bind_namespaces="none")
226
277
 
227
278
  # Copy triples for each subject
228
279
  for s in subjects_ordered:
229
280
  for p, o in base.predicate_objects(s):
230
281
  sg.add((s, p, o))
231
282
 
283
+ # Match sub-graph triples against the *base* graph's namespace registry
284
+ # (the sub-graph's own registry is intentionally empty at this point).
285
+ used_ns = collect_used_namespaces(sg, namespace_source=base)
286
+ for pfx, uri in base.namespace_manager.namespaces():
287
+ if str(uri) in used_ns:
288
+ sg.namespace_manager.bind(pfx, uri, override=True, replace=True)
289
+
232
290
  return sg
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rdf-construct
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: Semantic RDF manipulation toolkit - order, serialize, and diff RDF ontologies
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -425,7 +425,7 @@ properties:
425
425
 
426
426
  ## Project Status
427
427
 
428
- **Current**: v0.4.0 - Feature complete for core ontology workflows
428
+ **Current**: v0.4.1 - Feature complete for core ontology workflows
429
429
  **License**: MIT
430
430
 
431
431
  ### Implemented
@@ -512,7 +512,7 @@ MIT License - see [LICENSE](LICENSE) file for details.
512
512
 
513
513
  ---
514
514
 
515
- **Status**: v0.4.0
515
+ **Status**: v0.4.1
516
516
  **Python**: 3.10+ required
517
517
  **Maintainer**: See [CONTRIBUTING.md](CONTRIBUTING.md)
518
518
 
@@ -1,13 +1,13 @@
1
- rdf_construct/__init__.py,sha256=9M_dNYQYdJqwwXnwonajTNqDJrxQQWUNk5SVd4nlkGM,296
1
+ rdf_construct/__init__.py,sha256=FDsnLwjSAR3yMLtq_GWucI1zAnO9hU9Bj7syUeg038c,296
2
2
  rdf_construct/__main__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- rdf_construct/cli.py,sha256=Z3iMI_w8pLWAOAAwKk6IwAx-O2HuiHChUUjCPooVPeY,108330
4
- rdf_construct/core/__init__.py,sha256=YgxXUPGHgBqToc8u06qksfWh_vx25g2eCg8_X8vg5l4,781
3
+ rdf_construct/cli.py,sha256=gVkr_mx5eJ54mDIuIV6mgMjVN-k6TH-N8dYWwhIiPvU,108357
4
+ rdf_construct/core/__init__.py,sha256=qFf1u6WKHVaswipXkR9tXBGrCkNo06aGT-6c9mCOpvs,838
5
5
  rdf_construct/core/config.py,sha256=uOAvvZ7keI8o4o6r6ESzHC4AkKHN1Ja2FADiHZqZDaM,3523
6
6
  rdf_construct/core/ordering.py,sha256=fGw5aGIY8SpsGgbm1Z1YH5mzlDv7mU7b9Is07ekJxZg,7248
7
7
  rdf_construct/core/predicate_order.py,sha256=ITQYC_pWtH6d4JbvOwKjyU7xGL_bSDoHHLQOTac8kMc,6688
8
8
  rdf_construct/core/profile.py,sha256=CpA6fNMZKzDQgYa91KMylbfMv9RBiVo3AlUJ91_buzI,5475
9
9
  rdf_construct/core/selector.py,sha256=Ie_J3ZcAHYVxk7hP2YzbtJ0oE93CikWBd8cbWq8c9PE,2386
10
- rdf_construct/core/serialiser.py,sha256=Sba4Bn_8oUzRu6ntwapw215aSHC6B56Z8GSYU1Hsn04,7414
10
+ rdf_construct/core/serialiser.py,sha256=FRQFUx2roB5OdVm6gVyuEDdZJR773GdUKHubegk-p_I,9847
11
11
  rdf_construct/core/utils.py,sha256=dhu92LvvNJ21UI7FpdcjW1PaoHPo6UXcgnrofhkO_WE,2557
12
12
  rdf_construct/cq/__init__.py,sha256=PDFzRuBjlMKhyaimnOEHDpQ1Ok98xa4T6qtztju4Edw,1832
13
13
  rdf_construct/cq/expectations.py,sha256=IHQhKd8-eetyj-jvbGn502vFcL0qoUzX_4IT0GfBSGE,11850
@@ -117,8 +117,8 @@ rdf_construct/uml/odm_renderer.py,sha256=X4QqzWXJ-FX64ZIfu0Nx6gpHbEQsJOo2hq2fbY3
117
117
  rdf_construct/uml/renderer.py,sha256=Zj3udsghxXqJ5NPqvVSoIK177Vtzh-fFgsDzYxF5OoY,23755
118
118
  rdf_construct/uml/uml_layout.py,sha256=PBd_qOBJzDq2N8SCqDJqgAoFmYnzZC4jrLgCQ4biYBM,13217
119
119
  rdf_construct/uml/uml_style.py,sha256=ngVqmbS18Y4mAi9ggtL26IeVF5VbcOIOvalvI62jSO4,21876
120
- rdf_construct-0.4.0.dist-info/METADATA,sha256=PzNRNxOgohZAJS2Ow_PpIws154KJ_04f5qMRTgBGgKE,15741
121
- rdf_construct-0.4.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
122
- rdf_construct-0.4.0.dist-info/entry_points.txt,sha256=L4Mh7BDMt2BUHq_x9BwyPVZmZ-j_wifbD574Zm3qXZY,55
123
- rdf_construct-0.4.0.dist-info/licenses/LICENSE,sha256=Fh-f4K2IlA0QH5XThePUIoG6_J_UqDkQyihGfvHcvpk,1061
124
- rdf_construct-0.4.0.dist-info/RECORD,,
120
+ rdf_construct-0.4.2.dist-info/METADATA,sha256=difpznuOH0b0YNRP77a61esgIaD2_J4q4kW8eaosHbI,15739
121
+ rdf_construct-0.4.2.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
122
+ rdf_construct-0.4.2.dist-info/entry_points.txt,sha256=L4Mh7BDMt2BUHq_x9BwyPVZmZ-j_wifbD574Zm3qXZY,55
123
+ rdf_construct-0.4.2.dist-info/licenses/LICENSE,sha256=Fh-f4K2IlA0QH5XThePUIoG6_J_UqDkQyihGfvHcvpk,1061
124
+ rdf_construct-0.4.2.dist-info/RECORD,,