ethspecify 0.3.8__tar.gz → 0.3.10__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,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ethspecify
3
- Version: 0.3.8
3
+ Version: 0.3.10
4
4
  Summary: A utility for processing Ethereum specification tags.
5
- Home-page: https://github.com/jtraglia/ethspecify
5
+ Home-page: https://github.com/ethereum/ethspecify
6
6
  Author: Justin Traglia
7
7
  Author-email: jtraglia@pm.me
8
8
  Classifier: Programming Language :: Python :: 3
@@ -278,12 +278,20 @@ def is_fully_withdrawable_validator(validator: Validator, balance: Gwei, epoch:
278
278
 
279
279
  ### `link`
280
280
 
281
- This style displays an ethspec.tools link to the specification
282
- item.
281
+ This style displays a link to the specification item's source on
282
+ GitHub. For a tagged `version`, the link uses the tag as the ref:
283
283
 
284
284
  ```
285
- <spec fn="apply_pending_deposit" fork="electra" style="link" hash="83ee9126">
286
- https://ethspec.tools/#specs/v1.7.0-alpha.1/functions-apply_pending_deposit-electra
285
+ <spec ssz_object="BeaconState" fork="gloas" version="v1.7.0-alpha.11" style="link">
286
+ https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.11/specs/gloas/beacon-chain.md?plain=1#L411-L468
287
+ </spec>
288
+ ```
289
+
290
+ For `nightly`, the link uses a commit permalink instead of the tag:
291
+
292
+ ```
293
+ <spec fn="apply_pending_deposit" fork="electra" style="link">
294
+ https://github.com/ethereum/consensus-specs/blob/99cc40f9317a15ea185690cee6095297fc571dda/specs/electra/beacon-chain.md?plain=1#L960-L975
287
295
  </spec>
288
296
  ```
289
297
 
@@ -252,12 +252,20 @@ def is_fully_withdrawable_validator(validator: Validator, balance: Gwei, epoch:
252
252
 
253
253
  ### `link`
254
254
 
255
- This style displays an ethspec.tools link to the specification
256
- item.
255
+ This style displays a link to the specification item's source on
256
+ GitHub. For a tagged `version`, the link uses the tag as the ref:
257
257
 
258
258
  ```
259
- <spec fn="apply_pending_deposit" fork="electra" style="link" hash="83ee9126">
260
- https://ethspec.tools/#specs/v1.7.0-alpha.1/functions-apply_pending_deposit-electra
259
+ <spec ssz_object="BeaconState" fork="gloas" version="v1.7.0-alpha.11" style="link">
260
+ https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.11/specs/gloas/beacon-chain.md?plain=1#L411-L468
261
+ </spec>
262
+ ```
263
+
264
+ For `nightly`, the link uses a commit permalink instead of the tag:
265
+
266
+ ```
267
+ <spec fn="apply_pending_deposit" fork="electra" style="link">
268
+ https://github.com/ethereum/consensus-specs/blob/99cc40f9317a15ea185690cee6095297fc571dda/specs/electra/beacon-chain.md?plain=1#L960-L975
261
269
  </spec>
262
270
  ```
263
271
 
@@ -237,12 +237,30 @@ def diff(a_name, a_content, b_name, b_content):
237
237
 
238
238
  @functools.lru_cache()
239
239
  def get_pyspec(version="nightly"):
240
- url = f"https://raw.githubusercontent.com/jtraglia/ethspecify/main/pyspec/{version}/pyspec.json"
240
+ url = f"https://raw.githubusercontent.com/ethereum/ethspecify/main/pyspec/{version}/pyspec.json"
241
241
  response = requests.get(url)
242
242
  response.raise_for_status()
243
243
  return response.json()
244
244
 
245
245
 
246
+ @functools.lru_cache()
247
+ def get_links(version="nightly"):
248
+ """
249
+ Fetch the source location map (links.json) for a given version.
250
+
251
+ Returns a dict of the form {"commit": <sha>, "items": {name: {fork: {...}}}}
252
+ or None if no links.json is available for this version (e.g. older tags that
253
+ predate link support).
254
+ """
255
+ url = f"https://raw.githubusercontent.com/ethereum/ethspecify/main/pyspec/{version}/links.json"
256
+ try:
257
+ response = requests.get(url)
258
+ response.raise_for_status()
259
+ return response.json()
260
+ except (requests.RequestException, ValueError):
261
+ return None
262
+
263
+
246
264
  def get_previous_forks(fork, version="nightly"):
247
265
  pyspec = get_pyspec(version)
248
266
  config_vars = pyspec["mainnet"][fork]["config_vars"]
@@ -563,31 +581,117 @@ def get_spec_item(attributes, config=None):
563
581
  raise Exception("invalid style type")
564
582
 
565
583
 
566
- def build_spec_link(attributes, fork, version):
567
- base = f"https://ethspec.tools/#specs/{version}"
584
+ GITHUB_SPEC_REPO = "https://github.com/ethereum/consensus-specs"
585
+
586
+
587
+ def _get_link_item_name(attributes):
588
+ """
589
+ Return the spec item name referenced by a tag, or None if the tag does not
590
+ reference a linkable item.
591
+ """
592
+ if "function" in attributes and "fn" in attributes:
593
+ raise Exception("cannot contain 'function' and 'fn'")
568
594
  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}"
595
+ return attributes.get("function", attributes.get("fn"))
573
596
  if "constant_var" in attributes:
574
- return f"{base}/constant_vars-{attributes['constant_var']}-{fork}"
597
+ return attributes["constant_var"]
575
598
  if "preset_var" in attributes:
576
- return f"{base}/preset_vars-{attributes['preset_var']}-{fork}"
599
+ return attributes["preset_var"]
577
600
  if "config_var" in attributes:
578
- return f"{base}/config_vars-{attributes['config_var']}-{fork}"
601
+ return attributes["config_var"]
579
602
  if "custom_type" in attributes:
580
- return f"{base}/custom_types-{attributes['custom_type']}-{fork}"
603
+ return attributes["custom_type"]
604
+ if "ssz_object" in attributes and "container" in attributes:
605
+ raise Exception("cannot contain 'ssz_object' and 'container'")
581
606
  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}"
