morphir-python 0.0.1__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.
Files changed (99) hide show
  1. morphir/__init__.py +14 -0
  2. morphir/ir/__init__.py +110 -0
  3. morphir/ir/access_controlled.py +15 -0
  4. morphir/ir/decorations.py +19 -0
  5. morphir/ir/diagnostics.py +105 -0
  6. morphir/ir/distribution.py +21 -0
  7. morphir/ir/document.py +37 -0
  8. morphir/ir/documented.py +11 -0
  9. morphir/ir/format_version.py +483 -0
  10. morphir/ir/fqname.py +9 -0
  11. morphir/ir/json.py +11 -0
  12. morphir/ir/literal.py +25 -0
  13. morphir/ir/meta.py +11 -0
  14. morphir/ir/migrate.py +1267 -0
  15. morphir/ir/module.py +17 -0
  16. morphir/ir/name.py +27 -0
  17. morphir/ir/package.py +15 -0
  18. morphir/ir/path.py +25 -0
  19. morphir/ir/qname.py +9 -0
  20. morphir/ir/ref.py +17 -0
  21. morphir/ir/type.py +37 -0
  22. morphir/ir/type_constraints.py +33 -0
  23. morphir/ir/type_def.py +19 -0
  24. morphir/ir/type_spec.py +25 -0
  25. morphir/ir/v3/__init__.py +64 -0
  26. morphir/ir/v3/_legacy_value.py +201 -0
  27. morphir/ir/v3/access_controlled.py +31 -0
  28. morphir/ir/v3/codec.py +1275 -0
  29. morphir/ir/v3/codec_v1.py +491 -0
  30. morphir/ir/v3/codec_v2.py +187 -0
  31. morphir/ir/v3/distribution.py +42 -0
  32. morphir/ir/v3/documented.py +13 -0
  33. morphir/ir/v3/fqname.py +30 -0
  34. morphir/ir/v3/literal.py +46 -0
  35. morphir/ir/v3/module.py +32 -0
  36. morphir/ir/v3/name.py +42 -0
  37. morphir/ir/v3/package.py +23 -0
  38. morphir/ir/v3/path.py +29 -0
  39. morphir/ir/v3/qname.py +16 -0
  40. morphir/ir/v3/type.py +126 -0
  41. morphir/ir/v3/value.py +235 -0
  42. morphir/ir/v4/__init__.py +160 -0
  43. morphir/ir/v4/access_controlled.py +17 -0
  44. morphir/ir/v4/annotation.py +75 -0
  45. morphir/ir/v4/codec.py +2161 -0
  46. morphir/ir/v4/decorations.py +88 -0
  47. morphir/ir/v4/distribution.py +56 -0
  48. morphir/ir/v4/document.py +69 -0
  49. morphir/ir/v4/documented.py +10 -0
  50. morphir/ir/v4/fqname.py +69 -0
  51. morphir/ir/v4/incompleteness.py +78 -0
  52. morphir/ir/v4/json.py +103 -0
  53. morphir/ir/v4/literal.py +51 -0
  54. morphir/ir/v4/meta.py +27 -0
  55. morphir/ir/v4/module.py +30 -0
  56. morphir/ir/v4/name.py +69 -0
  57. morphir/ir/v4/package.py +19 -0
  58. morphir/ir/v4/path.py +50 -0
  59. morphir/ir/v4/qname.py +34 -0
  60. morphir/ir/v4/ref.py +35 -0
  61. morphir/ir/v4/type.py +140 -0
  62. morphir/ir/v4/type_constraints.py +91 -0
  63. morphir/ir/v4/type_def.py +38 -0
  64. morphir/ir/v4/type_spec.py +64 -0
  65. morphir/ir/v4/value.py +480 -0
  66. morphir/ir/value.py +81 -0
  67. morphir/py.typed +0 -0
  68. morphir/sdk/__init__.py +110 -0
  69. morphir/sdk/_compare.py +187 -0
  70. morphir/sdk/aggregate.py +421 -0
  71. morphir/sdk/basics.py +504 -0
  72. morphir/sdk/char.py +110 -0
  73. morphir/sdk/decimal.py +311 -0
  74. morphir/sdk/dict.py +336 -0
  75. morphir/sdk/instant.py +118 -0
  76. morphir/sdk/int.py +86 -0
  77. morphir/sdk/key.py +522 -0
  78. morphir/sdk/list.py +356 -0
  79. morphir/sdk/local_date.py +436 -0
  80. morphir/sdk/local_time.py +267 -0
  81. morphir/sdk/maybe.py +135 -0
  82. morphir/sdk/number.py +237 -0
  83. morphir/sdk/regex.py +287 -0
  84. morphir/sdk/result.py +162 -0
  85. morphir/sdk/result_list.py +169 -0
  86. morphir/sdk/rule.py +103 -0
  87. morphir/sdk/set.py +214 -0
  88. morphir/sdk/stateful_app.py +49 -0
  89. morphir/sdk/string.py +427 -0
  90. morphir/sdk/tuple.py +43 -0
  91. morphir/sdk/uuid.py +209 -0
  92. morphir_python-0.0.1.dist-info/METADATA +269 -0
  93. morphir_python-0.0.1.dist-info/RECORD +99 -0
  94. morphir_python-0.0.1.dist-info/WHEEL +4 -0
  95. morphir_python-0.0.1.dist-info/entry_points.txt +2 -0
  96. morphir_python-0.0.1.dist-info/licenses/LICENSE +201 -0
  97. morphir_tools/__init__.py +13 -0
  98. morphir_tools/cli.py +223 -0
  99. morphir_tools/py.typed +0 -0
