Gen3SchemaDev 2.5.0__tar.gz → 2.6.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 (23) hide show
  1. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/PKG-INFO +3 -1
  2. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/README.md +2 -0
  3. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/pyproject.toml +1 -1
  4. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/cli.py +38 -1
  5. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/refs.py +58 -0
  6. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/LICENSE +0 -0
  7. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/__init__.py +0 -0
  8. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/converter.py +0 -0
  9. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/ddvis.py +0 -0
  10. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/schema/__init__.py +0 -0
  11. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/schema/gen3_template.py +0 -0
  12. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/schema/input_schema.py +0 -0
  13. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/schema/schema_templates/_definitions.yaml +0 -0
  14. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/schema/schema_templates/_settings.yaml +0 -0
  15. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/schema/schema_templates/_terms.yaml +0 -0
  16. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/schema/schema_templates/core_metadata_collection.yaml +0 -0
  17. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/schema/schema_templates/gen3_metaschema.yml +0 -0
  18. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/schema/schema_templates/program.yaml +0 -0
  19. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/schema/schema_templates/project.yaml +0 -0
  20. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/utils.py +0 -0
  21. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/validators/input_validator.py +0 -0
  22. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/validators/metaschema_validator.py +0 -0
  23. {gen3schemadev-2.5.0 → gen3schemadev-2.6.0}/src/gen3schemadev/validators/rule_validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: Gen3SchemaDev
3
- Version: 2.5.0
3
+ Version: 2.6.0
4
4
  Summary: Tool for data modelling in Gen3
5
5
  License: Apache 2.0
6
6
  License-File: LICENSE
@@ -46,6 +46,8 @@ gen3schemadev fix-refs -y path/to/dictionary # rewrite in place
46
46
 
47
47
  The command is idempotent and never touches bare refs, refs already inside `allOf`/`anyOf`/`oneOf`, the `properties: {$ref: ...}` merge construct, or `_definitions.yaml`/`_terms.yaml`/`_settings.yaml`.
48
48
 
49
+ Both `fix-refs` and `validate` also warn about `description: null` placeholders anywhere in the dictionary (commonly in `_definitions.yaml`): the Gen3 metaschema requires descriptions to be strings, and such placeholders fail metaschema validation once exposed through bare or `allOf`-wrapped refs. Remove the null keys to resolve the warning.
50
+
49
51
 
50
52
  ## Deep dive into Gen3 Data Modelling