607
+ return attributes.get("ssz_object", attributes.get("container"))
586
608
  if "dataclass" in attributes:
587
- return f"{base}/dataclasses-{attributes['dataclass']}-{fork}"
609
+ return attributes["dataclass"]
588
610
  return None
589
611
 
590
612
 
613
+ def build_spec_link(attributes, fork, version):
614
+ """
615
+ Build a GitHub link to the source of the referenced spec item, or None if it
616
+ can't be resolved (unknown item, or no links.json for this version).
617
+ Tagged versions link to the tag; nightly links to a commit permalink.
618
+ """
619
+ item_name = _get_link_item_name(attributes)
620
+ if item_name is None:
621
+ return None
622
+
623
+ links = get_links(version)
624
+ if not links:
625
+ return None
626
+
627
+ item_forks = links.get("items", {}).get(item_name)
628
+ if not item_forks:
629
+ return None
630
+
631
+ location = _resolve_location(item_forks, fork, version)
632
+ if location is None:
633
+ return None
634
+
635
+ ref = version if version != "nightly" else links.get("commit")
636
+ if not ref:
637
+ return None
638
+
639
+ start = location["start"]
640
+ end = location["end"]
641
+
642
+ # For function line selections, narrow the anchor to the requested lines.
643
+ if ("function" in attributes or "fn" in attributes) and "lines" in attributes:
644
+ sub = _apply_line_subrange(start, end, attributes["lines"])
645
+ if sub is not None:
646
+ start, end = sub
647
+
648
+ anchor = f"L{start}" if start == end else f"L{start}-L{end}"
649
+ return f"{GITHUB_SPEC_REPO}/blob/{ref}/{location['file']}?plain=1#{anchor}"
650
+
651
+
652
+ def _resolve_location(item_forks, fork, version):
653
+ """
654
+ Find the source location for an item at the given fork. If the item is not
655
+ (re)defined in that fork, walk back through previous forks to the most recent
656
+ one that defines it (matching how the spec inherits unchanged items).
657
+ """
658
+ if fork in item_forks:
659
+ return item_forks[fork]
660
+ try:
661
+ previous_forks = get_previous_forks(fork, version)
662
+ except Exception:
663
+ return None
664
+ for prev in previous_forks:
665
+ if prev in item_forks:
666
+ return item_forks[prev]
667
+ return None
668
+
669
+
670
+ def _apply_line_subrange(start, end, lines_attr):
671
+ """
672
+ Narrow a [start, end] line range using a tag's `lines` attribute (1-indexed,
673
+ relative to the item). Returns (new_start, new_end) or None if invalid.
674
+ """
675
+ try:
676
+ parts = lines_attr.split("-")
677
+ if len(parts) == 1:
678
+ s = e = int(parts[0])
679
+ elif len(parts) == 2:
680
+ s = int(parts[0])
681
+ e = int(parts[1])
682
+ else:
683
+ return None
684
+ except ValueError:
685
+ return None
686
+
687
+ total = end - start + 1
688
+ s = max(1, min(s, total))
689
+ e = max(1, min(e, total))
690
+ if s > e:
691
+ return None
692
+ return start + s - 1, start + e - 1
693
+
694
+
591
695
  def extract_attributes(tag):
