infinity-data 1.1.0__tar.gz → 1.2.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 (57) hide show
  1. {infinity_data-1.1.0/src/infinity_data.egg-info → infinity_data-1.2.0}/PKG-INFO +1 -1
  2. {infinity_data-1.1.0 → infinity_data-1.2.0}/pyproject.toml +4 -1
  3. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/parser/diagnostics.py +5 -0
  4. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/parser/parser.py +22 -2
  5. infinity_data-1.2.0/src/infinity_data/py.typed +0 -0
  6. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/registry/dict_constraints.py +13 -4
  7. {infinity_data-1.1.0 → infinity_data-1.2.0/src/infinity_data.egg-info}/PKG-INFO +1 -1
  8. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data.egg-info/SOURCES.txt +1 -0
  9. {infinity_data-1.1.0 → infinity_data-1.2.0}/LICENSE +0 -0
  10. {infinity_data-1.1.0 → infinity_data-1.2.0}/README.md +0 -0
  11. {infinity_data-1.1.0 → infinity_data-1.2.0}/setup.cfg +0 -0
  12. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/__init__.py +0 -0
  13. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/emit/__init__.py +0 -0
  14. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/emit/converter.py +0 -0
  15. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/frontend.py +0 -0
  16. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/infra/__init__.py +0 -0
  17. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/infra/diagnostics.py +0 -0
  18. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/infra/file.py +0 -0
  19. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/infra/ll1_stream.py +0 -0
  20. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/infra/location.py +0 -0
  21. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/infra/path.py +0 -0
  22. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/parser/__init__.py +0 -0
  23. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/parser/models.py +0 -0
  24. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/parser/token_stream.py +0 -0
  25. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/pipeline.py +0 -0
  26. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/sandbox/__init__.py +0 -0
  27. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/sandbox/config.py +0 -0
  28. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/sandbox/errors.py +0 -0
  29. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/sandbox/mediator.py +0 -0
  30. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/sandbox/schema.py +0 -0
  31. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/__init__.py +0 -0
  32. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/builder/__init__.py +0 -0
  33. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/builder/builder.py +0 -0
  34. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/builder/models.py +0 -0
  35. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/constraints.py +0 -0
  36. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/diagnostics.py +0 -0
  37. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/executor/__init__.py +0 -0
  38. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/executor/executor.py +0 -0
  39. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/registry/__init__.py +0 -0
  40. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/registry/_core.py +0 -0
  41. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/registry/general.py +0 -0
  42. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/registry/logic.py +0 -0
  43. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/registry/types.py +0 -0
  44. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/resolver/__init__.py +0 -0
  45. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/resolver/imports.py +0 -0
  46. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/resolver/models.py +0 -0
  47. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/semantic/resolver/resolver.py +0 -0
  48. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/tokenizer/__init__.py +0 -0
  49. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/tokenizer/char_stream.py +0 -0
  50. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/tokenizer/diagnostics.py +0 -0
  51. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/tokenizer/finalizer.py +0 -0
  52. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/tokenizer/models/__init__.py +0 -0
  53. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/tokenizer/models/raw_tokens.py +0 -0
  54. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/tokenizer/models/tokens.py +0 -0
  55. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data/tokenizer/tokenizer.py +0 -0
  56. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data.egg-info/dependency_links.txt +0 -0
  57. {infinity_data-1.1.0 → infinity_data-1.2.0}/src/infinity_data.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: infinity-data
3
- Version: 1.1.0
3
+ Version: 1.2.0
4
4
  Summary: InfinityData:声明式配置语言(.infd/.inft)的 Python 编译器库
5
5
  Author: infinity_system: yin_bailiang
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "infinity-data"
3
- version = "1.1.0"
3
+ version = "1.2.0"
4
4
  description = "InfinityData:声明式配置语言(.infd/.inft)的 Python 编译器库"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -57,6 +57,9 @@ package-dir = {"" = "src"}
57
57
  [tool.setuptools.packages.find]
58
58
  where = ["src"]
59
59
 
60
+ [tool.setuptools.package-data]
61
+ infinity_data = ["py.typed"]
62
+
60
63
  [tool.ruff]
61
64
  line-length = 120
62
65
  target-version = "py312"
@@ -48,6 +48,11 @@ register_diagnostic_define(
48
48
  '[{location}] 导入项之间必须用逗号分隔(import 列表不接受换行/空格分隔)',
49
49
  en='[{location}] import items must be separated by commas (newlines/spaces are not allowed)',
50
50
  ),