51
53
  *Special Thanks to Marion Shadbolt for providing the [source material](https://github.com/AustralianBioCommons/umccr-dictionary/tree/main/docs/schemas)*
@@ -23,6 +23,8 @@ gen3schemadev fix-refs -y path/to/dictionary # rewrite in place
23
23
 
24
24
  The command is idempotent and never touches bare refs, refs already inside `allOf`/`anyOf`/`oneOf`, the `properties: {$ref: ...}` merge construct, or `_definitions.yaml`/`_terms.yaml`/`_settings.yaml`.
25
25
 
26
+ Both `fix-refs` and `validate` also warn about `description: null` placeholders anywhere in the dictionary (commonly in `_definitions.yaml`): the Gen3 metaschema requires descriptions to be strings, and such placeholders fail metaschema validation once exposed through bare or `allOf`-wrapped refs. Remove the null keys to resolve the warning.
27
+
26
28
 
27
29
  ## Deep dive into Gen3 Data Modelling
28
30
  *Special Thanks to Marion Shadbolt for providing the [source material](https://github.com/AustralianBioCommons/umccr-dictionary/tree/main/docs/schemas)*
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "Gen3SchemaDev"
3
- version = "2.5.0"
3
+ version = "2.6.0"
4
4
  description = "Tool for data modelling in Gen3"
5
5
  authors = [
6
6
  {name = "JoshuaHarris391",email = "harjo391@gmail.com"}
@@ -20,7 +20,31 @@ from gen3schemadev.validators.metaschema_validator import validate_schema_with_m
20
20
  from importlib.metadata import version
21
21
  from gen3schemadev.ddvis import visualise_with_docker
22
22
  from gen3schemadev.validators.rule_validator import RuleValidator
23
- from gen3schemadev.refs import WRAPPED, SKIP_REASONS, fix_yaml_dir
23
+ from gen3schemadev.refs import (
24
+ WRAPPED,
25
+ SKIP_REASONS,
26
+ fix_yaml_dir,
27
+ find_null_descriptions,
28
+ scan_dir_null_descriptions,
29
+ )
30
+
31
+
32
+ def print_null_description_warning(hits):
33
+ """
34
+ Print a warning block listing every null-valued 'description' key found
35
+ in the dictionary ("file: dotted.path" strings). No-op when hits is empty.
36
+ """
37
+ if not hits:
38
+ return
39
+ print(
40
+ "\nWARNING: found 'description: null' placeholders. The Gen3 metaschema "
41
+ "requires 'description' to be a string, and null placeholders in shared "
42
+ "definitions fail metaschema validation once exposed through bare or "
43
+ "allOf-wrapped $refs. Remove the null 'description' keys (removing adds "
44
+ "no shared description, so nothing leaks onto referencing properties):"
45
+ )
46
+ for hit in hits:
47
+ print(f" - {hit}")
24
48
 
25
49
 
26
50
  def main():
@@ -242,6 +266,15 @@ def main():
242
266
  elif args.yamls:
243
267
  schema_dict = bundle_yamls(args.yamls)
244
268
 
269
+ # Pre-resolution diagnostic: report every null 'description' up front,
270
+ # because the metaschema stage fails on the first resolved node schema,
271
+ # far away from the definition that carries the null.
272
+ null_hits = []
273
+ for schema_name, schema in schema_dict.items():
274
+ for hit in find_null_descriptions(schema):
275
+ null_hits.append(f"{schema_name}: {hit}")
276
+ print_null_description_warning(null_hits)
277
+
245
278
  for schema_name, schema in schema_dict.items():
246
279
 
247
280
  if '.' in schema_name:
@@ -364,5 +397,9 @@ def main():
364
397
  print(f"\nSummary: {total_wrapped} properties {verb} in {files_changed} files; "
365
398
  f"{files_unchanged} files unchanged.")
366
399
 
400
+ # Wrapping is what exposes null 'description' placeholders in shared
401
+ # definitions to metaschema validation, so surface them here too.
402
+ print_null_description_warning(scan_dir_null_descriptions(args.yamldir))
403
+
367
404
  if __name__ == "__main__":
368
405
  main()
@@ -141,6 +141,64 @@ def fix_schema(schema: dict) -> "tuple":
141
141
  return new_schema, changes
142
142
 
143
143
 
144
+ def find_null_descriptions(node, path: str = "") -> list:
145
+ """
146
+ Recursively find every ``description`` key whose value is null.
147
+
148
+ The Gen3 metaschema requires ``description`` to be a string, so a
149
+ ``description: null`` placeholder (common in generated shared
150
+ definitions) is invalid. With a direct ``$ref`` the resolver happens to
151
+ mask it — the referencing property's own description merges over the
152
+ definition's null — but a bare or allOf-wrapped ref exposes the null in
153
+ the resolved node schema, where metaschema validation fails far away
154
+ from the definition that caused it.
155
+
156
+ Returns a list of dotted paths to each offender, with list items shown
157
+ as ``[i]`` (e.g. ``"enum_yes_no.description"``,
158
+ ``"properties.status.anyOf[0].description"``). Non-dict/list input
159
+ yields an empty list.
160
+ """
161
+ hits = []
162
+ if isinstance(node, dict):
163
+ for key, value in node.items():
164
+ key_path = f"{path}.{key}" if path else str(key)
165
+ if key == "description" and value is None:
166
+ hits.append(key_path)
167
+ else:
168
+ hits.extend(find_null_descriptions(value, key_path))
169
+ elif isinstance(node, list):
170
+ for i, item in enumerate(node):
171
+ hits.extend(find_null_descriptions(item, f"{path}[{i}]"))
172
+ return hits
173
+
174
+
175
+ def scan_dir_null_descriptions(yaml_dir: str) -> list:
176
+ """
177
+ Scan every YAML file under ``yaml_dir`` (recursively) for null-valued
178
+ ``description`` keys.
179
+
180
+ Unlike ``fix_yaml_dir``, underscore files (``_definitions.yaml``,
181
+ ``_terms.yaml``, ...) are INCLUDED — shared definitions are where the
182
+ null placeholders usually live, and where they do the most damage
183
+ because every referencing property inherits them on resolution.
184
+
185
+ Returns ``"relpath: dotted.path"`` strings, one per offender.
186
+ """
187
+ from gen3schemadev.utils import load_yaml
188
+
189
+ hits = []
190
+ for root, _dirs, files in os.walk(yaml_dir):
191
+ for fname in sorted(files):
192
+ if not (fnmatch.fnmatch(fname, "*.yaml") or fnmatch.fnmatch(fname, "*.yml")):
193
+ continue
194
+ path = os.path.join(root, fname)
195
+ rel_path = os.path.relpath(path, yaml_dir)
196
+ schema = load_yaml(path)
197
+ for hit in find_null_descriptions(schema):
198
+ hits.append(f"{rel_path}: {hit}")
199
+ return hits
200
+
201
+
144
202
  def fix_yaml_dir(yaml_dir: str, dry_run: bool = False) -> list:
145
203
  """
146
204
  Rewrite every YAML node schema under ``yaml_dir`` (recursively) so that
File without changes