plain-parser 0.1.3.dev8__py3-none-any.whl → 0.1.4.dev9__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.
@@ -709,19 +709,31 @@ def parse_plain_file(
709
709
  )
710
710
 
711
711
 
712
+ @dataclass
713
+ class RequiredModule:
714
+ """A required module as parsed by the requires walk; validated once the top module is complete."""
715
+
716
+ parse_result: PlainFileParseResult
717
+ # Definitions exported to this module by the modules it requires.
718
+ ancestor_exported_definitions: list[mistletoe.block_token.token]
719
+ code_variables: dict
720
+ # Definitions this module exports to the modules that require it.
721
+ exported_definitions: list[mistletoe.block_token.token]
722
+ # Marshalled plain source tree, set once the module is validated.
723
+ tree: dict | None = None
724
+
725
+
712
726
  def process_required_modules(
713
727
  required_modules: list[str],
714
728
  template_dirs: list[str],
715
729
  all_required_modules: list[str],
716
730
  modules_trace: list[str],
717
- chain: list[tuple[str, dict]],
718
- module_exports: dict[str, list[mistletoe.block_token.token]],
731
+ required: dict[str, RequiredModule],
719
732
  ) -> list[mistletoe.block_token.token]:
720
- """Parse and fully validate every required module, deepest first.
733
+ """Parse every required module, deepest first, without validating it.
721
734
 