51
+ diagnostic_define(
52
+ 'parse.import_requires_newline',
53
+ '[{location}] 导入语句必须以换行结尾(同一行逗号后不能再接其他语句)',
54
+ en='[{location}] import statement must end with a newline (cannot be followed by more tokens on the same line)',
55
+ ),
51
56
  diagnostic_define(
52
57
  'parse.value_field',
53
58
  '[{location}] 值位置出现字段定义 {name}(外层数组/对象未闭合)',
@@ -138,8 +138,13 @@ class Parser:
138
138
 
139
139
  @staticmethod
140
140
  def _parse_statement(stream: TokenStream, collector: DiagnosticCollector) -> Statement | None:
141
- """解析一条顶层语句。"""
142
- stream.skip_newlines()
141
+ """解析一条顶层语句。
142
+
143
+ 顶层与块内一致,接受**逗号或换行**分隔(二者等价,可混用)——
144
+ 整个文件(含模板定义、字段、结构级约束)可压缩成一行;
145
+ 导入语句内部仍强制逗号分隔(见 §3.2)。
146
+ """
147
+ stream.skip_separators()
143
148
 
144
149
  # EofToken 或物理耗尽均视为流结束
145
150
  if stream.eof():
@@ -223,6 +228,21 @@ class Parser:
223
228
  stream.advance()
224
229
  alias = stream.expect(IdentifierToken).name
225
230
 
231
+ # 导入语句必须换行/EOF 结尾:!env 无导入项列表,若不加检查,同一行的逗号会被
232
+ # 顶层 skip_separators 吞掉(`!env import A as a, x = 1` 被误认为合法),与
233
+ # !from / !file 的「尾部必须换行」行为不一致。
234
+ tok = stream.peek()
235
+ # 显式排除 NoNextType 以收窄类型:stream.eof() 是方法调用,无法据此收窄 tok,
236
+ # 否则 tok 仍为 Token | NoNextType,访问 tok.raw 会触发类型错误。
237
+ if not isinstance(tok, NoNextType) and not (stream.eof() or isinstance(tok, NewlineToken)):
238
+ collector.add(
239
+ diag(
240
+ 'parse.import_requires_newline',
241
+ {'actual': tok.raw.type.name},
242
+ stream.single_span(tok),
243
+ )
244
+ )
245
+
226
246
  # 注意:不在此消费尾部换行——语句间分隔由 _parse_statement 开头统一处理,
227
247
  # 否则语句 source 会把下一行行首吞入(与 Field 不一致)
228
248
  return EnvImportStmt(
File without changes
@@ -1,4 +1,9 @@
1
- """内置字典约束:has / field。"""
1
+ """内置字典约束:has / field。
2
+
3
+ 与三态可空的交互:``noexist`` 字段(键不出现)对二者均视为**不存在**——
4
+ ``has(noexist字段)`` 不满足、``field(noexist字段, c)`` 视为字段缺失。
5
+ (noexist 在 StdObject 中是非 None 哨兵,渲染时才过滤,须显式排除。)
6
+ """
2
7
 
3
8
  from __future__ import annotations
4
9
 
@@ -19,7 +24,7 @@ from infinity_data.semantic.registry._core import (
19
24
  )
20
25
  from infinity_data.tokenizer.models.raw_tokens import SourceRange
21
26
 
22
- __all__ = ['_check_has', '_check_field']
27
+ __all__ = ['_check_field', '_check_has']
23
28
 
24
29
 
25
30
  def _check_has(
@@ -32,7 +37,10 @@ def _check_has(
32
37
  if not isinstance(val, StdObject):
33
38
  return fail_result('constraint.has_only', {}, source, path)
34
39
  key = _spec_name(args[0])
35
- if val.get(key) is not None:
40
+ f = val.get(key)
41
+ # noexist 字段在 StdObject 中仍以非 None 哨兵存在(渲染时才过滤),
42
+ # 但按三态语义「键不出现」应视为不存在(回归:one(has(a), has(b)) 误判 both)。
43
+ if f is not None and not f.is_noexist:
36
44
  return ok_result()
37
45
  return fail_result('constraint.has_missing', {'key': key}, source, path)
38
46
 
@@ -51,6 +59,7 @@ def _check_field(
51
59
  if spec is None:
52
60
  return fail_result('constraint.field_need', {}, source, path)
53
61
  f = val.get(name)
54
- if f is None:
62
+ # noexist = 键不出现 → 视为字段缺失(与 has 同理)
63
+ if f is None or f.is_noexist:
55
64
  return fail_result('constraint.field_missing', {'field': name}, source, path)
56
65
  return executor(spec, f.value, source, f'{path}.{name}')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: infinity-data
3
- Version: 1.1.0
3
+ Version: 1.2.0
4
4
  Summary: InfinityData:声明式配置语言(.infd/.inft)的 Python 编译器库
5
5
  Author: infinity_system: yin_bailiang
6
6
  License: MIT
@@ -4,6 +4,7 @@ pyproject.toml
4
4
  src/infinity_data/__init__.py
5
5
  src/infinity_data/frontend.py
6
6
  src/infinity_data/pipeline.py
7
+ src/infinity_data/py.typed
7
8
  src/infinity_data.egg-info/PKG-INFO
8
9
  src/infinity_data.egg-info/SOURCES.txt
9
10
  src/infinity_data.egg-info/dependency_links.txt
File without changes
File without changes
File without changes