592
696
  attr_pattern = re.compile(r'(\w+)="(.*?)"')
593
697
  return dict(attr_pattern.findall(tag))
@@ -1656,8 +1760,8 @@ def run_checks(project_dir, config):
1656
1760
  source_root = os.path.join(project_dir, search_root_rel) if not os.path.isabs(search_root_rel) else search_root_rel
1657
1761
  source_root = os.path.abspath(source_root)
1658
1762
  else:
1659
- # Default behavior: project directory itself
1660
- source_root = project_dir
1763
+ # Default behavior: if we're in a specrefs directory, search in the parent directory
1764
+ source_root = os.path.dirname(project_dir) if os.path.basename(project_dir) == 'specrefs' else project_dir
1661
1765
 
1662
1766
  valid_count, total_count, source_errors = check_source_files(yaml_path, source_root, [])
1663
1767
 
@@ -1717,8 +1821,8 @@ def run_checks(project_dir, config):
1717
1821
  source_root = os.path.join(project_dir, search_root_rel) if not os.path.isabs(search_root_rel) else search_root_rel
1718
1822
  source_root = os.path.abspath(source_root)
1719
1823
  else:
1720
- # Default behavior: project directory itself
1721
- source_root = project_dir
1824
+ # Default behavior: if we're in a specrefs directory, search in the parent directory
1825
+ source_root = os.path.dirname(project_dir) if os.path.basename(project_dir) == 'specrefs' else project_dir
1722
1826
 
1723
1827
  valid_count, total_count, source_errors = check_source_files(yaml_path, source_root, all_exceptions)
1724
1828
 
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ethspecify
3
- Version: 0.3.8
3
+ Version: 0.3.10
4
4
  Summary: A utility for processing Ethereum specification tags.
5
- Home-page: https://github.com/jtraglia/ethspecify
5
+ Home-page: https://github.com/ethereum/ethspecify
6
6
  Author: Justin Traglia
7
7
  Author-email: jtraglia@pm.me
8
8
  Classifier: Programming Language :: Python :: 3
@@ -278,12 +278,20 @@ def is_fully_withdrawable_validator(validator: Validator, balance: Gwei, epoch:
278
278
 
279
279
  ### `link`
280
280
 
281
- This style displays an ethspec.tools link to the specification
282
- item.
281
+ This style displays a link to the specification item's source on
282
+ GitHub. For a tagged `version`, the link uses the tag as the ref:
283
283
 
284
284
  ```
285
- <spec fn="apply_pending_deposit" fork="electra" style="link" hash="83ee9126">
286
- https://ethspec.tools/#specs/v1.7.0-alpha.1/functions-apply_pending_deposit-electra
285
+ <spec ssz_object="BeaconState" fork="gloas" version="v1.7.0-alpha.11" style="link">
286
+ https://github.com/ethereum/consensus-specs/blob/v1.7.0-alpha.11/specs/gloas/beacon-chain.md?plain=1#L411-L468
287
+ </spec>
288
+ ```
289
+
290
+ For `nightly`, the link uses a commit permalink instead of the tag:
291
+
292
+ ```
293
+ <spec fn="apply_pending_deposit" fork="electra" style="link">
294
+ https://github.com/ethereum/consensus-specs/blob/99cc40f9317a15ea185690cee6095297fc571dda/specs/electra/beacon-chain.md?plain=1#L960-L975
287
295
  </spec>
288
296
  ```
289
297
 
@@ -8,13 +8,13 @@ long_description = (this_directory / "README.md").read_text(encoding="utf-8")
8
8
 
9
9
  setup(
10
10
  name="ethspecify",
11
- version="0.3.8",
11
+ version="0.3.10",
12
12
  description="A utility for processing Ethereum specification tags.",
13
13
  long_description=long_description,
14
14
  long_description_content_type="text/markdown",
15
15
  author="Justin Traglia",
16
16
  author_email="jtraglia@pm.me",
17
- url="https://github.com/jtraglia/ethspecify",
17
+ url="https://github.com/ethereum/ethspecify",
18
18
  packages=find_packages(),
19
19
  entry_points={
20
20
  "console_scripts": [
File without changes
File without changes