omlish 0.0.0.dev23__py3-none-any.whl → 0.0.0.dev25__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 (46) hide show
  1. omlish/__about__.py +16 -4
  2. omlish/_manifests.json +1 -0
  3. omlish/bootstrap/diag.py +2 -2
  4. omlish/check.py +202 -24
  5. omlish/collections/__init__.py +2 -2
  6. omlish/collections/utils.py +3 -3
  7. omlish/concurrent/threadlets.py +5 -0
  8. omlish/dataclasses/__init__.py +1 -0
  9. omlish/dataclasses/impl/LICENSE +279 -0
  10. omlish/dataclasses/impl/init.py +10 -2
  11. omlish/dataclasses/impl/metadata.py +3 -3
  12. omlish/dataclasses/impl/reflect.py +1 -1
  13. omlish/dataclasses/utils.py +16 -3
  14. omlish/diag/pycharm.py +69 -10
  15. omlish/docker.py +16 -11
  16. omlish/genmachine.py +2 -1
  17. omlish/graphs/trees.py +1 -1
  18. omlish/lang/__init__.py +14 -1
  19. omlish/lang/cached.py +5 -2
  20. omlish/lang/descriptors.py +33 -16
  21. omlish/lang/resources.py +60 -0
  22. omlish/lang/typing.py +32 -0
  23. omlish/lite/logs.py +133 -4
  24. omlish/logs/__init__.py +17 -2
  25. omlish/logs/configs.py +13 -1
  26. omlish/logs/formatters.py +0 -1
  27. omlish/marshal/__init__.py +2 -0
  28. omlish/marshal/helpers.py +27 -0
  29. omlish/specs/jsonschema/keywords/base.py +2 -2
  30. omlish/specs/jsonschema/keywords/parse.py +1 -1
  31. omlish/specs/jsonschema/schemas/draft202012/metaschema.json +58 -0
  32. omlish/specs/jsonschema/schemas/draft202012/vocabularies/applicator.json +48 -0
  33. omlish/specs/jsonschema/schemas/draft202012/vocabularies/content.json +17 -0
  34. omlish/specs/jsonschema/schemas/draft202012/vocabularies/core.json +51 -0
  35. omlish/specs/jsonschema/schemas/draft202012/vocabularies/format-annotation.json +14 -0
  36. omlish/specs/jsonschema/schemas/draft202012/vocabularies/format-assertion.json +14 -0
  37. omlish/specs/jsonschema/schemas/draft202012/vocabularies/format.json +14 -0
  38. omlish/specs/jsonschema/schemas/draft202012/vocabularies/meta-data.json +37 -0
  39. omlish/specs/jsonschema/schemas/draft202012/vocabularies/unevaluated.json +15 -0
  40. omlish/specs/jsonschema/schemas/draft202012/vocabularies/validation.json +98 -0
  41. omlish/stats.py +1 -0
  42. {omlish-0.0.0.dev23.dist-info → omlish-0.0.0.dev25.dist-info}/METADATA +1 -1
  43. {omlish-0.0.0.dev23.dist-info → omlish-0.0.0.dev25.dist-info}/RECORD +46 -33
  44. {omlish-0.0.0.dev23.dist-info → omlish-0.0.0.dev25.dist-info}/LICENSE +0 -0
  45. {omlish-0.0.0.dev23.dist-info → omlish-0.0.0.dev25.dist-info}/WHEEL +0 -0
  46. {omlish-0.0.0.dev23.dist-info → omlish-0.0.0.dev25.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,60 @@
1
+ import functools
2
+ import importlib.resources
3
+ import os.path
4
+ import typing as ta
5
+
6
+
7
+ class RelativeResource(ta.NamedTuple):
8
+ name: str
9
+ is_file: bool
10
+ read_bytes: ta.Callable[[], bytes]
11
+
12
+
13
+ def get_relative_resources(
14
+ prefix: str | None = None,
15
+ *,
16
+ globals: ta.Mapping[str, ta.Any] | None = None, # noqa
17
+ package: str | None = None,
18
+ file: str | None = None,
19
+ ) -> ta.Mapping[str, RelativeResource]:
20
+ if globals is not None:
21
+ if not package:
22
+ package = globals.get('__package__')
23
+ if not file:
24
+ file = globals.get('__file__')
25
+
26
+ lst: list[RelativeResource] = []
27
+
28
+ if package:
29
+ anchor = package
30
+ if prefix:
31
+ anchor += '.' + prefix.replace(os.sep, '.')
32
+
33
+ for pf in importlib.resources.files(anchor).iterdir():
34
+ lst.append(RelativeResource(
35
+ name=pf.name,
36
+ is_file=pf.is_file(),
37
+ read_bytes=pf.read_bytes if pf.is_file() else None, # type: ignore
38
+ ))
39
+
40
+ elif file:
41
+ path = os.path.dirname(file)
42
+ if prefix:
43
+ path = os.path.join(path, prefix.replace('.', os.sep))
44
+
45
+ def _read_file(fp: str) -> bytes:
46
+ with open(fp, 'rb') as f:
47
+ return f.read()
48
+
49
+ for ff in os.listdir(path):
50
+ ff = os.path.join(path, ff)
51
+ lst.append(RelativeResource(
52
+ name=os.path.basename(ff),
53
+ is_file=os.path.isfile(ff),
54
+ read_bytes=functools.partial(_read_file, ff),
55
+ ))
56
+
57
+ else:
58
+ raise RuntimeError('no package or file specified')
59
+
60
+ return {r.name: r for r in lst}
omlish/lang/typing.py CHANGED
@@ -14,6 +14,9 @@ import typing as ta
14
14
  Ty = ta.TypeVar('Ty', bound=type)
15
15
 
16
16
  T = ta.TypeVar('T')
17
+ T_co = ta.TypeVar('T_co', covariant=True)
18
+ T_contra = ta.TypeVar('T_contra', contravariant=True)
19
+
17
20
  A0 = ta.TypeVar('A0')
18
21
  A1 = ta.TypeVar('A1')
19
22
  A2 = ta.TypeVar('A2')
@@ -133,3 +136,32 @@ class Func3(ta.Generic[A0, A1, A2, T]):
133
136
 
134
137
  def __call__(self, a0: A0, a1: A1, a2: A2) -> T:
135
138
  return self.fn(a0, a1, a2)
139
+
140
+
141
+ ##
142
+
143
+
144
+ class SequenceNotStr(ta.Protocol[T_co]):
145
+ """
146
+ https://github.com/python/mypy/issues/11001
147
+ https://github.com/python/typing/issues/256#issuecomment-1442633430
148
+ https://github.com/hauntsaninja/useful_types/blob/735ef9dd0b55b35b118ef630d5a0f3618ecedbff/useful_types/__init__.py#L285
149
+ """
150
+
151
+ @ta.overload
152
+ def __getitem__(self, index: ta.SupportsIndex, /) -> T_co: ...
153
+
154
+ @ta.overload
155
+ def __getitem__(self, index: slice, /) -> ta.Sequence[T_co]: ... # noqa
156
+
157
+ def __contains__(self, value: object, /) -> bool: ...
158
+
159
+ def __len__(self) -> int: ...
160
+
161
+ def __iter__(self) -> ta.Iterator[T_co]: ...
162
+
163
+ def index(self, value: ta.Any, start: int = 0, stop: int = ..., /) -> int: ...
164
+
165
+ def count(self, value: ta.Any, /) -> int: ...
166
+
167
+ def __reversed__(self) -> ta.Iterator[T_co]: ...
omlish/lite/logs.py CHANGED
@@ -97,13 +97,134 @@ class StandardLogFormatter(logging.Formatter):
97
97
  ##
98
98
 
99
99
 
100
+ class ProxyLogFilterer(logging.Filterer):
101
+ def __init__(self, underlying: logging.Filterer) -> None: # noqa
102
+ self._underlying = underlying
103
+
104
+ @property
105
+ def underlying(self) -> logging.Filterer:
106
+ return self._underlying
107
+
108
+ @property
109
+ def filters(self):
110
+ return self._underlying.filters
111
+
112
+ @filters.setter
113
+ def filters(self, filters):
114
+ self._underlying.filters = filters
115
+
116
+ def addFilter(self, filter): # noqa
117
+ self._underlying.addFilter(filter)
118
+
119
+ def removeFilter(self, filter): # noqa
120
+ self._underlying.removeFilter(filter)
121
+
122
+ def filter(self, record):
123
+ return self._underlying.filter(record)
124
+
125
+
126
+ class ProxyLogHandler(ProxyLogFilterer, logging.Handler):
127
+ def __init__(self, underlying: logging.Handler) -> None: # noqa
128
+ ProxyLogFilterer.__init__(self, underlying)
129
+
130
+ _underlying: logging.Handler
131
+
132
+ @property
133
+ def underlying(self) -> logging.Handler:
134
+ return self._underlying
135
+
136
+ def get_name(self):
137
+ return self._underlying.get_name()
138
+
139
+ def set_name(self, name):
140
+ self._underlying.set_name(name)
141
+
142
+ @property
143
+ def name(self):
144
+ return self._underlying.name
145
+
146
+ @property
147
+ def level(self):
148
+ return self._underlying.level
149
+
150
+ @level.setter
151
+ def level(self, level):
152
+ self._underlying.level = level
153
+
154
+ @property
155
+ def formatter(self):
156
+ return self._underlying.formatter
157
+
158
+ @formatter.setter
159
+ def formatter(self, formatter):
160
+ self._underlying.formatter = formatter
161
+
162
+ def createLock(self):
163
+ self._underlying.createLock()
164
+
165
+ def acquire(self):
166
+ self._underlying.acquire()
167
+
168
+ def release(self):
169
+ self._underlying.release()
170
+
171
+ def setLevel(self, level):
172
+ self._underlying.setLevel(level)
173
+
174
+ def format(self, record):
175
+ return self._underlying.format(record)
176
+
177
+ def emit(self, record):
178
+ self._underlying.emit(record)
179
+
180
+ def handle(self, record):
181
+ return self._underlying.handle(record)
182
+
183
+ def setFormatter(self, fmt):
184
+ self._underlying.setFormatter(fmt)
185
+
186
+ def flush(self):
187
+ self._underlying.flush()
188
+
189
+ def close(self):
190
+ self._underlying.close()
191
+
192
+ def handleError(self, record):
193
+ self._underlying.handleError(record)
194
+
195
+
196
+ ##
197
+
198
+
199
+ class StandardLogHandler(ProxyLogHandler):
200
+ pass
201
+
202
+
203
+ ##
204
+
205
+
100
206
  def configure_standard_logging(
101
207
  level: ta.Union[int, str] = logging.INFO,
102
208
  *,
103
209
  json: bool = False,
104
- ) -> logging.Handler:
210
+ target: ta.Optional[logging.Logger] = None,
211
+ no_check: bool = False,
212
+ ) -> ta.Optional[StandardLogHandler]:
213
+ if target is None:
214
+ target = logging.root
215
+
216
+ #
217
+
218
+ if not no_check:
219
+ if any(isinstance(h, StandardLogHandler) for h in list(target.handlers)):
220
+ return None
221
+
222
+ #
223
+
105
224
  handler = logging.StreamHandler()
