ethspecify 0.3.1__tar.gz → 0.3.2__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.
- {ethspecify-0.3.1 → ethspecify-0.3.2}/PKG-INFO +1 -1
- {ethspecify-0.3.1 → ethspecify-0.3.2}/ethspecify/cli.py +24 -7
- {ethspecify-0.3.1 → ethspecify-0.3.2}/ethspecify/core.py +364 -1
- {ethspecify-0.3.1 → ethspecify-0.3.2}/ethspecify.egg-info/PKG-INFO +1 -1
- {ethspecify-0.3.1 → ethspecify-0.3.2}/setup.py +1 -1
- {ethspecify-0.3.1 → ethspecify-0.3.2}/LICENSE +0 -0
- {ethspecify-0.3.1 → ethspecify-0.3.2}/README.md +0 -0
- {ethspecify-0.3.1 → ethspecify-0.3.2}/ethspecify/__init__.py +0 -0
- {ethspecify-0.3.1 → ethspecify-0.3.2}/ethspecify.egg-info/SOURCES.txt +0 -0
- {ethspecify-0.3.1 → ethspecify-0.3.2}/ethspecify.egg-info/dependency_links.txt +0 -0
- {ethspecify-0.3.1 → ethspecify-0.3.2}/ethspecify.egg-info/entry_points.txt +0 -0
- {ethspecify-0.3.1 → ethspecify-0.3.2}/ethspecify.egg-info/requires.txt +0 -0
- {ethspecify-0.3.1 → ethspecify-0.3.2}/ethspecify.egg-info/top_level.txt +0 -0
- {ethspecify-0.3.1 → ethspecify-0.3.2}/setup.cfg +0 -0
|
@@ -3,7 +3,7 @@ import json
|
|
|
3
3
|
import os
|
|
4
4
|
import sys
|
|
5
5
|
|
|
6
|
-
from .core import grep, replace_spec_tags, get_pyspec, get_latest_fork, get_spec_item_history, load_config, run_checks, sort_specref_yaml, generate_specref_files
|
|
6
|
+
from .core import grep, replace_spec_tags, get_pyspec, get_latest_fork, get_spec_item_history, load_config, run_checks, sort_specref_yaml, generate_specref_files, get_yaml_filename_for_spec_attr, get_spec_attr_and_name, add_missing_entries_to_yaml
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def process(args):
|
|
@@ -16,20 +16,37 @@ def process(args):
|
|
|
16
16
|
# Load config once from the project directory
|
|
17
17
|
config = load_config(project_dir)
|
|
18
18
|
|
|
19
|
-
#
|
|
20
|
-
for f in grep(project_dir, r"<spec\b.*?>", args.exclude):
|
|
21
|
-
print(f"Processing file: {f}")
|
|
22
|
-
replace_spec_tags(f, config)
|
|
23
|
-
|
|
24
|
-
# Sort specref YAML files if they exist in config
|
|
19
|
+
# Check if auto_add_missing_entries and auto_standardize_names are enabled
|
|
25
20
|
specrefs_config = config.get('specrefs', {})
|
|
26
21
|
if isinstance(specrefs_config, dict):
|
|
22
|
+
auto_add_missing = specrefs_config.get('auto_add_missing_entries', False)
|
|
23
|
+
auto_standardize_names = specrefs_config.get('auto_standardize_names', False)
|
|
27
24
|
specrefs_files = specrefs_config.get('files', [])
|
|
28
25
|
elif isinstance(specrefs_config, list):
|
|
26
|
+
auto_add_missing = False
|
|
27
|
+
auto_standardize_names = False
|
|
29
28
|
specrefs_files = specrefs_config
|
|
30
29
|
else:
|
|
30
|
+
auto_add_missing = False
|
|
31
|
+
auto_standardize_names = False
|
|
31
32
|
specrefs_files = []
|
|
32
33
|
|
|
34
|
+
# Process spec tags in files
|
|
35
|
+
for f in grep(project_dir, r"<spec\b.*?>", args.exclude):
|
|
36
|
+
print(f"Processing file: {f}")
|
|
37
|
+
replace_spec_tags(f, config)
|
|
38
|
+
|
|
39
|
+
# Add missing spec items to YAML files if enabled
|
|
40
|
+
if auto_add_missing:
|
|
41
|
+
from .core import add_missing_spec_items_to_yaml_files
|
|
42
|
+
add_missing_spec_items_to_yaml_files(project_dir, config, specrefs_files)
|
|
43
|
+
|
|
44
|
+
# Update entry names to <spec_item>#<fork> format if enabled
|
|
45
|
+
if auto_standardize_names:
|
|
46
|
+
from .core import update_entry_names_in_yaml_files
|
|
47
|
+
update_entry_names_in_yaml_files(project_dir, specrefs_files)
|
|
48
|
+
|
|
49
|
+
# Sort specref YAML files if they exist in config
|
|
33
50
|
for yaml_file in specrefs_files:
|
|
34
51
|
yaml_path = os.path.join(project_dir, yaml_file)
|
|
35
52
|
if os.path.exists(yaml_path):
|
|
@@ -89,7 +89,8 @@ def validate_exception_items(exceptions, version):
|
|
|
89
89
|
break
|
|
90
90
|
|
|
91
91
|
if not item_found:
|
|
92
|
-
|
|
92
|
+
fork_suffix = f"#{fork}" if fork else ""
|
|
93
|
+
errors.append(f"invalid key: {exception_key}.{item_name}{fork_suffix}")
|
|
93
94
|
|
|
94
95
|
if errors:
|
|
95
96
|
error_msg = "Invalid exception items in configuration:\n" + "\n".join(f" - {e}" for e in errors)
|
|
@@ -724,6 +725,9 @@ def replace_spec_tags(file_path, config=None):
|
|
|
724
725
|
re.DOTALL
|
|
725
726
|
)
|
|
726
727
|
|
|
728
|
+
# Collect processed spec items for potential YAML updates
|
|
729
|
+
processed_items = []
|
|
730
|
+
|
|
727
731
|
def rebuild_opening_tag(attributes, hash_value):
|
|
728
732
|
# Rebuild a fresh opening tag from attributes, overriding any existing hash.
|
|
729
733
|
new_opening = "<spec"
|
|
@@ -762,6 +766,17 @@ def replace_spec_tags(file_path, config=None):
|
|
|
762
766
|
spec = get_spec(attributes, preset, fork, version)
|
|
763
767
|
hash_value = hashlib.sha256(spec.encode('utf-8')).hexdigest()[:8]
|
|
764
768
|
|
|
769
|
+
# Collect this item for potential YAML updates
|
|
770
|
+
processed_items.append({
|
|
771
|
+
'attributes': attributes,
|
|
772
|
+
'preset': preset,
|
|
773
|
+
'fork': fork,
|
|
774
|
+
'style': style,
|
|
775
|
+
'version': version,
|
|
776
|
+
'spec': spec,
|
|
777
|
+
'hash': hash_value
|
|
778
|
+
})
|
|
779
|
+
|
|
765
780
|
if style == "hash":
|
|
766
781
|
# Rebuild a fresh self-closing tag.
|
|
767
782
|
updated_tag = rebuild_self_closing_tag(attributes, hash_value)
|
|
@@ -786,6 +801,151 @@ def replace_spec_tags(file_path, config=None):
|
|
|
786
801
|
with open(file_path, 'w') as file:
|
|
787
802
|
file.write(updated_content)
|
|
788
803
|
|
|
804
|
+
# Return processed items for potential YAML updates
|
|
805
|
+
return processed_items
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
def get_yaml_filename_for_spec_attr(spec_attr):
|
|
809
|
+
"""Map spec attribute to YAML filename."""
|
|
810
|
+
attr_to_file = {
|
|
811
|
+
'fn': 'functions.yml',
|
|
812
|
+
'function': 'functions.yml',
|
|
813
|
+
'constant_var': 'constants.yml',
|
|
814
|
+
'config_var': 'configs.yml',
|
|
815
|
+
'preset_var': 'presets.yml',
|
|
816
|
+
'container': 'containers.yml',
|
|
817
|
+
'ssz_object': 'containers.yml',
|
|
818
|
+
'dataclass': 'dataclasses.yml',
|
|
819
|
+
'custom_type': 'types.yml',
|
|
820
|
+
}
|
|
821
|
+
return attr_to_file.get(spec_attr)
|
|
822
|
+
|
|
823
|
+
|
|
824
|
+
def get_spec_attr_and_name(attributes):
|
|
825
|
+
"""Extract the spec attribute and item name from tag attributes."""
|
|
826
|
+
spec_attrs = ['fn', 'function', 'constant_var', 'config_var', 'preset_var',
|
|
827
|
+
'container', 'ssz_object', 'dataclass', 'custom_type']
|
|
828
|
+
for attr in spec_attrs:
|
|
829
|
+
if attr in attributes:
|
|
830
|
+
return attr, attributes[attr]
|
|
831
|
+
return None, None
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
def load_yaml_entries(yaml_file):
|
|
835
|
+
"""Load existing entries from a YAML file."""
|
|
836
|
+
if not os.path.exists(yaml_file):
|
|
837
|
+
return []
|
|
838
|
+
|
|
839
|
+
try:
|
|
840
|
+
with open(yaml_file, 'r') as f:
|
|
841
|
+
content_str = f.read()
|
|
842
|
+
|
|
843
|
+
# Try to fix common YAML issues with unquoted search strings containing colons
|
|
844
|
+
content_str = re.sub(r'(\s+search:\s+)([^"\n]+:)(\s*$)', r'\1"\2"\3', content_str, flags=re.MULTILINE)
|
|
845
|
+
|
|
846
|
+
try:
|
|
847
|
+
content = yaml.safe_load(content_str)
|
|
848
|
+
except yaml.YAMLError:
|
|
849
|
+
content = yaml.load(content_str, Loader=yaml.FullLoader)
|
|
850
|
+
|
|
851
|
+
if isinstance(content, list):
|
|
852
|
+
return content
|
|
853
|
+
return []
|
|
854
|
+
except (yaml.YAMLError, IOError):
|
|
855
|
+
return []
|
|
856
|
+
|
|
857
|
+
|
|
858
|
+
def extract_spec_tag_key(spec_content):
|
|
859
|
+
"""Extract a unique key from spec tag to identify duplicates."""
|
|
860
|
+
if not spec_content:
|
|
861
|
+
return None
|
|
862
|
+
|
|
863
|
+
# Extract the opening spec tag
|
|
864
|
+
match = re.search(r'<spec\b([^>]*)>', spec_content)
|
|
865
|
+
if not match:
|
|
866
|
+
return None
|
|
867
|
+
|
|
868
|
+
# Extract attributes from the tag
|
|
869
|
+
attributes = extract_attributes(match.group(0))
|
|
870
|
+
|
|
871
|
+
# Build a key from the spec attribute and fork
|
|
872
|
+
# e.g., "constant_var:DOMAIN_PTC_ATTESTER:fork:gloas"
|
|
873
|
+
key_parts = []
|
|
874
|
+
for attr in ['fn', 'function', 'constant_var', 'config_var', 'preset_var',
|
|
875
|
+
'container', 'ssz_object', 'dataclass', 'custom_type']:
|
|
876
|
+
if attr in attributes:
|
|
877
|
+
key_parts.append(f"{attr}:{attributes[attr]}")
|
|
878
|
+
break
|
|
879
|
+
|
|
880
|
+
if 'fork' in attributes:
|
|
881
|
+
key_parts.append(f"fork:{attributes['fork']}")
|
|
882
|
+
|
|
883
|
+
return ':'.join(key_parts) if key_parts else None
|
|
884
|
+
|
|
885
|
+
|
|
886
|
+
def add_missing_entries_to_yaml(yaml_file, new_entries):
|
|
887
|
+
"""Add new entries to a YAML file and sort it."""
|
|
888
|
+
if not new_entries:
|
|
889
|
+
return
|
|
890
|
+
|
|
891
|
+
# Load existing entries
|
|
892
|
+
existing_entries = load_yaml_entries(yaml_file)
|
|
893
|
+
|
|
894
|
+
# Build a set of existing spec tag keys
|
|
895
|
+
existing_spec_keys = set()
|
|
896
|
+
for entry in existing_entries:
|
|
897
|
+
if isinstance(entry, dict) and 'spec' in entry:
|
|
898
|
+
spec_key = extract_spec_tag_key(entry['spec'])
|
|
899
|
+
if spec_key:
|
|
900
|
+
existing_spec_keys.add(spec_key)
|
|
901
|
+
|
|
902
|
+
# Filter out entries that already exist (based on spec tag, not name)
|
|
903
|
+
entries_to_add = []
|
|
904
|
+
for entry in new_entries:
|
|
905
|
+
spec_key = extract_spec_tag_key(entry.get('spec', ''))
|
|
906
|
+
if spec_key and spec_key not in existing_spec_keys:
|
|
907
|
+
entries_to_add.append(entry)
|
|
908
|
+
existing_spec_keys.add(spec_key) # Avoid duplicates within new entries
|
|
909
|
+
|
|
910
|
+
if not entries_to_add:
|
|
911
|
+
return
|
|
912
|
+
|
|
913
|
+
# Combine and write
|
|
914
|
+
all_entries = existing_entries + entries_to_add
|
|
915
|
+
|
|
916
|
+
# Ensure directory exists
|
|
917
|
+
os.makedirs(os.path.dirname(yaml_file) if os.path.dirname(yaml_file) else '.', exist_ok=True)
|
|
918
|
+
|
|
919
|
+
# Write combined entries using the same format as generate_specref_files
|
|
920
|
+
with open(yaml_file, 'w') as f:
|
|
921
|
+
for i, entry in enumerate(all_entries):
|
|
922
|
+
if i > 0:
|
|
923
|
+
f.write('\n')
|
|
924
|
+
f.write(f'- name: {entry["name"]}\n')
|
|
925
|
+
if 'sources' in entry:
|
|
926
|
+
if isinstance(entry['sources'], list) and len(entry['sources']) == 0:
|
|
927
|
+
f.write(' sources: []\n')
|
|
928
|
+
else:
|
|
929
|
+
f.write(' sources:\n')
|
|
930
|
+
for source in entry['sources']:
|
|
931
|
+
if isinstance(source, dict):
|
|
932
|
+
f.write(f' - file: {source.get("file", "")}\n')
|
|
933
|
+
if 'search' in source:
|
|
934
|
+
f.write(f' search: {source["search"]}\n')
|
|
935
|
+
if 'regex' in source:
|
|
936
|
+
f.write(f' regex: {source["regex"]}\n')
|
|
937
|
+
else:
|
|
938
|
+
f.write(f' - {source}\n')
|
|
939
|
+
if 'spec' in entry:
|
|
940
|
+
f.write(' spec: |\n')
|
|
941
|
+
for line in entry['spec'].split('\n'):
|
|
942
|
+
f.write(f' {line}\n')
|
|
943
|
+
|
|
944
|
+
# Sort the file
|
|
945
|
+
sort_specref_yaml(yaml_file)
|
|
946
|
+
|
|
947
|
+
print(f"Added {len(entries_to_add)} new entries to {yaml_file}")
|
|
948
|
+
|
|
789
949
|
|
|
790
950
|
def check_source_files(yaml_file, project_root, exceptions=None):
|
|
791
951
|
"""
|
|
@@ -1520,6 +1680,209 @@ def run_checks(project_dir, config):
|
|
|
1520
1680
|
return overall_success, results
|
|
1521
1681
|
|
|
1522
1682
|
|
|
1683
|
+
def update_entry_names_in_yaml_files(project_dir, specrefs_files):
|
|
1684
|
+
"""
|
|
1685
|
+
Update all entry names to use the format <spec_item>#<fork>.
|
|
1686
|
+
"""
|
|
1687
|
+
for yaml_file in specrefs_files:
|
|
1688
|
+
yaml_path = os.path.join(project_dir, yaml_file)
|
|
1689
|
+
|
|
1690
|
+
if not os.path.exists(yaml_path):
|
|
1691
|
+
continue
|
|
1692
|
+
|
|
1693
|
+
# Load existing entries
|
|
1694
|
+
existing_entries = load_yaml_entries(yaml_path)
|
|
1695
|
+
if not existing_entries:
|
|
1696
|
+
continue
|
|
1697
|
+
|
|
1698
|
+
updated = False
|
|
1699
|
+
for entry in existing_entries:
|
|
1700
|
+
if not isinstance(entry, dict) or 'spec' not in entry:
|
|
1701
|
+
continue
|
|
1702
|
+
|
|
1703
|
+
# Extract spec tag attributes
|
|
1704
|
+
spec_content = entry['spec']
|
|
1705
|
+
match = re.search(r'<spec\b([^>]*)>', spec_content)
|
|
1706
|
+
if not match:
|
|
1707
|
+
continue
|
|
1708
|
+
|
|
1709
|
+
attributes = extract_attributes(match.group(0))
|
|
1710
|
+
|
|
1711
|
+
# Get the spec item name and fork
|
|
1712
|
+
spec_attr, item_name = get_spec_attr_and_name(attributes)
|
|
1713
|
+
fork = attributes.get('fork')
|
|
1714
|
+
|
|
1715
|
+
if item_name and fork:
|
|
1716
|
+
# Build the expected name
|
|
1717
|
+
expected_name = f'{item_name}#{fork}'
|
|
1718
|
+
|
|
1719
|
+
# Update if different
|
|
1720
|
+
if entry.get('name') != expected_name:
|
|
1721
|
+
entry['name'] = expected_name
|
|
1722
|
+
updated = True
|
|
1723
|
+
|
|
1724
|
+
# Write back if updated
|
|
1725
|
+
if updated:
|
|
1726
|
+
with open(yaml_path, 'w') as f:
|
|
1727
|
+
for i, entry in enumerate(existing_entries):
|
|
1728
|
+
if i > 0:
|
|
1729
|
+
f.write('\n')
|
|
1730
|
+
f.write(f'- name: {entry["name"]}\n')
|
|
1731
|
+
if 'sources' in entry:
|
|
1732
|
+
if isinstance(entry['sources'], list) and len(entry['sources']) == 0:
|
|
1733
|
+
f.write(' sources: []\n')
|
|
1734
|
+
else:
|
|
1735
|
+
f.write(' sources:\n')
|
|
1736
|
+
for source in entry['sources']:
|
|
1737
|
+
if isinstance(source, dict):
|
|
1738
|
+
f.write(f' - file: {source.get("file", "")}\n')
|
|
1739
|
+
if 'search' in source:
|
|
1740
|
+
f.write(f' search: {source["search"]}\n')
|
|
1741
|
+
if 'regex' in source:
|
|
1742
|
+
f.write(f' regex: {source["regex"]}\n')
|
|
1743
|
+
else:
|
|
1744
|
+
f.write(f' - {source}\n')
|
|
1745
|
+
if 'spec' in entry:
|
|
1746
|
+
f.write(' spec: |\n')
|
|
1747
|
+
for line in entry['spec'].split('\n'):
|
|
1748
|
+
f.write(f' {line}\n')
|
|
1749
|
+
|
|
1750
|
+
# Sort the file
|
|
1751
|
+
sort_specref_yaml(yaml_path)
|
|
1752
|
+
print(f"Updated entry names in {yaml_file}")
|
|
1753
|
+
|
|
1754
|
+
|
|
1755
|
+
def add_missing_spec_items_to_yaml_files(project_dir, config, specrefs_files):
|
|
1756
|
+
"""
|
|
1757
|
+
Add missing spec items to existing YAML files.
|
|
1758
|
+
Ensures all spec items from the specification exist in YAML files with sources: []
|
|
1759
|
+
"""
|
|
1760
|
+
version = config.get('version', 'nightly')
|
|
1761
|
+
preset = 'mainnet' # Could make this configurable
|
|
1762
|
+
|
|
1763
|
+
# Get all spec items
|
|
1764
|
+
pyspec = get_pyspec(version)
|
|
1765
|
+
if preset not in pyspec:
|
|
1766
|
+
print(f"Error: Preset '{preset}' not found")
|
|
1767
|
+
return
|
|
1768
|
+
|
|
1769
|
+
# Get all forks in chronological order, excluding EIP forks
|
|
1770
|
+
all_forks = sorted(
|
|
1771
|
+
[fork for fork in pyspec[preset].keys() if not fork.startswith("eip")],
|
|
1772
|
+
key=lambda x: (x != "phase0", x)
|
|
1773
|
+
)
|
|
1774
|
+
|
|
1775
|
+
# Map YAML filenames to category keys and spec attribute names
|
|
1776
|
+
filename_to_category = {
|
|
1777
|
+
'constants.yml': ('constant_vars', 'constant_var'),
|
|
1778
|
+
'configs.yml': ('config_vars', 'config_var'),
|
|
1779
|
+
'presets.yml': ('preset_vars', 'preset_var'),
|
|
1780
|
+
'functions.yml': ('functions', 'fn'),
|
|
1781
|
+
'containers.yml': ('ssz_objects', 'container'),
|
|
1782
|
+
'dataclasses.yml': ('dataclasses', 'dataclass'),
|
|
1783
|
+
'types.yml': ('custom_types', 'custom_type'),
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
for yaml_file in specrefs_files:
|
|
1787
|
+
yaml_path = os.path.join(project_dir, yaml_file)
|
|
1788
|
+
yaml_basename = os.path.basename(yaml_file)
|
|
1789
|
+
|
|
1790
|
+
if yaml_basename not in filename_to_category:
|
|
1791
|
+
continue
|
|
1792
|
+
|
|
1793
|
+
category, spec_attr = filename_to_category[yaml_basename]
|
|
1794
|
+
|
|
1795
|
+
# Collect all items in this category organized by name and fork
|
|
1796
|
+
items_by_name = {}
|
|
1797
|
+
for fork in all_forks:
|
|
1798
|
+
if fork not in pyspec[preset]:
|
|
1799
|
+
continue
|
|
1800
|
+
fork_data = pyspec[preset][fork]
|
|
1801
|
+
|
|
1802
|
+
if category not in fork_data:
|
|
1803
|
+
continue
|
|
1804
|
+
|
|
1805
|
+
for item_name, item_data in fork_data[category].items():
|
|
1806
|
+
if item_name not in items_by_name:
|
|
1807
|
+
items_by_name[item_name] = []
|
|
1808
|
+
items_by_name[item_name].append((fork, item_data))
|
|
1809
|
+
|
|
1810
|
+
# Build entries for missing items
|
|
1811
|
+
new_entries = []
|
|
1812
|
+
for item_name in sorted(items_by_name.keys()):
|
|
1813
|
+
forks_data = items_by_name[item_name]
|
|
1814
|
+
|
|
1815
|
+
# Find all unique versions of this item (where content differs)
|
|
1816
|
+
versions = [] # List of (fork, item_data, spec_content)
|
|
1817
|
+
prev_content = None
|
|
1818
|
+
|
|
1819
|
+
for fork, item_data in forks_data:
|
|
1820
|
+
# Build the spec content based on category
|
|
1821
|
+
if category == 'functions':
|
|
1822
|
+
spec_content = item_data
|
|
1823
|
+
elif category in ['constant_vars', 'config_vars', 'preset_vars']:
|
|
1824
|
+
# item_data is a list: [type, value, ...]
|
|
1825
|
+
if isinstance(item_data, (list, tuple)) and len(item_data) >= 2:
|
|
1826
|
+
type_info = item_data[0]
|
|
1827
|
+
value = item_data[1]
|
|
1828
|
+
if type_info:
|
|
1829
|
+
spec_content = f"{item_name}: {type_info} = {value}"
|
|
1830
|
+
else:
|
|
1831
|
+
spec_content = f"{item_name} = {value}"
|
|
1832
|
+
else:
|
|
1833
|
+
spec_content = str(item_data)
|
|
1834
|
+
elif category == 'ssz_objects':
|
|
1835
|
+
spec_content = item_data
|
|
1836
|
+
elif category == 'dataclasses':
|
|
1837
|
+
spec_content = item_data.replace("@dataclass\n", "")
|
|
1838
|
+
elif category == 'custom_types':
|
|
1839
|
+
# custom_types are simple type aliases: TypeName = SomeType
|
|
1840
|
+
spec_content = f"{item_name} = {item_data}"
|
|
1841
|
+
else:
|
|
1842
|
+
spec_content = str(item_data)
|
|
1843
|
+
|
|
1844
|
+
# Only add this version if it's different from the previous one
|
|
1845
|
+
if prev_content is None or spec_content != prev_content:
|
|
1846
|
+
versions.append((fork, item_data, spec_content))
|
|
1847
|
+
prev_content = spec_content
|
|
1848
|
+
|
|
1849
|
+
# Create entries based on number of unique versions
|
|
1850
|
+
use_fork_suffix = len(versions) > 1
|
|
1851
|
+
|
|
1852
|
+
for idx, (fork, item_data, spec_content) in enumerate(versions):
|
|
1853
|
+
# Calculate hash of current version
|
|
1854
|
+
hash_value = hashlib.sha256(spec_content.encode('utf-8')).hexdigest()[:8]
|
|
1855
|
+
|
|
1856
|
+
# For multiple versions after the first, use diff style
|
|
1857
|
+
if use_fork_suffix and idx > 0:
|
|
1858
|
+
# Get previous version for diff
|
|
1859
|
+
prev_fork, _, prev_spec_content = versions[idx - 1]
|
|
1860
|
+
|
|
1861
|
+
# Generate diff
|
|
1862
|
+
diff_content = diff(prev_fork, strip_comments(prev_spec_content), fork, strip_comments(spec_content))
|
|
1863
|
+
|
|
1864
|
+
# Build spec tag with style="diff"
|
|
1865
|
+
spec_tag = f'<spec {spec_attr}="{item_name}" fork="{fork}" style="diff" hash="{hash_value}">'
|
|
1866
|
+
content = diff_content
|
|
1867
|
+
else:
|
|
1868
|
+
# Build spec tag without style="diff"
|
|
1869
|
+
spec_tag = f'<spec {spec_attr}="{item_name}" fork="{fork}" hash="{hash_value}">'
|
|
1870
|
+
content = spec_content
|
|
1871
|
+
|
|
1872
|
+
# Create entry
|
|
1873
|
+
entry_name = f'{item_name}#{fork}' if use_fork_suffix else item_name
|
|
1874
|
+
entry = {
|
|
1875
|
+
'name': entry_name,
|
|
1876
|
+
'sources': [],
|
|
1877
|
+
'spec': f'{spec_tag}\n{content}\n</spec>'
|
|
1878
|
+
}
|
|
1879
|
+
new_entries.append(entry)
|
|
1880
|
+
|
|
1881
|
+
# Add missing entries to the YAML file
|
|
1882
|
+
if new_entries:
|
|
1883
|
+
add_missing_entries_to_yaml(yaml_path, new_entries)
|
|
1884
|
+
|
|
1885
|
+
|
|
1523
1886
|
def generate_specref_files(output_dir, version="nightly", preset="mainnet"):
|
|
1524
1887
|
"""
|
|
1525
1888
|
Generate specref YAML files without sources for manual mapping.
|
|
@@ -8,7 +8,7 @@ long_description = (this_directory / "README.md").read_text(encoding="utf-8")
|
|
|
8
8
|
|
|
9
9
|
setup(
|
|
10
10
|
name="ethspecify",
|
|
11
|
-
version="0.3.
|
|
11
|
+
version="0.3.2",
|
|
12
12
|
description="A utility for processing Ethereum specification tags.",
|
|
13
13
|
long_description=long_description,
|
|
14
14
|
long_description_content_type="text/markdown",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|