ethspecify 0.3.5__tar.gz → 0.3.7__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ethspecify
3
- Version: 0.3.5
3
+ Version: 0.3.7
4
4
  Summary: A utility for processing Ethereum specification tags.
5
5
  Home-page: https://github.com/jtraglia/ethspecify
6
6
  Author: Justin Traglia
@@ -184,11 +184,11 @@ def is_fully_withdrawable_validator(validator: Validator, balance: Gwei, epoch:
184
184
 
185
185
  ### `link`
186
186
 
187
- This style displays a GitHub link to the specification item.
187
+ This style displays an ethspec.tools link to the specification item.
188
188
 
189
189
  ```
190
190
  <spec fn="apply_pending_deposit" fork="electra" style="link" hash="83ee9126">
191
- https://github.com/ethereum/consensus-specs/blob/dev/specs/electra/beacon-chain.md#new-apply_pending_deposit
191
+ https://ethspec.tools/#specs/v1.7.0-alpha.1/functions-apply_pending_deposit-electra
192
192
  </spec>
193
193
  ```
194
194
 
@@ -158,11 +158,11 @@ def is_fully_withdrawable_validator(validator: Validator, balance: Gwei, epoch:
158
158
 
159
159
  ### `link`
160
160
 
161
- This style displays a GitHub link to the specification item.
161
+ This style displays an ethspec.tools link to the specification item.
162
162
 
163
163
  ```
164
164
  <spec fn="apply_pending_deposit" fork="electra" style="link" hash="83ee9126">
165
- https://github.com/ethereum/consensus-specs/blob/dev/specs/electra/beacon-chain.md#new-apply_pending_deposit
165
+ https://ethspec.tools/#specs/v1.7.0-alpha.1/functions-apply_pending_deposit-electra
166
166
  </spec>
167
167
  ```
168
168
 
@@ -235,14 +235,6 @@ def diff(a_name, a_content, b_name, b_content):
235
235
  return "\n".join(diff)
236
236
 
237
237
 
238
- @functools.lru_cache()
239
- def get_links(version="nightly"):
240
- url = f"https://raw.githubusercontent.com/jtraglia/ethspecify/main/pyspec/{version}/links.json"
241
- response = requests.get(url)
242
- response.raise_for_status()
243
- return response.json()
244
-
245
-
246
238
  @functools.lru_cache()
247
239
  def get_pyspec(version="nightly"):
248
240
  url = f"https://raw.githubusercontent.com/jtraglia/ethspecify/main/pyspec/{version}/pyspec.json"
@@ -563,23 +555,39 @@ def get_spec_item(attributes, config=None):
563
555
  raise Exception("there is no previous spec for this")
564
556
  return diff(previous_fork, strip_comments(previous_spec), fork, strip_comments(spec))
565
557
  if style == "link":
566
- if "function" in attributes or "fn" in attributes:
567
- if "function" in attributes and "fn" in attributes:
568
- raise Exception(f"cannot contain 'function' and 'fn'")
569
- if "function" in attributes:
570
- function_name = attributes["function"]
571
- else:
572
- function_name = attributes["fn"]
573
- for key, value in get_links(version).items():
574
- if fork in key and key.endswith(function_name):
575
- return value
576
- return "Could not find link"
577
- else:
558
+ link = build_spec_link(attributes, fork, version)
559
+ if link is None:
578
560
  return "Not available for this type of spec"
561
+ return link
579
562
  else:
580
563
  raise Exception("invalid style type")
581
564
 
582
565
 
566
+ def build_spec_link(attributes, fork, version):
567
+ base = f"https://ethspec.tools/#specs/{version}"
568
+ if "function" in attributes or "fn" in attributes:
569
+ if "function" in attributes and "fn" in attributes:
570
+ raise Exception(f"cannot contain 'function' and 'fn'")
571
+ function_name = attributes.get("function", attributes.get("fn"))
572
+ return f"{base}/functions-{function_name}-{fork}"
573
+ if "constant_var" in attributes:
574
+ return f"{base}/constant_vars-{attributes['constant_var']}-{fork}"
575
+ if "preset_var" in attributes:
576
+ return f"{base}/preset_vars-{attributes['preset_var']}-{fork}"
577
+ if "config_var" in attributes:
578
+ return f"{base}/config_vars-{attributes['config_var']}-{fork}"
579
+ if "custom_type" in attributes:
580
+ return f"{base}/custom_types-{attributes['custom_type']}-{fork}"
581
+ if "ssz_object" in attributes or "container" in attributes:
582
+ if "ssz_object" in attributes and "container" in attributes:
583
+ raise Exception(f"cannot contain 'ssz_object' and 'container'")
584
+ object_name = attributes.get("ssz_object", attributes.get("container"))
585
+ return f"{base}/ssz_objects-{object_name}-{fork}"
586
+ if "dataclass" in attributes:
587
+ return f"{base}/dataclasses-{attributes['dataclass']}-{fork}"
588
+ return None
589
+
590
+
583
591
  def extract_attributes(tag):
584
592
  attr_pattern = re.compile(r'(\w+)="(.*?)"')
585
593
  return dict(attr_pattern.findall(tag))
@@ -867,7 +875,7 @@ def load_yaml_entries(yaml_file):
867
875
  return []
868
876
 
869
877
 
870
- def extract_spec_tag_key(spec_content):
878
+ def extract_spec_tag_key(spec_content, alias_groups=None, alias_preference=None):
871
879
  """Extract a unique key from spec tag to identify duplicates."""
872
880
  if not spec_content:
873
881
  return None
@@ -886,7 +894,14 @@ def extract_spec_tag_key(spec_content):
886
894
  for attr in ['fn', 'function', 'constant_var', 'config_var', 'preset_var',
887
895
  'container', 'ssz_object', 'dataclass', 'custom_type']:
888
896
  if attr in attributes:
889
- key_parts.append(f"{attr}:{attributes[attr]}")
897
+ normalized_attr = attr
898
+ if alias_groups:
899
+ for group_key, aliases in alias_groups.items():
900
+ if attr in aliases:
901
+ if alias_preference and group_key in alias_preference:
902
+ normalized_attr = alias_preference[group_key]
903
+ break
904
+ key_parts.append(f"{normalized_attr}:{attributes[attr]}")
890
905
  break
891
906
 
892
907
  if 'fork' in attributes:
@@ -915,18 +930,40 @@ def add_missing_entries_to_yaml(yaml_file, new_entries):
915
930
  # Load existing entries
916
931
  existing_entries = load_yaml_entries(yaml_file)
917
932
 
933
+ # Build alias preferences from the first existing entries in the file
934
+ alias_groups = {
935
+ 'function': ['fn', 'function'],
936
+ 'ssz_object': ['ssz_object', 'container'],
937
+ }
938
+ alias_preference = {}
939
+ for entry in existing_entries:
940
+ if not isinstance(entry, dict) or 'spec' not in entry:
941
+ continue
942
+ spec_content = entry.get('spec', '')
943
+ match = re.search(r'<spec\b([^>]*)>', spec_content)
944
+ if not match:
945
+ continue
946
+ attributes = extract_attributes(match.group(0))
947
+ for group_key, aliases in alias_groups.items():
948
+ if group_key in alias_preference:
949
+ continue
950
+ for alias in aliases:
951
+ if alias in attributes:
952
+ alias_preference[group_key] = alias
953
+ break
954
+
918
955
  # Build a set of existing spec tag keys
919
956
  existing_spec_keys = set()
920
957
  for entry in existing_entries:
921
958
  if isinstance(entry, dict) and 'spec' in entry:
922
- spec_key = extract_spec_tag_key(entry['spec'])
959
+ spec_key = extract_spec_tag_key(entry['spec'], alias_groups, alias_preference)
923
960
  if spec_key:
924
961
  existing_spec_keys.add(spec_key)
925
962
 
926
963
  # Filter out entries that already exist (based on spec tag, not name)
927
964
  entries_to_add = []
928
965
  for entry in new_entries:
929
- spec_key = extract_spec_tag_key(entry.get('spec', ''))
966
+ spec_key = extract_spec_tag_key(entry.get('spec', ''), alias_groups, alias_preference)
930
967
  if spec_key and spec_key not in existing_spec_keys:
931
968
  entries_to_add.append(entry)
932
969
  existing_spec_keys.add(spec_key) # Avoid duplicates within new entries
@@ -1854,6 +1891,10 @@ def add_missing_spec_items_to_yaml_files(project_dir, config, specrefs_files):
1854
1891
  'dataclasses.yml': ('dataclasses', 'dataclass'),
1855
1892
  'types.yml': ('custom_types', 'custom_type'),
1856
1893
  }
1894
+ alias_groups = {
1895
+ 'functions': ['fn', 'function'],
1896
+ 'ssz_objects': ['container', 'ssz_object'],
1897
+ }
1857
1898
 
1858
1899
  for yaml_file in specrefs_files:
1859
1900
  yaml_path = os.path.join(project_dir, yaml_file)
@@ -1863,6 +1904,26 @@ def add_missing_spec_items_to_yaml_files(project_dir, config, specrefs_files):
1863
1904
  continue
1864
1905
 
1865
1906
  category, spec_attr = filename_to_category[yaml_basename]
1907
+
1908
+ # Prefer the first alias used in the file for this category.
1909
+ if category in alias_groups:
1910
+ existing_entries = load_yaml_entries(yaml_path)
1911
+ preferred_attr = None
1912
+ for entry in existing_entries:
1913
+ if not isinstance(entry, dict) or 'spec' not in entry:
1914
+ continue
1915
+ match = re.search(r'<spec\b([^>]*)>', entry.get('spec', ''))
1916
+ if not match:
1917
+ continue
1918
+ attributes = extract_attributes(match.group(0))
1919
+ for alias in alias_groups[category]:
1920
+ if alias in attributes:
1921
+ preferred_attr = alias
1922
+ break
1923
+ if preferred_attr:
1924
+ break
1925
+ if preferred_attr:
1926
+ spec_attr = preferred_attr
1866
1927
  type_exceptions = []
1867
1928
  if isinstance(exceptions, dict) and category in category_exception_keys:
1868
1929
  for key in category_exception_keys[category]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ethspecify
3
- Version: 0.3.5
3
+ Version: 0.3.7
4
4
  Summary: A utility for processing Ethereum specification tags.
5
5
  Home-page: https://github.com/jtraglia/ethspecify
6
6
  Author: Justin Traglia
@@ -184,11 +184,11 @@ def is_fully_withdrawable_validator(validator: Validator, balance: Gwei, epoch:
184
184
 
185
185
  ### `link`
186
186
 
187
- This style displays a GitHub link to the specification item.
187
+ This style displays an ethspec.tools link to the specification item.
188
188
 
189
189
  ```
190
190
  <spec fn="apply_pending_deposit" fork="electra" style="link" hash="83ee9126">
191
- https://github.com/ethereum/consensus-specs/blob/dev/specs/electra/beacon-chain.md#new-apply_pending_deposit
191
+ https://ethspec.tools/#specs/v1.7.0-alpha.1/functions-apply_pending_deposit-electra
192
192
  </spec>
193
193
  ```
194
194
 
@@ -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.5",
11
+ version="0.3.7",
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