Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
8d866e8
fix(github-templates): clean-up duplicated frontmatter
Silvanoc Oct 2, 2026
3496e7c
Merge branch 'main' into clean-up-issue-templates
matentzn Oct 7, 2026
6f37745
Merge pull request #4053 from linkml/clean-up-issue-templates
matentzn Oct 7, 2026
b2ebb17
feat(generator): shared config-file overlay for all generators (part …
noelmcloughlin Oct 7, 2026
79ad3ac
Keep class_uri alongside its skos:exactMatch
amc-corey-cox Oct 8, 2026
01ea592
Fix gen-jsonld with a relative schema path
amc-corey-cox Oct 8, 2026
dc38dec
Keep identifier keys out of --use-curies
amc-corey-cox Oct 8, 2026
68e7e3d
fix(javagen): report a missing --template-file as a usage error (#4076)
noelmcloughlin Oct 8, 2026
008c12d
feat(rdf): add opt-in diff-stable blank-node labels
jdsika Sep 8, 2026
4a9a7b2
fix(rdf): bump diffable-rdf to 0.3.0 and stop diff_stable silently no…
jdsika Sep 11, 2026
9b32570
build(deps): require diffable-rdf 0.4.0
jdsika Sep 11, 2026
e99dec2
test(rdf): mark diff-stable tests for diffable-rdf canary CI
jdsika Sep 14, 2026
3aaae35
Make diff-stable serialization optional and address review feedback
jdsika Sep 16, 2026
0800a00
test(rdf): trim the diff-stable tests and reuse the existing fixture
jdsika Oct 2, 2026
35f1df8
docs(owl): document deterministic serialization and --diff-stable
jdsika Sep 11, 2026
2cdaff1
test(rdf): record the canonicalizer gaps against the extracted library
jdsika Sep 11, 2026
c6ab471
refactor(rdf): delegate canonicalization to the diffable-rdf library
jdsika Sep 11, 2026
8ebd4dc
feat(gen-shacl): translate presence-implies-value rules to SHACL-SPARQL
rmessaou Sep 11, 2026
f1c04d0
feat(gen-shacl): add a compositional fallback for rule-to-SPARQL conv…
rmessaou Oct 6, 2026
9918427
docs(shacl): document rule-to-SHACL-SPARQL constraint generation
jdsika Sep 11, 2026
ee6954a
test(gen-shacl): cover nested range_expression postconditions
jdsika Oct 7, 2026
edc7c1a
fix(shaclgen): emit sh:pattern for pattern constraints inside any_of
jdsika May 7, 2026
5eb4ac8
feat(generators): translate class-level boolean expressions alike to …
jdsika Sep 24, 2026
55124e1
feat(jsonschemagen): emit propertyNames from inlined-dict key slot co…
jdsika Oct 2, 2026
bd28265
feat(generators): add --normalize-prefixes flag for well-known prefix…
jdsika Oct 2, 2026
e47c173
feat(gen-owl): honor instantiates on emitted schema resources
jdsika Oct 2, 2026
2796123
feat(rdf): honor declared annotation ranges in OWL and SHACL
jdsika Oct 2, 2026
4190754
fix(rdf): preserve string-derived anyURI literals across generators
jdsika Oct 2, 2026
d698ad8
fix(generators): enforce range_expression on each value alike in SHAC…
jdsika Oct 5, 2026
479ad10
feat(generators): enforce has_member alike in SHACL and JSON Schema
jdsika Oct 7, 2026
e0085cc
docs(rdf): model DCMI agent annotations with declared ranges
jdsika Oct 5, 2026
d75f782
fix(integration): reconcile generator features and verify their inter…
jdsika Oct 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,6 @@ about: Create a report to help us improve
title: ''
labels: bug
assignees: ''

---

---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''

---

**Describe the bug**
Expand Down
10 changes: 0 additions & 10 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,6 @@ about: Suggest an idea for this project
title: ''
labels: feature
assignees: ''

---

---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: feature
assignees: ''

---

**What is your feature request?**
Expand Down
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ All commands use `uv run` prefix (e.g., `uv run pytest`).
* Do not "fix" issues by changing or weakening test conditions. Try harder, or ask questions if a test fails.
* Avoid try/except blocks, these can mask bugs
* Failing fast is a good principle
* Optional dependencies are the documented exception to the two rules above. Guard the import, not the spec: `try: import x` / `except ImportError as exc: raise ImportError("x is required. Install with: pip install 'linkml[extra]'") from exc` - see `generators/bigquerygen.py`. `importlib.util.find_spec` raises under the test fixture below, which hides your message.
* Testing that an optional dependency is absent is not a mock test: use the `mock_missing_import` fixture in `tests/conftest.py`. Do not build isolated environments in CI for this.
* Follow the DRY principle
* Avoid repeating chunks of code, but also avoid premature over-abstraction
* Declarative principles are favored
Expand Down
9 changes: 5 additions & 4 deletions docs/generators/java.rst
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,11 @@ since that file is structured to configure every generator at once:
java:
package: org.example.model

``gen-java`` only ever reads ``generator_args.java.package`` out of this file --
every other key (``directory``, ``excludes``, other generators' ``generator_args``
entries, etc.) is ignored, so a full multi-generator project ``config.yaml`` can be
passed as-is without modification.
``gen-java`` reads only the ``generator_args.java`` section of this file (``directory``,
``excludes``, other generators' ``generator_args`` entries, etc. are ignored), so a full
multi-generator project ``config.yaml`` can be passed as-is. Any ``gen-java`` option can
be set there, keyed by its name with dashes as underscores; command-line options take
precedence, and a key that is not an option is reported as a warning and ignored.

An explicit ``--package`` command-line option always overrides a value set via
``--config-file``.
Expand Down
79 changes: 79 additions & 0 deletions docs/generators/json-schema.rst
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,19 @@ LinkML supports analogous elements:

Use of these elements will be translated into the appropriate JSON-Schema construct.

At the class level, a class carries the expressions of its ancestors and mixins.
A slot condition is unknown for an absent slot unless it decides whether the slot
may be absent, and an instance is invalid only when an expression is definitely
false, as described under "Class-level expressions and absent slots" in
:doc:`Advanced features </schemas/advanced>`.
A slot's `range_expression <https://w3id.org/linkml/range_expression>`_
constrains each of its values in the same way, with its conditions on the slots
of the value.
A multivalued slot's `has_member <https://w3id.org/linkml/has_member>`_ becomes
``contains``, and the slot is required, because a slot without a value has no
member.
The SHACL generator reads them the same way.

Inlining
^^^^^^^^

Expand Down Expand Up @@ -378,6 +391,72 @@ will generate:
LinkML also supports `Structured patterns <https://w3id.org/linkml/structured_pattern>`_, these are
compiled down to patterns during JSON Schema generation.

Dictionary key constraints (propertyNames)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

A multivalued, inlined slot whose range class has an identifier slot is
compiled to a JSON object keyed by that identifier (see *Inlining* above).
When the identifier slot carries string-applicable constraints, they are
emitted as a `propertyNames <https://json-schema.org/understanding-json-schema/reference/object.html#property-names>`_
schema on the container object, so the *keys* of the dictionary are validated,
not just the values:

.. code-block:: yaml

slots:
tags:
range: Tag
multivalued: true
inlined: true
uid:
identifier: true
pattern: "^(0|[1-9][0-9]*)$"

generates on the container:

.. code-block:: json

"tags": {
"additionalProperties": {"$ref": "#/$defs/Tag"},
"propertyNames": {"pattern": "^(0|[1-9][0-9]*)$"},
"type": "object"
}

The constraints carried over from the key slot are the ones applicable to JSON
Schema strings, because object keys are always strings (`JSON Schema Core
2019-09, §9.3.2.5 <https://json-schema.org/draft/2019-09/json-schema-core.html#rfc.section.9.3.2.5>`_):

* ``pattern`` -- whether written directly on the slot, resolved from a
``structured_pattern``, or inherited from the slot's ``range`` type (for
example an identifier with ``range: ncname``, or a user-defined type that
declares a ``pattern``);
* ``equals_string_in``, emitted as ``enum``;
* a string ``equals_string``, emitted as ``const``.

The emitted key pattern is always the same one that applies to the identifier
*inside* the value object, so a key and a redundantly repeated in-object
identifier are now validated identically.

Numeric constraints -- ``minimum_value``/``maximum_value``, and the numeric
``const`` produced by ``equals_number`` -- are deliberately **not** carried
over: they cannot be satisfied by a string key, and a numeric ``const`` would
reject every key. The ``allOf`` produced by a ``range_expression``, and the
permissible values of an ``enum``-ranged identifier, are likewise out of scope.

``propertyNames`` composes conjunctively with ``additionalProperties``, so keys
and values are constrained independently. It is emitted only when the key slot
actually carries one of the constraints listed above; an unconstrained key slot
produces exactly the same output as before.

.. note::

Because type-level patterns are included, an identifier slot whose range is
``ncname`` (or another pattern-bearing type) gains a ``propertyNames``
entry even if the slot itself declares no constraint. The generated schema
becomes stricter, but only in ways the model already required: data whose
keys satisfy the declared identifier type is unaffected.


Rules
^^^^^

Expand Down
39 changes: 39 additions & 0 deletions docs/generators/jsonld-context.rst
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,45 @@ to gen-prefix-map:

gen-prefix-map --flatprefixes personinfo.yaml > personinfo.prefixmap.json

URIs as IRIs or as literals
---------------------------

By default a ``uri`` or ``uriorcurie`` slot is coerced to ``xsd:anyURI``, a typed
literal. ``--xsd-anyuri-as-iri`` coerces it to ``@id`` instead, so the value becomes an
IRI node, matching the ``sh:nodeKind sh:IRI`` the SHACL generator emits. The OWL
generator accepts the same flag.

The flag applies to ``uri``, ``uriorcurie`` and their derived types when the
effective datatype remains ``xsd:anyURI``. Datatype IRIs are expanded before
comparison, so full IRIs and alternative prefixes behave identically. A type
derived from ``string`` that declares ``uri: xsd:anyURI`` stays a typed literal with or
without it. Use one for a URI reference that is data rather than a link, such as a file
path that may be relative: as ``@id`` it would be resolved against the document base.

.. code-block:: yaml

types:
FilePath:
typeof: string
uri: xsd:anyURI # always "@type": "xsd:anyURI", sh:datatype xsd:anyURI
slots:
homepage:
range: uri # "@id" with --xsd-anyuri-as-iri
file_path:
range: FilePath

The RDF dumper, SHACL and ShEx generators distinguish the same URI family from
literal-valued types. An explicit datatype override such as ``uri: xsd:string``
remains literal-valued, including when the type inherits from ``uri``.

`XSD anyURI <https://www.w3.org/TR/xmlschema11-2/#anyURI>`__ admits relative URI
references as literal values. This differs from an RDF IRI node: `JSON-LD type
coercion <https://www.w3.org/TR/json-ld11/#type-coercion>`__ with ``@id`` interprets
strings as identifiers and resolves relative references against the base IRI.
The existing option selects the JSON-LD/OWL representation of LinkML's URI
family; it is not needed to preserve a deliberately literal-valued type. No
additional option is introduced.


Docs
----
Expand Down
Loading
Loading