ethspecify 0.2.3__py3-none-any.whl → 0.2.4__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.
ethspecify/core.py CHANGED
@@ -745,14 +745,21 @@ def check_source_files(yaml_file, project_root, exceptions=None):
745
745
  return valid_count, total_count, errors
746
746
 
747
747
 
748
- def extract_spec_tags_from_yaml(yaml_file, tag_type):
748
+ def extract_spec_tags_from_yaml(yaml_file, tag_type=None):
749
749
  """
750
- Extract spec tags from a YAML file and return item#fork pairs.
750
+ Extract spec tags from a YAML file and return (tag_types_found, item#fork pairs).
751
+ If tag_type is provided, only extract tags of that type.
751
752
  """
752
753
  if not os.path.exists(yaml_file):
753
- return set()
754
+ return set(), set()
754
755
 
755
756
  pairs = set()
757
+ tag_types_found = set()
758
+
759
+ # Known tag type attributes
760
+ tag_attributes = ['fn', 'function', 'constant_var', 'config_var', 'preset_var',
761
+ 'ssz_object', 'dataclass', 'custom_type']
762
+
756
763
  try:
757
764
  with open(yaml_file, 'r') as f:
758
765
  content_str = f.read()
@@ -768,7 +775,7 @@ def extract_spec_tags_from_yaml(yaml_file, tag_type):
768
775
  content = yaml.load(content_str, Loader=yaml.FullLoader)
769
776
 
770
777
  if not content:
771
- return set()
778
+ return tag_types_found, pairs
772
779
 
773
780
  # Handle both array of objects and single object formats
774
781
  items = content if isinstance(content, list) else [content]
@@ -781,17 +788,38 @@ def extract_spec_tags_from_yaml(yaml_file, tag_type):
781
788
  if not isinstance(spec_content, str):
782
789
  continue
783
790
 
784
- # Find spec tags using regex in the spec field
785
- pattern = rf'<spec\s+{tag_type}="([^"]+)"[^>]*fork="([^"]+)"'
786
- matches = re.findall(pattern, spec_content)
791
+ # Find all spec tags in the content
792
+ spec_tag_pattern = r'<spec\s+([^>]+)>'
793
+ spec_matches = re.findall(spec_tag_pattern, spec_content)
794
+
795
+ for tag_attrs_str in spec_matches:
796
+ # Extract all attributes from the tag
797
+ attrs = dict(re.findall(r'(\w+)="([^"]+)"', tag_attrs_str))
798
+
799
+ # Find which tag type this is
800
+ found_tag_type = None
801
+ item_name = None
802
+
803
+ for attr in tag_attributes:
804
+ if attr in attrs:
805
+ found_tag_type = attr
806
+ item_name = attrs[attr]
807
+ # Normalize function to fn
808
+ if found_tag_type == 'function':
809
+ found_tag_type = 'fn'
810
+ break
811
+
812
+ if found_tag_type and 'fork' in attrs:
813
+ tag_types_found.add(found_tag_type)
787
814
 
788
- for match_item, fork in matches:
789
- pairs.add(f"{match_item}#{fork}")
815
+ # If tag_type filter is specified, only add matching types
816
+ if tag_type is None or tag_type == found_tag_type:
817
+ pairs.add(f"{item_name}#{attrs['fork']}")
790
818
 
791
819
  except (IOError, UnicodeDecodeError, yaml.YAMLError):
792
820
  pass
793
821
 
794
- return pairs
822
+ return tag_types_found, pairs
795
823
 
796
824
 
797
825
  def check_coverage(yaml_file, tag_type, exceptions, preset="mainnet"):
@@ -821,7 +849,7 @@ def check_coverage(yaml_file, tag_type, exceptions, preset="mainnet"):
821
849
  expected_pairs.add(f"{item_name}#{fork}")
822
850
 
823
851
  # Get actual pairs from YAML file
824
- actual_pairs = extract_spec_tags_from_yaml(yaml_file, tag_type)
852
+ _, actual_pairs = extract_spec_tags_from_yaml(yaml_file, tag_type)
825
853
 
826
854
  # Find missing items (excluding exceptions)
827
855
  missing_items = []
@@ -866,14 +894,15 @@ def run_checks(project_dir, config):
866
894
  print("Please add a 'specrefs:' section with 'files:' listing the files to check")
867
895
  return False, {}
868
896
 