@@ -0,0 +1,483 @@
1
+ """Reading, checking, and writing the ``formatVersion`` member of Morphir IR JSON.
2
+
3
+ The reader is deliberately more permissive than its sources:
4
+
5
+ - morphir-elm decodes ``formatVersion`` with ``Decode.int``, so it rejects the
6
+ release string ``"3.0.0"``;
7
+ - the finos/morphir format-version contract accepts integer ``N`` and
8
+ ``"N.minor.patch"`` but rejects the bare string ``"N"``.
9
+
10
+ This reader accepts all three spellings (``3``, ``"3"``, ``"3.0.0"``) so migration
11
+ tooling can read files written by older and newer tools. Writers stay canonical:
12
+ integer ``N`` for ``N.0.0`` and the exact release string otherwise, so this package
13
+ never produces a file that either source would reject.
14
+
15
+ The support table is ``[3.0.0,3.2.0),[4.0.0,4.1.0)``, the finos reference table
16
+ (finos/morphir decision record 0018). IR 3.1.0 added the v3 ``Specs``
17
+ distribution; `V3_1` names that release. v4 support is draft.
18
+
19
+ Formats 1 and 2 are legacy: the finos release grammar starts at major 3, so they
20
+ are in no support table, and `read_format_version` refuses them with
21
+ ``unsupported_format_version_major``. `read_document_with_legacy` and
22
+ `read_legacy_document` recognize them, only as the integers morphir-elm wrote, for
23
+ the read-only decoders in `morphir.ir.v3.codec_v1` and `morphir.ir.v3.codec_v2`.
24
+ `write_format_version` never writes them.
25
+
26
+ Example:
27
+ >>> read_format_version(3)
28
+ FormatVersion(major=3, minor=0, patch=0)
29
+ >>> read_format_version("3.0.0") == read_format_version("3")
30
+ True
31
+ >>> write_format_version(FormatVersion(3, 0, 0))
32
+ 3
33
+ """
34
+
35
+ from __future__ import annotations
36
+
37
+ import json
38
+ import re
39
+ from dataclasses import dataclass
40
+ from enum import Enum
41
+
42
+ from . import diagnostics as d
43
+ from .diagnostics import DiagnosticError, fail
44
+
45
+ _U32_MAX = 4294967295
46
+ _COMPONENT = r"(0|[1-9][0-9]*)"
47
+ _RELEASE_RE = re.compile(rf"^{_COMPONENT}\.{_COMPONENT}\.{_COMPONENT}$")
48
+ _MAJOR_RE = re.compile(rf"^{_COMPONENT}$")
49
+ _CONSTRUCT = "formatVersion"
50
+
51
+
52
+ @dataclass(frozen=True, order=True)
53
+ class FormatVersion:
54
+ """An exact, normalized format release such as 3.0.0."""
55
+
56
+ major: int
57
+ minor: int
58
+ patch: int
59
+
60
+ def __str__(self) -> str:
61
+ return f"{self.major}.{self.minor}.{self.patch}"
62
+
63
+
64
+ @dataclass(frozen=True)
65
+ class Interval:
66
+ """A half-open release interval ``[lower, upper)``."""
67
+
68
+ lower: FormatVersion
69
+ upper: FormatVersion
70
+
71
+ def __contains__(self, version: object) -> bool:
72
+ return isinstance(version, FormatVersion) and (
73
+ self.lower <= version < self.upper
74
+ )
75
+
76
+ def __str__(self) -> str:
77
+ return f"[{self.lower},{self.upper})"
78
+
79
+
80
+ SupportTable = tuple[Interval, ...]
81
+
82
+ V3_INTERVAL = Interval(FormatVersion(3, 0, 0), FormatVersion(3, 2, 0))
83
+ V4_INTERVAL = Interval(FormatVersion(4, 0, 0), FormatVersion(4, 1, 0))
84
+ SUPPORT_TABLE: SupportTable = (V3_INTERVAL, V4_INTERVAL)
85
+ V3_TABLE: SupportTable = (V3_INTERVAL,)
86
+ V4_TABLE: SupportTable = (V4_INTERVAL,)
87
+
88
+ V3 = FormatVersion(3, 0, 0)
89
+ V3_1 = FormatVersion(3, 1, 0)
90
+ """The release that introduced the v3 ``Specs`` distribution."""
91
+ V4 = FormatVersion(4, 0, 0)
92
+
93
+
94
+ def table_to_string(table: SupportTable) -> str:
95
+ """Render a support table in canonical interval notation."""
96
+ return ",".join(str(interval) for interval in table)
97
+
98
+
99
+ def _component(text: str, value: object) -> int:
100
+ number = int(text)
101
+ if number > _U32_MAX:
102
+ raise fail(
103
+ d.FORMAT_VERSION_OUT_OF_RANGE,
104
+ _CONSTRUCT,
105
+ (_CONSTRUCT,),
106
+ f"formatVersion {value!r} has a component above {_U32_MAX}",
107
+ )
108
+ return number
109
+
110
+
111
+ def recognize_format_version(value: object) -> FormatVersion:
112
+ """Recognize and normalize a ``formatVersion`` value without a support check.
113
+
114
+ Historical integers 1 and 2 normalize to ``1.0.0`` and ``2.0.0`` so that the
115
+ support check can report them as unsupported majors.
116
+
117
+ Args:
118
+ value: The decoded JSON value of the ``formatVersion`` member.
119
+
120
+ Returns:
121
+ The normalized release.
122
+
123
+ Raises:
124
+ DiagnosticError: With ``invalid_format_version_type``,
125
+ ``invalid_format_version_syntax``, or ``format_version_out_of_range``.
126
+ """
127
+ loc: d.Location = (_CONSTRUCT,)
128
+ if isinstance(value, bool) or not isinstance(value, (int, str)):
129
+ raise fail(
130
+ d.INVALID_FORMAT_VERSION_TYPE,
131
+ _CONSTRUCT,
132
+ loc,
133
+ f"formatVersion must be an integer or a release string, "
134
+ f"not {type(value).__name__} {value!r}",
135
+ )
136
+ if isinstance(value, int):
137
+ if value < 0:
138
+ raise fail(
139
+ d.INVALID_FORMAT_VERSION_TYPE,
140
+ _CONSTRUCT,
141
+ loc,
142
+ f"formatVersion must be an unsigned integer, not {value}",
143
+ )
144
+ if value > _U32_MAX:
145
+ raise fail(
146
+ d.FORMAT_VERSION_OUT_OF_RANGE,
147
+ _CONSTRUCT,
148
+ loc,
149
+ f"formatVersion {value} is above {_U32_MAX}",
150
+ )
151
+ if value == 0:
152
+ raise fail(
153
+ d.INVALID_FORMAT_VERSION_SYNTAX,
154
+ _CONSTRUCT,
155
+ loc,
156
+ "formatVersion 0 is not a format family",
157
+ )
158
+ return FormatVersion(value, 0, 0)
159
+ release = _RELEASE_RE.match(value)
160
+ if release is not None:
161
+ major, minor, patch = (_component(part, value) for part in release.groups())
162
+ version = FormatVersion(major, minor, patch)
163
+ else:
164
+ bare = _MAJOR_RE.match(value)
165
+ if bare is None:
166
+ raise fail(
167
+ d.INVALID_FORMAT_VERSION_SYNTAX,
168
+ _CONSTRUCT,
169
+ loc,
170
+ f"formatVersion {value!r} is not N or N.minor.patch",
171
+ )
172
+ version = FormatVersion(_component(bare.group(1), value), 0, 0)
173
+ if version.major < 3:
174
+ raise fail(
175
+ d.INVALID_FORMAT_VERSION_SYNTAX,
176
+ _CONSTRUCT,
177
+ loc,
178
+ f"formatVersion {value!r} names a major below 3; "
179
+ "formats 1 and 2 are written only as integers",
180
+ )
181
+ return version
182
+
183
+
184
+ def check_supported(
185
+ version: FormatVersion, table: SupportTable = SUPPORT_TABLE
186
+ ) -> FormatVersion:
187
+ """Check a normalized release against a support table.
188
+
189
+ Args:
190
+ version: A release returned by `recognize_format_version`.
191
+ table: The intervals the caller can process.
192
+
193
+ Returns:
194
+ The same release, when it is supported.
195
+
196
+ Raises:
197
+ DiagnosticError: With ``unsupported_format_version_major`` or
198
+ ``unsupported_format_version_minor``.
199
+ """
200
+ if any(version in interval for interval in table):
201
+ return version
202
+ accepted = table_to_string(table)
203
+ loc: d.Location = (_CONSTRUCT,)
204
+ if not any(interval.lower.major == version.major for interval in table):
205
+ if version.major in (1, 2):
206
+ detail = _LEGACY_DETAIL
207
+ else:
208
+ detail = f"format family {version.major} is not supported"
209
+ raise fail(
210
+ d.UNSUPPORTED_FORMAT_VERSION_MAJOR,
211
+ _CONSTRUCT,
212
+ loc,
213
+ f"format version {version} is not supported ({detail}); "
214
+ f"this reader accepts only {_describe(table)} ({accepted})",
215
+ )
216
+ raise fail(
217
+ d.UNSUPPORTED_FORMAT_VERSION_MINOR,
218
+ _CONSTRUCT,
219
+ loc,
220
+ f"format version {version} is not supported; "
221
+ f"this reader accepts only {_describe(table)} ({accepted})",
222
+ )
223
+
224
+
225
+ def _families(interval: Interval) -> list[str]:
226
+ lower, upper = interval.lower, interval.upper
227
+ if upper.major == lower.major and upper.patch == 0:
228
+ minors = range(lower.minor, max(upper.minor, lower.minor + 1))
229
+ else:
230
+ minors = range(lower.minor, lower.minor + 1)
231
+ draft = "draft " if lower.major == 4 else ""
232
+ return [f"{draft}{lower.major}.{minor}.x" for minor in minors]
233
+
234
+
235
+ def _describe(table: SupportTable) -> str:
236
+ names = [name for interval in table for name in _families(interval)]
237
+ if len(names) == 1:
238
+ return names[0]
239
+ return f"{', '.join(names[:-1])} and {names[-1]}"
240
+
241
+
242
+ def read_format_version(
243
+ value: object, table: SupportTable = SUPPORT_TABLE
244
+ ) -> FormatVersion:
245
+ """Recognize, normalize, and support-check a ``formatVersion`` value.
246
+
247
+ Args:
248
+ value: The decoded JSON value of the ``formatVersion`` member.
249
+ table: The intervals the caller can process.
250
+
251
+ Returns:
252
+ The normalized, supported release.
253
+
254
+ Raises:
255
+ DiagnosticError: With one of the finos format-version codes.
256
+ """
257
+ return check_supported(recognize_format_version(value), table)
258
+
259
+
260
+ def write_format_version(version: FormatVersion) -> int | str:
261
+ """Return the canonical spelling: integer N for N.0.0, else the release string.
262
+
263
+ Raises:
264
+ ValueError: For a legacy major (1 or 2); legacy formats are never written.
265
+ """
266
+ if version.major < 3:
267
+ raise ValueError(f"format {version.major} is legacy and is never written")
268
+ if version.minor == 0 and version.patch == 0:
269
+ return version.major
270
+ return str(version)
271
+
272
+
273
+ class _Object(dict[str, object]):
274
+ duplicates: frozenset[str] = frozenset()
275
+
276
+
277
+ def _object_pairs(pairs: list[tuple[str, object]], seen: list[str]) -> _Object:
278
+ obj = _Object()
279
+ dups: set[str] = set()
280
+ for key, value in pairs:
281
+ if key in obj:
282
+ dups.add(key)
283
+ obj[key] = value
284
+ if dups:
285
+ obj.duplicates = frozenset(dups)
286
+ seen.extend(sorted(dups))
287
+ return obj
288
+
289
+
290
+ def parse_json(text: str) -> object:
291
+ """Parse JSON text, rejecting duplicate object members.
292
+
293
+ ``json.loads`` silently keeps the last duplicate member, which the v4 JSON
294
+ profile and the format-version contract both forbid.
295
+
296
+ Raises:
297
+ DiagnosticError: With ``invalid_json``, ``duplicate_format_version`` (root
298
+ only), or ``duplicate_member``.
299
+ """
300
+ seen: list[str] = []
301
+ try:
302
+ root: object = json.loads(
303
+ text, object_pairs_hook=lambda pairs: _object_pairs(pairs, seen)
304
+ )
305
+ except json.JSONDecodeError as error:
306
+ raise fail(
307
+ d.INVALID_JSON, "document", (), f"input is not valid JSON: {error}"
308
+ ) from None
309
+ if isinstance(root, _Object) and _CONSTRUCT in root.duplicates:
310
+ raise fail(
311
+ d.DUPLICATE_FORMAT_VERSION,
312
+ _CONSTRUCT,
313
+ (),
314
+ "the document root contains formatVersion more than once",
315
+ )
316
+ if seen:
317
+ raise fail(
318
+ d.DUPLICATE_MEMBER,
319
+ "object",
320
+ (),
321
+ f"an object contains member {seen[0]!r} more than once",
322
+ )
323
+ return root
324
+
325
+
326
+ def read_document(
327
+ document: str | object, table: SupportTable = SUPPORT_TABLE
328
+ ) -> tuple[FormatVersion, dict[str, object]]:
329
+ """Read the root of a versioned IR document and check its format version.
330
+
331
+ Recognition and the support check finish before any distribution decoder runs.
332
+
333
+ Args:
334
+ document: JSON text, or an already-decoded JSON value. Only text input can
335
+ be checked for duplicate members.
336
+ table: The intervals the caller can process.
337
+
338
+ Returns:
339
+ The supported release and the root object.
340
+
341
+ Raises:
342
+ DiagnosticError: With a format-version or JSON diagnostic.
343
+ """
344
+ obj = _versioned_root(document)
345
+ return read_format_version(obj[_CONSTRUCT], table), obj
346
+
347
+
348
+ def _versioned_root(document: str | object) -> dict[str, object]:
349
+ root = parse_json(document) if isinstance(document, str) else document
350
+ if not isinstance(root, dict):
351
+ raise fail(
352
+ d.INVALID_JSON,
353
+ "document",
354
+ (),
355
+ "the document root must be a JSON object",
356
+ )
357
+ if _CONSTRUCT not in root:
358
+ raise fail(
359
+ d.MISSING_FORMAT_VERSION,
360
+ _CONSTRUCT,
361
+ (),
362
+ "the IR has no formatVersion member; it is in an old format. "
363
+ "Please regenerate it!",
364
+ )
365
+ return dict(root)
366
+
367
+
368
+ def dump_json(value: object) -> str:
369
+ """Serialize JSON compactly with members in insertion order."""
370
+ return json.dumps(value, ensure_ascii=False, separators=(",", ":"))
371
+
372
+
373
+ # --- Legacy formats 1 and 2 (read-only) ---
374
+
375
+ _LEGACY_DETAIL = (
376
+ "formats 1 and 2 are legacy formats outside the support table; "
377
+ "morphir.ir.v3.codec_v1 and codec_v2 read them as format 3.0.0"
378
+ )
379
+
380
+
381
+ class LegacyFormat(Enum):
382
+ """A morphir-elm format from before the release grammar, which starts at 3.
383
+
384
+ morphir-elm wrote formats 1 and 2 only as the JSON integers ``1`` and ``2``.
385
+ They are in no support table: the legacy readers decode them into the
386
+ format 3.0.0 model, and no writer emits them.
387
+ """
388
+
389
+ V1 = 1
390
+ V2 = 2
391
+
392
+ def __str__(self) -> str:
393
+ return str(self.value)
394
+
395
+
396
+ def recognize_legacy_format(value: object) -> LegacyFormat | None:
397
+ """Return the legacy format for the JSON integer ``1`` or ``2``, else ``None``.
398
+
399
+ Example:
400
+ >>> recognize_legacy_format(1)
401
+ <LegacyFormat.V1: 1>
402
+ >>> recognize_legacy_format("1") is None
403
+ True
404
+ """
405
+ if isinstance(value, bool) or not isinstance(value, int):
406
+ return None
407
+ return {1: LegacyFormat.V1, 2: LegacyFormat.V2}.get(value)
408
+
409
+
410
+ def read_document_with_legacy(
411
+ document: str | object, table: SupportTable = SUPPORT_TABLE
412
+ ) -> tuple[FormatVersion | LegacyFormat, dict[str, object]]:
413
+ """Read a document root like `read_document`, but report legacy formats.
414
+
415
+ The integers ``1`` and ``2`` give a `LegacyFormat`; every other value goes
416
+ through `read_format_version` with ``table`` and fails as it does there.
417
+
418
+ Raises:
419
+ DiagnosticError: With a format-version or JSON diagnostic.
420
+ """
421
+ obj = _versioned_root(document)
422
+ legacy = recognize_legacy_format(obj[_CONSTRUCT])
423
+ if legacy is not None:
424
+ return legacy, obj
425
+ return read_format_version(obj[_CONSTRUCT], table), obj
426
+
427
+
428
+ def read_legacy_document(
429
+ document: str | object, accepted: LegacyFormat
430
+ ) -> dict[str, object]:
431
+ """Read the root of a legacy document and check that it is ``accepted``.
432
+
433
+ Args:
434
+ document: JSON text, or an already-decoded JSON value.
435
+ accepted: The one legacy format the caller decodes.
436
+
437
+ Returns:
438
+ The root object.
439
+
440
+ Raises:
441
+ DiagnosticError: With ``unsupported_format_version_major`` for any other
442
+ format, or with the recognition diagnostic for a malformed version.
443
+ """
444
+ obj = _versioned_root(document)
445
+ value = obj[_CONSTRUCT]
446
+ found: FormatVersion | LegacyFormat | None = recognize_legacy_format(value)
447
+ if found is accepted:
448
+ return obj
449
+ if found is None:
450
+ found = recognize_format_version(value)
451
+ raise fail(
452
+ d.UNSUPPORTED_FORMAT_VERSION_MAJOR,
453
+ _CONSTRUCT,
454
+ (_CONSTRUCT,),
455
+ f"format version {found} is not supported; "
456
+ f"this reader accepts only legacy format {accepted}",
457
+ )
458
+
459
+
460
+ __all__ = [
461
+ "SUPPORT_TABLE",
462
+ "V3",
463
+ "V3_1",
464
+ "V3_TABLE",
465
+ "V4",
466
+ "V4_TABLE",
467
+ "DiagnosticError",
468
+ "FormatVersion",
469
+ "Interval",
470
+ "LegacyFormat",
471
+ "SupportTable",
472
+ "check_supported",
473
+ "dump_json",
474
+ "parse_json",
475
+ "read_document",
476
+ "read_document_with_legacy",
477
+ "read_format_version",
478
+ "read_legacy_document",
479
+ "recognize_format_version",
480
+ "recognize_legacy_format",
481
+ "table_to_string",
482
+ "write_format_version",
483
+ ]
morphir/ir/fqname.py ADDED
@@ -0,0 +1,9 @@
1
+ """Compatibility shim: re-exports `morphir.ir.v4.fqname`."""
2
+
3
+ from morphir.ir.v4.fqname import (
4
+ FQName,
5
+ )
6
+
7
+ __all__ = [
8
+ "FQName",
9
+ ]
morphir/ir/json.py ADDED
@@ -0,0 +1,11 @@
1
+ """Compatibility shim: re-exports `morphir.ir.v4.json`."""
2
+
3
+ from morphir.ir.v4.json import (
4
+ MorphirJSONEncoder,
5
+ encode,
6
+ )
7
+
8
+ __all__ = [
9
+ "MorphirJSONEncoder",
10
+ "encode",
11
+ ]
morphir/ir/literal.py ADDED
@@ -0,0 +1,25 @@
1
+ """Compatibility shim: re-exports `morphir.ir.v4.literal`."""
2
+
3
+ from morphir.ir.v4.document import Document
4
+ from morphir.ir.v4.literal import (
5
+ BoolLiteral,
6
+ CharLiteral,
7
+ DecimalLiteral,
8
+ DocumentLiteral,
9
+ FloatLiteral,
10
+ IntegerLiteral,
11
+ Literal,
12
+ StringLiteral,
13
+ )
14
+
15
+ __all__ = [
16
+ "BoolLiteral",
17
+ "CharLiteral",
18
+ "DecimalLiteral",
19
+ "Document",
20
+ "DocumentLiteral",
21
+ "FloatLiteral",
22
+ "IntegerLiteral",
23
+ "Literal",
24
+ "StringLiteral",
25
+ ]
morphir/ir/meta.py ADDED
@@ -0,0 +1,11 @@
1
+ """Compatibility shim: re-exports `morphir.ir.v4.meta`."""
2
+
3
+ from morphir.ir.v4.meta import (
4
+ FileMeta,
5
+ SourceRange,
6
+ )
7
+
8
+ __all__ = [
9
+ "FileMeta",
10
+ "SourceRange",
11
+ ]