722
- Appends ``(module name, marshalled plain source tree)`` to ``chain`` for each module not already in it,
723
- records each module's exported definitions in ``module_exports``, and returns the exported definitions
724
- of the directly required modules.
735
+ Records each module in ``required`` the first time it is reached (deepest ancestors first) and returns
736
+ the exported definitions of the directly required modules.
725
737
  """
726
738
  exported_definitions = list[mistletoe.block_token.token]()
727
739
  for module_name in required_modules:
@@ -730,7 +742,7 @@ def process_required_modules(
730
742
 
731
743
  if len(all_required_modules) > 0 and module_name == all_required_modules[-1]:
732
744
  # Already processed as an earlier entry; its exports are still visible to this module.
733
- exported_definitions.extend(module_exports[module_name])
745
+ exported_definitions.extend(required[module_name].exported_definitions)
734
746
  continue
735
747
 
736
748
  code_variables: dict = {}
@@ -753,8 +765,7 @@ def process_required_modules(
753
765
  template_dirs,
754
766
  all_required_modules,
755
767
  modules_trace + [module_name],
756
- chain,
757
- module_exports,
768
+ required,
758
769
  )
759
770
 
760
771
  own_exported_definitions = list[mistletoe.block_token.token]()
@@ -770,20 +781,32 @@ def process_required_modules(
770
781
  exported_concept, plain_file_parse_result.plain_source, renderer
771
782
  )
772
783
  )
773
- module_exports[module_name] = own_exported_definitions
774
- exported_definitions.extend(own_exported_definitions)
775
-
776
- marshalled_plain_source = validate_and_marshall_module(
777
- plain_file_parse_result, module_name, ancestor_exported_definitions, code_variables, template_dirs
784
+ required[module_name] = RequiredModule(
785
+ plain_file_parse_result, ancestor_exported_definitions, code_variables, own_exported_definitions
778
786
  )
779
- if module_name not in (chain_module_name for chain_module_name, _ in chain):
780
- chain.append((module_name, marshalled_plain_source))
787
+ exported_definitions.extend(own_exported_definitions)
781
788
 
782
789
  all_required_modules.append(module_name)
783
790
 
784
791
  return exported_definitions
785
792
 
786
793
 
794
+ def validate_required_modules(
795
+ required_modules: list[str], required: dict[str, RequiredModule], template_dirs: list[str]
796
+ ) -> None:
797
+ """Validate recorded required modules top-down, in listed order, each module once."""
798
+ for module_name in required_modules:
799
+ module = required[module_name]
800
+ if module.tree is not None:
801
+ continue
802
+
803
+ validate_module_structure(module.parse_result, module_name)
804
+ module.tree = validate_and_build_module_tree(
805
+ module.parse_result, module_name, module.ancestor_exported_definitions, module.code_variables, template_dirs
806
+ )
807
+ validate_required_modules(module.parse_result.required_modules, required, template_dirs)
808
+
809
+
787
810
  def process_exported_definitions(plain_source: dict, exported_definitions: list[mistletoe.block_token.token]) -> None:
788
811
  if len(exported_definitions) == 0:
789
812
  return
@@ -806,14 +829,8 @@ def process_exported_definitions(plain_source: dict, exported_definitions: list[
806
829
  plain_source[plain_spec.DEFINITIONS].children.append(exported_definition)
807
830
 
808
831
 
809
- def validate_and_marshall_module(
810
- plain_file_parse_result: PlainFileParseResult,
811
- module_name: str,
812
- exported_definitions: list[mistletoe.block_token.token],
813
- code_variables: dict,
814
- template_dirs: list[str],
815
- ) -> dict:
816
- """Every check a module must pass after parsing, and its marshalled plain source tree."""
832
+ def validate_module_structure(plain_file_parse_result: PlainFileParseResult, module_name: str) -> None:
833
+ """Required concepts defined, functional specs present and non-empty, implementation reqs present."""
817
834
  if len(plain_file_parse_result.required_concepts) > 0:
818
835
  missing_required_concepts_msg = "Missing required concepts: "
819
836
  missing_required_concepts_msg += ", ".join(plain_file_parse_result.required_concepts)
@@ -841,6 +858,16 @@ def validate_and_marshall_module(
841
858
  has_requires=bool(plain_file_parse_result.required_modules),
842
859
  )
843
860
 
861
+
862
+ def validate_and_build_module_tree(
863
+ plain_file_parse_result: PlainFileParseResult,
864
+ module_name: str,
865
+ exported_definitions: list[mistletoe.block_token.token],
866
+ code_variables: dict,
867
+ template_dirs: list[str],
868
+ ) -> dict:
869
+ """Merge exported definitions, validate acceptance tests, linked resources and concepts, and return the
870
+ marshalled plain source tree."""
844
871
  process_exported_definitions(plain_file_parse_result.plain_source, exported_definitions)
845
872
 
846
873
  process_acceptance_tests(plain_file_parse_result.plain_source)
@@ -890,20 +917,27 @@ def _parse_module(
890
917
  modules_trace=[],
891
918
  )
892
919
 
893
- chain: list[tuple[str, dict]] = []
920
+ # Check the top module's structure, walk its requires, finish the top module's checks, then validate
921
+ # every required module top-down.
922
+ validate_module_structure(plain_file_parse_result, module_name)
923
+
924
+ required: dict[str, RequiredModule] = {}
894
925
  exported_definitions = process_required_modules(
895
926
  plain_file_parse_result.required_modules,
896
927
  template_dirs=template_dirs,
897
928
  all_required_modules=[],
898
929
  modules_trace=[],
899
- chain=chain,
900
- module_exports={},
930
+ required=required,
901
931
  )
902
932
 
903
- marshalled_plain_source = validate_and_marshall_module(
933
+ marshalled_plain_source = validate_and_build_module_tree(
904
934
  plain_file_parse_result, module_name, exported_definitions, code_variables, template_dirs
905
935
  )
906
936
 
937
+ validate_required_modules(plain_file_parse_result.required_modules, required, template_dirs)
938
+ # The walk records modules deepest first, which is the chain order.
939
+ chain = [(chain_module_name, module.tree) for chain_module_name, module in required.items()]
940
+
907
941
  return module_name, marshalled_plain_source, plain_file_parse_result.required_modules, chain
908
942
 
909
943
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: plain-parser
3
- Version: 0.1.3.dev8
3
+ Version: 0.1.4.dev9
4
4
  Summary: Parser for ***plain specification files
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -5,10 +5,10 @@ plain_parser/exceptions.py,sha256=WcHK5g9K6bsE-ZZBKWl0lZtiMTQ6fif8-zdEx9qjmRw,79
5
5
  plain_parser/graph.py,sha256=xZfgzAXoL_hMfqre0Vj4kdvCC8vzfxZgvYptEK9W0Ho,6843
6
6
  plain_parser/liquid_nodes.py,sha256=CYmujdPJMK9hLjfFPmnSoKL3Ps4sb-2OOhH-fZUssis,3917
7
7
  plain_parser/loaders.py,sha256=o-I7u1NL8hZdTWztqwO7zw072aGxXTBBYSAFDBRG4q0,5136
8
- plain_parser/plain_file.py,sha256=7QCIh2PlGZoltilLgNirwjm0fdcvDJIMlk9NfR8ViKI,40431
8
+ plain_parser/plain_file.py,sha256=NlcuSbVHS4dbwWEOETv5xY9-mg5y7yZEAvHI6P5maL8,42064
9
9
  plain_parser/plain_spec.py,sha256=Z79Vi8bdRiOiM53QyWS8OLNSlGPrQObSZx11Eh8i8Mk,15308
10
- plain_parser-0.1.3.dev8.dist-info/METADATA,sha256=NI7l_hkUjP8fFa1qcvg-qICxofIM-EAq3yENX6xOeKQ,2647
11
- plain_parser-0.1.3.dev8.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
12
- plain_parser-0.1.3.dev8.dist-info/entry_points.txt,sha256=pA31GGUyYrmZSpH1CuSzhjrv8pX5ac5HI5hFop1B4eI,55
13
- plain_parser-0.1.3.dev8.dist-info/licenses/LICENSE,sha256=QClWKncxgRjNUVOW8Axi7zK9HtsMdJEtUSMA4LEe8fo,1071
14
- plain_parser-0.1.3.dev8.dist-info/RECORD,,
10
+ plain_parser-0.1.4.dev9.dist-info/METADATA,sha256=zTBbXnaNNkU7xZwFrONlUU9iOCOT0a9gnXGOBBIkzRQ,2647
11
+ plain_parser-0.1.4.dev9.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
12
+ plain_parser-0.1.4.dev9.dist-info/entry_points.txt,sha256=pA31GGUyYrmZSpH1CuSzhjrv8pX5ac5HI5hFop1B4eI,55
13
+ plain_parser-0.1.4.dev9.dist-info/licenses/LICENSE,sha256=QClWKncxgRjNUVOW8Axi7zK9HtsMdJEtUSMA4LEe8fo,1071
14
+ plain_parser-0.1.4.dev9.dist-info/RECORD,,