869
- # File type mapping for coverage checking
870
- file_type_mapping = {
871
- 'ssz-objects': 'ssz_object',
872
- 'config-variables': 'config_var',
873
- 'preset-variables': 'preset_var',
874
- 'dataclasses': 'dataclass',
875
- 'functions': 'fn',
876
- 'constants': 'constant_var',
897
+ # Map tag types to exception keys (support both singular and plural)
898
+ exception_key_map = {
899
+ 'ssz_object': ['ssz_objects', 'ssz_object'],
900
+ 'config_var': ['configs', 'config_variables', 'config_var'],
901
+ 'preset_var': ['presets', 'preset_variables', 'preset_var'],
902
+ 'dataclass': ['dataclasses', 'dataclass'],
903
+ 'fn': ['functions', 'fn'],
904
+ 'constant_var': ['constants', 'constant_variables', 'constant_var'],
905
+ 'custom_type': ['custom_types', 'custom_type']
877
906
  }
878
907
 
879
908
  # Use explicit file list only
@@ -885,67 +914,91 @@ def run_checks(project_dir, config):
885
914
  overall_success = False
886
915
  continue
887
916
 
888
- # Determine the tag type from filename for coverage checking
889
- tag_type = None
890
- preset = "mainnet" # default preset
891
-
892
- for pattern, file_tag_type in file_type_mapping.items():
893
- if pattern in filename:
894
- tag_type = file_tag_type
895
- # Check for preset indicators
896
- if 'minimal' in filename.lower():
897
- preset = "minimal"
898
- break
917
+ # Detect tag types in the file
918
+ tag_types_found, _ = extract_spec_tags_from_yaml(yaml_path)
899
919
 
900
- # Get the appropriate exceptions for this file type
901
- section_exceptions = []
902
- if tag_type:
903
- # Map tag types to exception keys (support both singular and plural)
904
- exception_key_map = {
905
- 'ssz_object': ['ssz_objects', 'ssz_object'],
906
- 'config_var': ['configs', 'config_variables', 'config_var'],
907
- 'preset_var': ['presets', 'preset_variables', 'preset_var'],
908
- 'dataclass': ['dataclasses', 'dataclass'],
909
- 'fn': ['functions', 'fn'],
910
- 'constant_var': ['constants', 'constant_variables', 'constant_var'],
911
- 'custom_type': ['custom_types', 'custom_type']
920
+ # Check for preset indicators in filename
921
+ preset = "mainnet" # default preset
922
+ if 'minimal' in filename.lower():
923
+ preset = "minimal"
924
+
925
+ # Process each tag type found in the file
926
+ if not tag_types_found:
927
+ # No spec tags found, still check source files
928
+ valid_count, total_count, source_errors = check_source_files(yaml_path, os.path.dirname(project_dir), [])
929
+
930
+ # Store results using filename as section name
931
+ section_name = filename.replace('.yml', '').replace('-', ' ').title()
932
+ if preset != "mainnet":
933
+ section_name += f" ({preset.title()})"
934
+
935
+ results[section_name] = {
936
+ 'source_files': {
937
+ 'valid': valid_count,
938
+ 'total': total_count,
939
+ 'errors': source_errors
940
+ },
941
+ 'coverage': {
942
+ 'found': 0,
943
+ 'expected': 0,
944
+ 'missing': []
945
+ }
912
946
  }
913
947
 
914
- # Try plural first, then singular for backward compatibility
915
- if tag_type in exception_key_map:
916
- for key in exception_key_map[tag_type]:
917
- if key in exceptions:
918
- section_exceptions = exceptions[key]
919
- break
948
+ if source_errors:
949
+ overall_success = False
950
+ else:
951
+ # Process each tag type separately for better reporting
952
+ all_missing_items = []
953
+ total_found = 0
954
+ total_expected = 0
955
+
956
+ for tag_type in tag_types_found:
957
+ # Get the appropriate exceptions for this tag type
958
+ section_exceptions = []
959
+ if tag_type in exception_key_map:
960
+ for key in exception_key_map[tag_type]:
961
+ if key in exceptions:
962
+ section_exceptions = exceptions[key]
963
+ break
920
964
 
921
- # Check source files
922
- valid_count, total_count, source_errors = check_source_files(yaml_path, os.path.dirname(project_dir), section_exceptions)
923
-
924
- # Check coverage if we can determine the type
925
- found_count, expected_count, missing_items = 0, 0, []
926
- if tag_type:
927
- found_count, expected_count, missing_items = check_coverage(yaml_path, tag_type, section_exceptions, preset)
928
-
929
- # Store results using filename as section name
930
- section_name = filename.replace('.yml', '').replace('-', ' ').title()
931
- if preset != "mainnet":
932
- section_name += f" ({preset.title()})"
933
-
934
- results[section_name] = {
935
- 'source_files': {
936
- 'valid': valid_count,
937
- 'total': total_count,
938
- 'errors': source_errors
939
- },
940
- 'coverage': {
941
- 'found': found_count,
942
- 'expected': expected_count,
943
- 'missing': missing_items
965
+ # Check coverage for this specific tag type
966
+ found_count, expected_count, missing_items = check_coverage(yaml_path, tag_type, section_exceptions, preset)
967
+ total_found += found_count
968
+ total_expected += expected_count
969
+ all_missing_items.extend(missing_items)
970
+
971
+ # Check source files (only once per file, not per tag type)
972
+ # Use the union of all exceptions for source file checking
973
+ all_exceptions = []
974
+ for tag_type in tag_types_found:
975
+ if tag_type in exception_key_map:
976
+ for key in exception_key_map[tag_type]:
977
+ if key in exceptions:
978
+ all_exceptions.extend(exceptions[key])
979
+
980
+ valid_count, total_count, source_errors = check_source_files(yaml_path, os.path.dirname(project_dir), all_exceptions)
981
+
982
+ # Store results using filename as section name
983
+ section_name = filename.replace('.yml', '').replace('-', ' ').title()
984
+ if preset != "mainnet":
985
+ section_name += f" ({preset.title()})"
986
+
987
+ results[section_name] = {
988
+ 'source_files': {
989
+ 'valid': valid_count,
990
+ 'total': total_count,
991
+ 'errors': source_errors
992
+ },
993
+ 'coverage': {
994
+ 'found': total_found,
995
+ 'expected': total_expected,
996
+ 'missing': all_missing_items
997
+ }
944
998
  }
945
- }
946
999
 
947
- # Update overall success
948
- if source_errors or missing_items:
949
- overall_success = False
1000
+ # Update overall success
1001
+ if source_errors or all_missing_items:
1002
+ overall_success = False
950
1003
 
951
1004
  return overall_success, results
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ethspecify
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: A utility for processing Ethereum specification tags.
5
5
  Home-page: https://github.com/jtraglia/ethspecify
6
6
  Author: Justin Traglia
@@ -0,0 +1,9 @@
1
+ ethspecify/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ ethspecify/cli.py,sha256=SZ47-lgfeDHmzXCE-rx8ydM66N9NfNAA2GDxoC4DE7E,7641
3
+ ethspecify/core.py,sha256=kOu8avxvFnDt8uRuIK4bbl0zjIciXk_8jvlE1cu23J0,37884
4
+ ethspecify-0.2.4.dist-info/licenses/LICENSE,sha256=Awxsr73mm9YMBVhBYnzeI7bNdRd-bH6RDtO5ItG0DaM,1071
5
+ ethspecify-0.2.4.dist-info/METADATA,sha256=DzopppX63lH3ykj6H1nq5mNbRV1mA1XkhAX8bzJhkVw,9212
6
+ ethspecify-0.2.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
+ ethspecify-0.2.4.dist-info/entry_points.txt,sha256=09viGkCg9J3h0c9BFRN-BKaJUEaIc4JyULNgBP5EL_g,51
8
+ ethspecify-0.2.4.dist-info/top_level.txt,sha256=0klaMvlVyOkXW09fwZTijJpdybITEp2c9zQKV5v30VM,11
9
+ ethspecify-0.2.4.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- ethspecify/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- ethspecify/cli.py,sha256=SZ47-lgfeDHmzXCE-rx8ydM66N9NfNAA2GDxoC4DE7E,7641
3
- ethspecify/core.py,sha256=bQ1D7zdR_xDx_OuyPrFBNKBNxXpH3bjn2L4-pqHhgJo,35530
4
- ethspecify-0.2.3.dist-info/licenses/LICENSE,sha256=Awxsr73mm9YMBVhBYnzeI7bNdRd-bH6RDtO5ItG0DaM,1071
5
- ethspecify-0.2.3.dist-info/METADATA,sha256=77_CCIaxJ5Cf6Cg_FlIDXhS_djSf-D5nAujQ9DJthys,9212
6
- ethspecify-0.2.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
- ethspecify-0.2.3.dist-info/entry_points.txt,sha256=09viGkCg9J3h0c9BFRN-BKaJUEaIc4JyULNgBP5EL_g,51
8
- ethspecify-0.2.3.dist-info/top_level.txt,sha256=0klaMvlVyOkXW09fwZTijJpdybITEp2c9zQKV5v30VM,11
9
- ethspecify-0.2.3.dist-info/RECORD,,