106
225
 
226
+ #
227
+
107
228
  formatter: logging.Formatter
108
229
  if json:
109
230
  formatter = JsonLogFormatter()
@@ -111,11 +232,19 @@ def configure_standard_logging(
111
232
  formatter = StandardLogFormatter(StandardLogFormatter.build_log_format(STANDARD_LOG_FORMAT_PARTS))
112
233
  handler.setFormatter(formatter)
113
234
 
235
+ #
236
+
114
237
  handler.addFilter(TidLogFilter())
115
238
 
116
- logging.root.addHandler(handler)
239
+ #
240
+
241
+ target.addHandler(handler)
242
+
243
+ #
117
244
 
118
245
  if level is not None:
119
- logging.root.setLevel(level)
246
+ target.setLevel(level)
247
+
248
+ #
120
249
 
121
- return handler
250
+ return StandardLogHandler(handler)
omlish/logs/__init__.py CHANGED
@@ -4,8 +4,6 @@ from .configs import ( # noqa
4
4
 
5
5
  from .formatters import ( # noqa
6
6
  ColorLogFormatter,
7
- JsonLogFormatter,
8
- StandardLogFormatter,
9
7
  )
10
8
 
11
9
  from .handlers import ( # noqa
@@ -15,3 +13,20 @@ from .handlers import ( # noqa
15
13
  from .utils import ( # noqa
16
14
  error_logging,
17
15
  )
16
+
17
+
18
+ ##
19
+
20
+
21
+ from ..lite.logs import ( # noqa
22
+ TidLogFilter,
23
+ JsonLogFormatter,
24
+
25
+ STANDARD_LOG_FORMAT_PARTS,
26
+ StandardLogFormatter,
27
+
28
+ ProxyLogFilterer,
29
+ ProxyLogHandler,
30
+
31
+ StandardLogHandler,
32
+ )
omlish/logs/configs.py CHANGED
@@ -2,6 +2,7 @@ import dataclasses as dc
2
2
  import logging
3
3
  import typing as ta
4
4
 
5
+ from ..lite.logs import StandardLogHandler
5
6
  from ..lite.logs import configure_standard_logging as configure_lite_standard_logging
6
7
  from .noisy import silence_noisy_loggers
7
8
 
@@ -34,12 +35,23 @@ def configure_standard_logging(
34
35
  level: ta.Any = None,
35
36
  *,
36
37
  json: bool = False,
37
- ) -> logging.Handler:
38
+ target: logging.Logger | None = None,
39
+ no_check: bool = False,
40
+ ) -> StandardLogHandler | None:
38
41
  handler = configure_lite_standard_logging(
39
42
  level,
40
43
  json=json,
44
+ target=target,
45
+ no_check=no_check,
41
46
  )
42
47
 
48
+ if handler is None:
49
+ return None
50
+
51
+ #
52
+
43
53
  silence_noisy_loggers()
44
54
 
55
+ #
56
+
45
57
  return handler
omlish/logs/formatters.py CHANGED
@@ -3,7 +3,6 @@ import logging
3
3
  import typing as ta
4
4
 
5
5
  from .. import term
6
- from ..lite.logs import JsonLogFormatter # noqa
7
6
  from ..lite.logs import StandardLogFormatter
8
7
 
9
8
 
@@ -49,7 +49,9 @@ from .global_ import ( # noqa
49
49
  )
50
50
 
51
51
  from .helpers import ( # noqa
52
+ update_field_metadata,
52
53
  update_fields_metadata,
54
+ update_object_metadata,
53
55
  )
54
56
 
55
57
  from .objects import ( # noqa
omlish/marshal/helpers.py CHANGED
@@ -2,11 +2,24 @@ import typing as ta
2
2
 
3
3
  from .. import dataclasses as dc
4
4
  from .objects import FieldMetadata
5
+ from .objects import ObjectMetadata
5
6
 
6
7
 
7
8
  T = ta.TypeVar('T')
8
9
 
9
10
 
11
+ def update_field_metadata(**kwargs: ta.Any) -> dc.field_modifier:
12
+ @dc.field_modifier
13
+ def inner(f: dc.Field) -> dc.Field:
14
+ return dc.update_field_metadata(f, {
15
+ FieldMetadata: dc.replace(
16
+ f.metadata.get(FieldMetadata, FieldMetadata()),
17
+ **kwargs,
18
+ ),
19
+ })
20
+ return inner
21
+
22
+
10
23
  def update_fields_metadata(
11
24
  fields: ta.Iterable[str] | None = None,
12
25
  **kwargs: ta.Any,
@@ -20,3 +33,17 @@ def update_fields_metadata(
20
33
  })
21
34
 
22
35
  return dc.update_fields(inner, fields)
36
+
37
+
38
+ def update_object_metadata(
39
+ cls: type | None = None,
40
+ **kwargs: ta.Any,
41
+ ):
42
+ def inner(cls):
43
+ return dc.update_class_metadata(cls, ObjectMetadata(**kwargs))
44
+
45
+ if cls is not None:
46
+ inner(cls)
47
+ return cls
48
+ else:
49
+ return inner
@@ -37,12 +37,12 @@ class Keywords(lang.Final):
37
37
  @cached.property
38
38
  @dc.init
39
39
  def by_type(self) -> ta.Mapping[type[Keyword], Keyword]:
40
- return col.unique_map_by(type, self.lst, strict=True) # noqa
40
+ return col.make_map_by(type, self.lst, strict=True) # noqa
41
41
 
42
42
  @cached.property
43
43
  @dc.init
44
44
  def by_tag(self) -> ta.Mapping[str, Keyword]:
45
- return col.unique_map_by(operator.attrgetter('tag'), self.lst, strict=True) # noqa
45
+ return col.make_map_by(operator.attrgetter('tag'), self.lst, strict=True) # noqa
46
46
 
47
47
  def __getitem__(self, item: type[KeywordT] | str) -> KeywordT:
48
48
  if isinstance(item, type):
@@ -24,7 +24,7 @@ KeywordT = ta.TypeVar('KeywordT', bound=Keyword)
24
24
  ##
25
25
 
26
26
 
27
- KEYWORD_TYPES_BY_TAG: ta.Mapping[str, type[Keyword]] = col.unique_map_by( # noqa
27
+ KEYWORD_TYPES_BY_TAG: ta.Mapping[str, type[Keyword]] = col.make_map_by( # noqa
28
28
  operator.attrgetter('tag'),
29
29
  (cls for cls in lang.deep_subclasses(Keyword) if not lang.is_abstract_class(cls)),
30
30
  strict=True,
@@ -0,0 +1,58 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://json-schema.org/draft/2020-12/schema",
4
+ "$vocabulary": {
5
+ "https://json-schema.org/draft/2020-12/vocab/core": true,
6
+ "https://json-schema.org/draft/2020-12/vocab/applicator": true,
7
+ "https://json-schema.org/draft/2020-12/vocab/unevaluated": true,
8
+ "https://json-schema.org/draft/2020-12/vocab/validation": true,
9
+ "https://json-schema.org/draft/2020-12/vocab/meta-data": true,
10
+ "https://json-schema.org/draft/2020-12/vocab/format-annotation": true,
11
+ "https://json-schema.org/draft/2020-12/vocab/content": true
12
+ },
13
+ "$dynamicAnchor": "meta",
14
+
15
+ "title": "Core and Validation specifications meta-schema",
16
+ "allOf": [
17
+ {"$ref": "meta/core"},
18
+ {"$ref": "meta/applicator"},
19
+ {"$ref": "meta/unevaluated"},
20
+ {"$ref": "meta/validation"},
21
+ {"$ref": "meta/meta-data"},
22
+ {"$ref": "meta/format-annotation"},
23
+ {"$ref": "meta/content"}
24
+ ],
25
+ "type": ["object", "boolean"],
26
+ "$comment": "This meta-schema also defines keywords that have appeared in previous drafts in order to prevent incompatible extensions as they remain in common use.",
27
+ "properties": {
28
+ "definitions": {
29
+ "$comment": "\"definitions\" has been replaced by \"$defs\".",
30
+ "type": "object",
31
+ "additionalProperties": { "$dynamicRef": "#meta" },
32
+ "deprecated": true,
33
+ "default": {}
34
+ },
35
+ "dependencies": {
36
+ "$comment": "\"dependencies\" has been split and replaced by \"dependentSchemas\" and \"dependentRequired\" in order to serve their differing semantics.",
37
+ "type": "object",
38
+ "additionalProperties": {
39
+ "anyOf": [
40
+ { "$dynamicRef": "#meta" },
41
+ { "$ref": "meta/validation#/$defs/stringArray" }
42
+ ]
43
+ },
44
+ "deprecated": true,
45
+ "default": {}
46
+ },
47
+ "$recursiveAnchor": {
48
+ "$comment": "\"$recursiveAnchor\" has been replaced by \"$dynamicAnchor\".",
49
+ "$ref": "meta/core#/$defs/anchorString",
50
+ "deprecated": true
51
+ },
52
+ "$recursiveRef": {
53
+ "$comment": "\"$recursiveRef\" has been replaced by \"$dynamicRef\".",
54
+ "$ref": "meta/core#/$defs/uriReferenceString",
55
+ "deprecated": true
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,48 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://json-schema.org/draft/2020-12/meta/applicator",
4
+ "$vocabulary": {
5
+ "https://json-schema.org/draft/2020-12/vocab/applicator": true
6
+ },
7
+ "$dynamicAnchor": "meta",
8
+
9
+ "title": "Applicator vocabulary meta-schema",
10
+ "type": ["object", "boolean"],
11
+ "properties": {
12
+ "prefixItems": { "$ref": "#/$defs/schemaArray" },
13
+ "items": { "$dynamicRef": "#meta" },
14
+ "contains": { "$dynamicRef": "#meta" },
15
+ "additionalProperties": { "$dynamicRef": "#meta" },
16
+ "properties": {
17
+ "type": "object",
18
+ "additionalProperties": { "$dynamicRef": "#meta" },
19
+ "default": {}
20
+ },
21
+ "patternProperties": {
22
+ "type": "object",
23
+ "additionalProperties": { "$dynamicRef": "#meta" },
24
+ "propertyNames": { "format": "regex" },
25
+ "default": {}
26
+ },
27
+ "dependentSchemas": {
28
+ "type": "object",
29
+ "additionalProperties": { "$dynamicRef": "#meta" },
30
+ "default": {}
31
+ },
32
+ "propertyNames": { "$dynamicRef": "#meta" },
33
+ "if": { "$dynamicRef": "#meta" },
34
+ "then": { "$dynamicRef": "#meta" },
35
+ "else": { "$dynamicRef": "#meta" },
36
+ "allOf": { "$ref": "#/$defs/schemaArray" },
37
+ "anyOf": { "$ref": "#/$defs/schemaArray" },
38
+ "oneOf": { "$ref": "#/$defs/schemaArray" },
39
+ "not": { "$dynamicRef": "#meta" }
40
+ },
41
+ "$defs": {
42
+ "schemaArray": {
43
+ "type": "array",
44
+ "minItems": 1,
45
+ "items": { "$dynamicRef": "#meta" }
46
+ }
47
+ }
48
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://json-schema.org/draft/2020-12/meta/content",
4
+ "$vocabulary": {
5
+ "https://json-schema.org/draft/2020-12/vocab/content": true
6
+ },
7
+ "$dynamicAnchor": "meta",
8
+
9
+ "title": "Content vocabulary meta-schema",
10
+
11
+ "type": ["object", "boolean"],
12
+ "properties": {
13
+ "contentEncoding": { "type": "string" },
14
+ "contentMediaType": { "type": "string" },
15
+ "contentSchema": { "$dynamicRef": "#meta" }
16
+ }
17
+ }
@@ -0,0 +1,51 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://json-schema.org/draft/2020-12/meta/core",
4
+ "$vocabulary": {
5
+ "https://json-schema.org/draft/2020-12/vocab/core": true
6
+ },
7
+ "$dynamicAnchor": "meta",
8
+
9
+ "title": "Core vocabulary meta-schema",
10
+ "type": ["object", "boolean"],
11
+ "properties": {
12
+ "$id": {
13
+ "$ref": "#/$defs/uriReferenceString",
14
+ "$comment": "Non-empty fragments not allowed.",
15
+ "pattern": "^[^#]*#?$"
16
+ },
17
+ "$schema": { "$ref": "#/$defs/uriString" },
18
+ "$ref": { "$ref": "#/$defs/uriReferenceString" },
19
+ "$anchor": { "$ref": "#/$defs/anchorString" },
20
+ "$dynamicRef": { "$ref": "#/$defs/uriReferenceString" },
21
+ "$dynamicAnchor": { "$ref": "#/$defs/anchorString" },
22
+ "$vocabulary": {
23
+ "type": "object",
24
+ "propertyNames": { "$ref": "#/$defs/uriString" },
25
+ "additionalProperties": {
26
+ "type": "boolean"
27
+ }
28
+ },
29
+ "$comment": {
30
+ "type": "string"
31
+ },
32
+ "$defs": {
33
+ "type": "object",
34
+ "additionalProperties": { "$dynamicRef": "#meta" }
35
+ }
36
+ },
37
+ "$defs": {
38
+ "anchorString": {
39
+ "type": "string",
40
+ "pattern": "^[A-Za-z_][-A-Za-z0-9._]*$"
41
+ },
42
+ "uriString": {
43
+ "type": "string",
44
+ "format": "uri"
45
+ },
46
+ "uriReferenceString": {
47
+ "type": "string",
48
+ "format": "uri-reference"
49
+ }
50
+ }
51
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://json-schema.org/draft/2020-12/meta/format-annotation",
4
+ "$vocabulary": {
5
+ "https://json-schema.org/draft/2020-12/vocab/format-annotation": true
6
+ },
7
+ "$dynamicAnchor": "meta",
8
+
9
+ "title": "Format vocabulary meta-schema for annotation results",
10
+ "type": ["object", "boolean"],
11
+ "properties": {
12
+ "format": { "type": "string" }
13
+ }
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://json-schema.org/draft/2020-12/meta/format-assertion",
4
+ "$vocabulary": {
5
+ "https://json-schema.org/draft/2020-12/vocab/format-assertion": true
6
+ },
7
+ "$dynamicAnchor": "meta",
8
+
9
+ "title": "Format vocabulary meta-schema for assertion results",
10
+ "type": ["object", "boolean"],
11
+ "properties": {
12
+ "format": { "type": "string" }
13
+ }
14
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2019-09/schema",
3
+ "$id": "https://json-schema.org/draft/2019-09/meta/format",
4
+ "$vocabulary": {
5
+ "https://json-schema.org/draft/2019-09/vocab/format": true
6
+ },
7
+ "$recursiveAnchor": true,
8
+
9
+ "title": "Format vocabulary meta-schema",
10
+ "type": ["object", "boolean"],
11
+ "properties": {
12
+ "format": { "type": "string" }
13
+ }
14
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://json-schema.org/draft/2020-12/meta/meta-data",
4
+ "$vocabulary": {
5
+ "https://json-schema.org/draft/2020-12/vocab/meta-data": true
6
+ },
7
+ "$dynamicAnchor": "meta",
8
+
9
+ "title": "Meta-data vocabulary meta-schema",
10
+
11
+ "type": ["object", "boolean"],
12
+ "properties": {
13
+ "title": {
14
+ "type": "string"
15
+ },
16
+ "description": {
17
+ "type": "string"
18
+ },
19
+ "default": true,
20
+ "deprecated": {
21
+ "type": "boolean",
22
+ "default": false
23
+ },
24
+ "readOnly": {
25
+ "type": "boolean",
26
+ "default": false
27
+ },
28
+ "writeOnly": {
29
+ "type": "boolean",
30
+ "default": false
31
+ },
32
+ "examples": {
33
+ "type": "array",
34
+ "items": true
35
+ }
36
+ }
37
+ }