2020-01-25 01:26:10 +01:00
from setuptools import setup , find_packages , Command
from setuptools . command . build_py import build_py
from distutils import dir_util
from distutils . util import convert_path
2021-05-18 12:12:01 +02:00
from pathlib import Path
2020-01-25 01:26:10 +01:00
import os
2021-04-19 22:41:45 +09:00
import string
2023-06-26 18:01:56 +08:00
from typing import Dict , List , Sequence , Optional , Tuple
2021-04-20 14:55:46 -07:00
import ast
2021-09-24 16:33:14 +02:00
import subprocess
import sys
2022-02-25 01:22:02 +08:00
import copy
from collections import OrderedDict
2022-09-27 17:30:35 +08:00
import json
2023-06-20 18:02:39 +03:00
from functools import reduce
2022-02-25 01:22:02 +08:00
2023-06-26 18:01:56 +08:00
from pysetup . constants import (
# code names
PHASE0 ,
# misc
ETH2_SPEC_COMMENT_PREFIX ,
)
from pysetup . spec_builders import spec_builders
from pysetup . typing import (
BuildTarget ,
ProtocolDefinition ,
SpecObject ,
VariableDefinition ,
)
from pysetup . helpers import (
combine_spec_objects ,
dependency_order_class_objects ,
objects_to_spec ,
parse_config_vars ,
)
from pysetup . md_doc_paths import get_md_doc_paths
2020-01-25 01:26:10 +01:00
2021-04-20 14:55:46 -07:00
# NOTE: have to programmatically include third-party dependencies in `setup.py`.
2021-09-24 16:33:14 +02:00
def installPackage ( package : str ) :
subprocess . check_call ( [ sys . executable , ' -m ' , ' pip ' , ' install ' , package ] )
2022-09-28 12:22:53 +08:00
RUAMEL_YAML_VERSION = " ruamel.yaml==0.17.21 "
2021-05-18 12:12:01 +02:00
try :
import ruamel . yaml
except ImportError :
2021-09-24 16:33:14 +02:00
installPackage ( RUAMEL_YAML_VERSION )
2021-05-18 12:12:01 +02:00
from ruamel . yaml import YAML
2021-04-20 14:55:46 -07:00
MARKO_VERSION = " marko==1.0.2 "
try :
import marko
except ImportError :
2021-09-24 16:33:14 +02:00
installPackage ( MARKO_VERSION )
2021-04-20 14:55:46 -07:00
from marko . block import Heading , FencedCode , LinkRefDef , BlankLine
from marko . inline import CodeSpan
from marko . ext . gfm import gfm
2021-09-24 12:45:37 +02:00
from marko . ext . gfm . elements import Table
2021-04-20 14:55:46 -07:00
2020-01-25 01:26:10 +01:00
2021-04-20 14:55:46 -07:00
def _get_name_from_heading ( heading : Heading ) - > Optional [ str ] :
last_child = heading . children [ - 1 ]
if isinstance ( last_child , CodeSpan ) :
return last_child . children
return None
2020-01-25 01:26:10 +01:00
2021-04-20 14:55:46 -07:00
def _get_source_from_code_block ( block : FencedCode ) - > str :
return block . children [ 0 ] . children . strip ( )
2020-01-25 01:26:10 +01:00
2021-04-20 14:55:46 -07:00
def _get_function_name_from_source ( source : str ) - > str :
fn = ast . parse ( source ) . body [ 0 ]
return fn . name
2021-05-12 02:40:23 +02:00
def _get_self_type_from_source ( source : str ) - > Optional [ str ] :
fn = ast . parse ( source ) . body [ 0 ]
args = fn . args . args
if len ( args ) == 0 :
return None
if args [ 0 ] . arg != ' self ' :
return None
if args [ 0 ] . annotation is None :
return None
return args [ 0 ] . annotation . id
2022-09-27 17:30:35 +08:00
def _get_class_info_from_source ( source : str ) - > Tuple [ str , Optional [ str ] ] :
2021-04-20 14:55:46 -07:00
class_def = ast . parse ( source ) . body [ 0 ]
base = class_def . bases [ 0 ]
if isinstance ( base , ast . Name ) :
parent_class = base . id
else :
# NOTE: SSZ definition derives from earlier phase...
# e.g. `phase0.SignedBeaconBlock`
# TODO: check for consistency with other phases
parent_class = None
return class_def . name , parent_class
def _is_constant_id ( name : str ) - > bool :
if name [ 0 ] not in string . ascii_uppercase + ' _ ' :
return False
return all ( map ( lambda c : c in string . ascii_uppercase + ' _ ' + string . digits , name [ 1 : ] ) )
2022-09-27 17:30:35 +08:00
def _load_kzg_trusted_setups ( preset_name ) :
"""
[ TODO ] it ' s not the final mainnet trusted setup.
We will update it after the KZG ceremony .
"""
file_path = str ( Path ( __file__ ) . parent ) + ' /presets/ ' + preset_name + ' /trusted_setups/testing_trusted_setups.json '
with open ( file_path , ' r ' ) as f :
json_data = json . load ( f )
trusted_setup_G1 = json_data [ ' setup_G1 ' ]
trusted_setup_G2 = json_data [ ' setup_G2 ' ]
trusted_setup_G1_lagrange = json_data [ ' setup_G1_lagrange ' ]
roots_of_unity = json_data [ ' roots_of_unity ' ]
return trusted_setup_G1 , trusted_setup_G2 , trusted_setup_G1_lagrange , roots_of_unity
2023-06-26 18:01:56 +08:00
2022-09-27 18:13:55 +08:00
ALL_KZG_SETUPS = {
' minimal ' : _load_kzg_trusted_setups ( ' minimal ' ) ,
' mainnet ' : _load_kzg_trusted_setups ( ' mainnet ' )
}
2022-09-27 17:30:35 +08:00
2021-04-20 14:55:46 -07:00
def _get_eth2_spec_comment ( child : LinkRefDef ) - > Optional [ str ] :
_ , _ , title = child . _parse_info
if not ( title [ 0 ] == " ( " and title [ len ( title ) - 1 ] == " ) " ) :
return None
title = title [ 1 : len ( title ) - 1 ]
if not title . startswith ( ETH2_SPEC_COMMENT_PREFIX ) :
return None
return title [ len ( ETH2_SPEC_COMMENT_PREFIX ) : ] . strip ( )
2023-06-26 18:01:56 +08:00
def _parse_value ( name : str , typed_value : str , type_hint : Optional [ str ] = None ) - > VariableDefinition :
2021-05-18 12:12:01 +02:00
comment = None
if name == " BLS12_381_Q " :
2021-05-19 17:15:34 +02:00
comment = " noqa: E501 "
2021-05-18 12:12:01 +02:00
typed_value = typed_value . strip ( )
if ' ( ' not in typed_value :
2022-09-28 12:22:53 +08:00
return VariableDefinition ( type_name = None , value = typed_value , comment = comment , type_hint = type_hint )
2021-05-18 12:12:01 +02:00
i = typed_value . index ( ' ( ' )
type_name = typed_value [ : i ]
2022-09-28 12:22:53 +08:00
return VariableDefinition ( type_name = type_name , value = typed_value [ i + 1 : - 1 ] , comment = comment , type_hint = type_hint )
2021-05-18 12:12:01 +02:00
2022-09-27 18:13:55 +08:00
def _update_constant_vars_with_kzg_setups ( constant_vars , preset_name ) :
comment = " noqa: E501 "
kzg_setups = ALL_KZG_SETUPS [ preset_name ]
constant_vars [ ' KZG_SETUP_G1 ' ] = VariableDefinition ( constant_vars [ ' KZG_SETUP_G1 ' ] . value , str ( kzg_setups [ 0 ] ) , comment , None )
constant_vars [ ' KZG_SETUP_G2 ' ] = VariableDefinition ( constant_vars [ ' KZG_SETUP_G2 ' ] . value , str ( kzg_setups [ 1 ] ) , comment , None )
constant_vars [ ' KZG_SETUP_LAGRANGE ' ] = VariableDefinition ( constant_vars [ ' KZG_SETUP_LAGRANGE ' ] . value , str ( kzg_setups [ 2 ] ) , comment , None )
constant_vars [ ' ROOTS_OF_UNITY ' ] = VariableDefinition ( constant_vars [ ' ROOTS_OF_UNITY ' ] . value , str ( kzg_setups [ 3 ] ) , comment , None )
2022-09-27 17:30:35 +08:00
def get_spec ( file_name : Path , preset : Dict [ str , str ] , config : Dict [ str , str ] , preset_name = str ) - > SpecObject :
2020-01-25 01:26:10 +01:00
functions : Dict [ str , str ] = { }
2021-05-12 02:40:23 +02:00
protocols : Dict [ str , ProtocolDefinition ] = { }
2021-05-18 12:12:01 +02:00
constant_vars : Dict [ str , VariableDefinition ] = { }
preset_vars : Dict [ str , VariableDefinition ] = { }
config_vars : Dict [ str , VariableDefinition ] = { }
2020-12-09 17:35:22 +08:00
ssz_dep_constants : Dict [ str , str ] = { }
2020-01-25 01:26:10 +01:00
ssz_objects : Dict [ str , str ] = { }
2020-07-03 10:48:57 +08:00
dataclasses : Dict [ str , str ] = { }
2020-01-25 01:26:10 +01:00
custom_types : Dict [ str , str ] = { }
2021-04-20 14:55:46 -07:00
with open ( file_name ) as source_file :
document = gfm . parse ( source_file . read ( ) )
current_name = None
should_skip = False
for child in document . children :
if isinstance ( child , BlankLine ) :
continue
if should_skip :
should_skip = False
continue
if isinstance ( child , Heading ) :
current_name = _get_name_from_heading ( child )
elif isinstance ( child , FencedCode ) :
if child . lang != " python " :
continue
source = _get_source_from_code_block ( child )
if source . startswith ( " def " ) :
current_name = _get_function_name_from_source ( source )
2021-05-12 02:40:23 +02:00
self_type_name = _get_self_type_from_source ( source )
function_def = " \n " . join ( line . rstrip ( ) for line in source . splitlines ( ) )
if self_type_name is None :
functions [ current_name ] = function_def
else :
if self_type_name not in protocols :
protocols [ self_type_name ] = ProtocolDefinition ( functions = { } )
protocols [ self_type_name ] . functions [ current_name ] = function_def
2021-04-20 14:55:46 -07:00
elif source . startswith ( " @dataclass " ) :
dataclasses [ current_name ] = " \n " . join ( line . rstrip ( ) for line in source . splitlines ( ) )
elif source . startswith ( " class " ) :
class_name , parent_class = _get_class_info_from_source ( source )
# check consistency with spec
assert class_name == current_name
if parent_class :
assert parent_class == " Container "
# NOTE: trim whitespace from spec
ssz_objects [ current_name ] = " \n " . join ( line . rstrip ( ) for line in source . splitlines ( ) )
else :
2021-10-05 18:01:12 +03:00
raise Exception ( " unrecognized python code element: " + source )
2021-04-20 14:55:46 -07:00
elif isinstance ( child , Table ) :
for row in child . children :
cells = row . children
if len ( cells ) > = 2 :
name_cell = cells [ 0 ]
name = name_cell . children [ 0 ] . children
2021-05-18 12:12:01 +02:00
2021-04-20 14:55:46 -07:00
value_cell = cells [ 1 ]
value = value_cell . children [ 0 ] . children
if isinstance ( value , list ) :
# marko parses `**X**` as a list containing a X
value = value [ 0 ] . children
2021-05-18 12:12:01 +02:00
if not _is_constant_id ( name ) :
# Check for short type declarations
2022-11-03 17:01:32 +02:00
if value . startswith ( ( " uint " , " Bytes " , " ByteList " , " Union " , " Vector " , " List " , " ByteVector " ) ) :
2021-05-18 12:12:01 +02:00
custom_types [ name ] = value
continue
if value . startswith ( " get_generalized_index " ) :
ssz_dep_constants [ name ] = value
continue
value_def = _parse_value ( name , value )
if name in preset :
2022-09-28 12:22:53 +08:00
preset_vars [ name ] = VariableDefinition ( value_def . type_name , preset [ name ] , value_def . comment , None )
2021-05-18 12:12:01 +02:00
elif name in config :
2022-09-28 12:22:53 +08:00
config_vars [ name ] = VariableDefinition ( value_def . type_name , config [ name ] , value_def . comment , None )
2021-05-18 12:12:01 +02:00
else :
2023-05-15 17:16:41 +08:00
if name in ( ' ENDIANNESS ' , ' KZG_ENDIANNESS ' ) :
2022-09-28 12:22:53 +08:00
# Deal with mypy Literal typing check
value_def = _parse_value ( name , value , type_hint = ' Final ' )
2021-05-18 12:12:01 +02:00
constant_vars [ name ] = value_def
2021-04-20 14:55:46 -07:00
elif isinstance ( child , LinkRefDef ) :
comment = _get_eth2_spec_comment ( child )
2021-04-23 08:03:49 -07:00
if comment == " skip " :
should_skip = True
2021-05-06 10:23:50 -07:00
2022-09-27 17:30:35 +08:00
# Load KZG trusted setup from files
if any ( ' KZG_SETUP ' in name for name in constant_vars ) :
2022-09-27 18:13:55 +08:00
_update_constant_vars_with_kzg_setups ( constant_vars , preset_name )
2022-09-27 17:30:35 +08:00
2023-06-08 18:56:02 +03:00
if any ( ' CURDLEPROOFS_CRS ' in name for name in constant_vars ) :
# TODO: Use actual CRS derived from a fixed string like 'nankokita_no_kakurenbo'
crs_len = int ( preset_vars [ ' WHISK_VALIDATORS_PER_SHUFFLE ' ] . value ) + int ( preset_vars [ ' CURDLEPROOFS_N_BLINDERS ' ] . value ) + 3
constant_vars [ ' CURDLEPROOFS_CRS_G1 ' ] = VariableDefinition ( constant_vars [ ' CURDLEPROOFS_CRS_G1 ' ] . value , str ( ALL_KZG_SETUPS [ ' mainnet ' ] [ 0 ] [ 0 : crs_len ] ) , " noqa: E501 " , None )
2023-06-22 14:09:08 +03:00
constant_vars [ ' CURDLEPROOFS_CRS ' ] = VariableDefinition (
None ,
2023-07-24 18:41:38 +02:00
" curdleproofs.CurdleproofsCrs.from_random_points(WHISK_VALIDATORS_PER_SHUFFLE, CURDLEPROOFS_N_BLINDERS, [G1Point.from_compressed_bytes_unchecked(p) for p in CURDLEPROOFS_CRS_G1]) " ,
2023-06-22 14:09:08 +03:00
" noqa: E501 " , None
)
constant_vars [ ' BLS_G1_GENERATOR ' ] = VariableDefinition (
constant_vars [ ' BLS_G1_GENERATOR ' ] . value ,
" ' 0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb ' " ,
" noqa: E501 " , None
)
2023-06-08 18:56:02 +03:00
2020-12-09 17:35:22 +08:00
return SpecObject (
functions = functions ,
2021-05-12 02:40:23 +02:00
protocols = protocols ,
2020-12-09 17:35:22 +08:00
custom_types = custom_types ,
2021-05-18 12:12:01 +02:00
constant_vars = constant_vars ,
preset_vars = preset_vars ,
config_vars = config_vars ,
2020-12-09 17:35:22 +08:00
ssz_dep_constants = ssz_dep_constants ,
ssz_objects = ssz_objects ,
dataclasses = dataclasses ,
)
2020-01-25 01:26:10 +01:00
2021-05-18 12:12:01 +02:00
def load_preset ( preset_files : Sequence [ Path ] ) - > Dict [ str , str ] :
"""
Loads the a directory of preset files , merges the result into one preset .
"""
preset = { }
for fork_file in preset_files :
yaml = YAML ( typ = ' base ' )
fork_preset : dict = yaml . load ( fork_file )
if fork_preset is None : # for empty YAML files
continue
if not set ( fork_preset . keys ( ) ) . isdisjoint ( preset . keys ( ) ) :
duplicates = set ( fork_preset . keys ( ) ) . intersection ( set ( preset . keys ( ) ) )
raise Exception ( f " duplicate config var(s) in preset files: { ' , ' . join ( duplicates ) } " )
preset . update ( fork_preset )
assert preset != { }
return parse_config_vars ( preset )
def load_config ( config_path : Path ) - > Dict [ str , str ] :
"""
Loads the given configuration file .
"""
yaml = YAML ( typ = ' base ' )
config_data = yaml . load ( config_path )
return parse_config_vars ( config_data )
2023-06-26 18:01:56 +08:00
def build_spec ( fork : str ,
preset_name : str ,
source_files : Sequence [ Path ] ,
preset_files : Sequence [ Path ] ,
config_file : Path ) - > str :
2021-05-18 12:12:01 +02:00
preset = load_preset ( preset_files )
config = load_config ( config_file )
2022-09-27 17:30:35 +08:00
all_specs = [ get_spec ( spec , preset , config , preset_name ) for spec in source_files ]
2020-01-25 01:26:10 +01:00
2020-01-25 22:10:03 +01:00
spec_object = all_specs [ 0 ]
for value in all_specs [ 1 : ] :
2020-01-25 01:26:10 +01:00
spec_object = combine_spec_objects ( spec_object , value )
2020-07-03 10:48:57 +08:00
class_objects = { * * spec_object . ssz_objects , * * spec_object . dataclasses }
2022-02-25 01:22:02 +08:00
# Ensure it's ordered after multiple forks
new_objects = { }
while OrderedDict ( new_objects ) != OrderedDict ( class_objects ) :
new_objects = copy . deepcopy ( class_objects )
dependency_order_class_objects ( class_objects , spec_object . custom_types )
2020-01-25 01:26:10 +01:00
2023-06-20 18:02:39 +03:00
return objects_to_spec ( preset_name , spec_object , fork , class_objects )
2020-01-25 01:26:10 +01:00
class PySpecCommand ( Command ) :
""" Convert spec markdown files to a spec python file """
description = " Convert spec markdown files to a spec python file "
2020-01-31 11:52:30 +01:00
spec_fork : str
2020-01-25 01:26:10 +01:00
md_doc_paths : str
parsed_md_doc_paths : List [ str ]
2021-05-18 12:12:01 +02:00
build_targets : str
parsed_build_targets : List [ BuildTarget ]
2020-01-25 01:26:10 +01:00
out_dir : str
# The format is (long option, short option, description).
user_options = [
2020-01-31 11:52:30 +01:00
( ' spec-fork= ' , None , " Spec fork to tag build with. Used to select md-docs defaults. " ) ,
2020-01-25 01:26:10 +01:00
( ' md-doc-paths= ' , None , " List of paths of markdown files to build spec with " ) ,
2021-05-18 12:12:01 +02:00
( ' build-targets= ' , None , " Names, directory paths of compile-time presets, and default config paths. " ) ,
2020-01-25 01:26:10 +01:00
( ' out-dir= ' , None , " Output directory to write spec package to " )
]
def initialize_options ( self ) :
""" Set default values for options. """
# Each user option must be listed here with their default value.
2021-03-12 20:26:26 +08:00
self . spec_fork = PHASE0
2020-01-25 01:26:10 +01:00
self . md_doc_paths = ' '
self . out_dir = ' pyspec_output '
2021-05-18 12:12:01 +02:00
self . build_targets = """
2021-05-19 17:15:34 +02:00
minimal : presets / minimal : configs / minimal . yaml
2021-05-24 11:51:08 -07:00
mainnet : presets / mainnet : configs / mainnet . yaml
2021-05-18 12:12:01 +02:00
"""
2020-01-25 01:26:10 +01:00
def finalize_options ( self ) :
""" Post-process options. """
if len ( self . md_doc_paths ) == 0 :
2020-01-25 22:10:03 +01:00
print ( " no paths were specified, using default markdown file paths for pyspec "
2020-01-31 11:52:30 +01:00
" build (spec fork: %s ) " % self . spec_fork )
2023-06-26 18:01:56 +08:00
self . md_doc_paths = get_md_doc_paths ( self . spec_fork )
2021-07-22 16:36:41 +02:00
if len ( self . md_doc_paths ) == 0 :
2020-01-31 11:52:30 +01:00
raise Exception ( ' no markdown files specified, and spec fork " %s " is unknown ' , self . spec_fork )
2020-01-25 01:26:10 +01:00
self . parsed_md_doc_paths = self . md_doc_paths . split ( )
for filename in self . parsed_md_doc_paths :
if not os . path . exists ( filename ) :
raise Exception ( ' Pyspec markdown input file " %s " does not exist. ' % filename )
2021-05-18 12:12:01 +02:00
self . parsed_build_targets = [ ]
for target in self . build_targets . split ( ) :
target = target . strip ( )
data = target . split ( ' : ' )
if len ( data ) != 3 :
raise Exception ( ' invalid target, expected " name:preset_dir:config_file " format, but got: %s ' % target )
name , preset_dir_path , config_path = data
if any ( ( c not in string . digits + string . ascii_letters ) for c in name ) :
raise Exception ( ' invalid target name: " %s " ' % name )
if not os . path . exists ( preset_dir_path ) :
raise Exception ( ' Preset dir " %s " does not exist ' % preset_dir_path )
_ , _ , preset_file_names = next ( os . walk ( preset_dir_path ) )
preset_paths = [ ( Path ( preset_dir_path ) / name ) for name in preset_file_names ]
if not os . path . exists ( config_path ) :
raise Exception ( ' Config file " %s " does not exist ' % config_path )
self . parsed_build_targets . append ( BuildTarget ( name , preset_paths , Path ( config_path ) ) )
2020-01-25 01:26:10 +01:00
def run ( self ) :
2021-05-18 12:12:01 +02:00
if not self . dry_run :
2020-01-25 01:26:10 +01:00
dir_util . mkpath ( self . out_dir )
2021-05-18 12:12:01 +02:00
for ( name , preset_paths , config_path ) in self . parsed_build_targets :
2023-06-26 18:01:56 +08:00
spec_str = build_spec (
spec_builders [ self . spec_fork ] . fork ,
name ,
self . parsed_md_doc_paths ,
preset_paths ,
config_path ,
)
2021-05-18 12:12:01 +02:00
if self . dry_run :
self . announce ( ' dry run successfully prepared contents for spec. '
f ' out dir: " { self . out_dir } " , spec fork: " { self . spec_fork } " , build target: " { name } " ' )
self . debug_print ( spec_str )
else :
with open ( os . path . join ( self . out_dir , name + ' .py ' ) , ' w ' ) as out :
out . write ( spec_str )
if not self . dry_run :
2020-01-25 01:26:10 +01:00
with open ( os . path . join ( self . out_dir , ' __init__.py ' ) , ' w ' ) as out :
2021-05-25 21:13:12 +08:00
# `mainnet` is the default spec.
2021-05-25 21:40:10 +08:00
out . write ( " from . import mainnet as spec # noqa:F401 \n " )
2020-01-25 01:26:10 +01:00
class BuildPyCommand ( build_py ) :
""" Customize the build command to run the spec-builder on setup.py build """
def initialize_options ( self ) :
super ( BuildPyCommand , self ) . initialize_options ( )
2020-01-31 11:52:30 +01:00
def run_pyspec_cmd ( self , spec_fork : str , * * opts ) :
2020-01-25 01:26:10 +01:00
cmd_obj : PySpecCommand = self . distribution . reinitialize_command ( " pyspec " )
2020-01-31 11:52:30 +01:00
cmd_obj . spec_fork = spec_fork
cmd_obj . out_dir = os . path . join ( self . build_lib , ' eth2spec ' , spec_fork )
2020-01-25 01:26:10 +01:00
for k , v in opts . items ( ) :
setattr ( cmd_obj , k , v )
self . run_command ( ' pyspec ' )
def run ( self ) :
2021-04-16 11:29:10 +08:00
for spec_fork in spec_builders :
2020-01-31 11:52:30 +01:00
self . run_pyspec_cmd ( spec_fork = spec_fork )
2020-01-25 01:26:10 +01:00
super ( BuildPyCommand , self ) . run ( )
class PyspecDevCommand ( Command ) :
""" Build the markdown files in-place to their source location for testing. """
description = " Build the markdown files in-place to their source location for testing. "
user_options = [ ]
def initialize_options ( self ) :
pass
def finalize_options ( self ) :
pass
2020-01-31 11:52:30 +01:00
def run_pyspec_cmd ( self , spec_fork : str , * * opts ) :
2020-01-25 01:26:10 +01:00
cmd_obj : PySpecCommand = self . distribution . reinitialize_command ( " pyspec " )
2020-01-31 11:52:30 +01:00
cmd_obj . spec_fork = spec_fork
2020-01-25 01:26:10 +01:00
eth2spec_dir = convert_path ( self . distribution . package_dir [ ' eth2spec ' ] )
2020-01-31 11:52:30 +01:00
cmd_obj . out_dir = os . path . join ( eth2spec_dir , spec_fork )
2020-01-25 01:26:10 +01:00
for k , v in opts . items ( ) :
setattr ( cmd_obj , k , v )
self . run_command ( ' pyspec ' )
def run ( self ) :
print ( " running build_py command " )
2021-04-16 11:29:10 +08:00
for spec_fork in spec_builders :
2020-01-31 11:52:30 +01:00
self . run_pyspec_cmd ( spec_fork = spec_fork )
2020-01-25 01:26:10 +01:00
2023-06-26 18:01:56 +08:00
2020-01-25 01:26:10 +01:00
commands = {
' pyspec ' : PySpecCommand ,
' build_py ' : BuildPyCommand ,
' pyspecdev ' : PyspecDevCommand ,
}
with open ( " README.md " , " rt " , encoding = " utf8 " ) as f :
readme = f . read ( )
2020-02-05 18:38:21 +01:00
# How to use "VERSION.txt" file:
# - dev branch contains "X.Y.Z.dev", where "X.Y.Z" is the target version to release dev into.
# -> Changed as part of 'master' backport to 'dev'
# - master branch contains "X.Y.Z", where "X.Y.Z" is the current version.
# -> Changed as part of 'dev' release (or other branch) into 'master'
# -> In case of a commit on master without git tag, target the next version
# with ".postN" (release candidate, numbered) suffixed.
# See https://www.python.org/dev/peps/pep-0440/#public-version-identifiers
with open ( os . path . join ( ' tests ' , ' core ' , ' pyspec ' , ' eth2spec ' , ' VERSION.txt ' ) ) as f :
spec_version = f . read ( ) . strip ( )
2020-01-25 01:26:10 +01:00
setup (
name = ' eth2spec ' ,
2020-02-05 18:38:21 +01:00
version = spec_version ,
2020-01-25 01:26:10 +01:00
description = " Eth2 spec, provided as Python package for tooling and testing " ,
long_description = readme ,
long_description_content_type = " text/markdown " ,
author = " ethereum " ,
url = " https://github.com/ethereum/eth2.0-specs " ,
include_package_data = False ,
package_data = { ' configs ' : [ ' *.yaml ' ] ,
2021-05-19 17:15:34 +02:00
' presets ' : [ ' *.yaml ' ] ,
2020-02-05 18:38:21 +01:00
' specs ' : [ ' **/*.md ' ] ,
' eth2spec ' : [ ' VERSION.txt ' ] } ,
2020-01-25 01:26:10 +01:00
package_dir = {
" eth2spec " : " tests/core/pyspec/eth2spec " ,
" configs " : " configs " ,
2021-05-19 17:15:34 +02:00
" presets " : " presets " ,
2021-02-18 17:51:01 +08:00
" specs " : " specs " ,
2020-01-25 01:26:10 +01:00
} ,
packages = find_packages ( where = ' tests/core/pyspec ' ) + [ ' configs ' , ' specs ' ] ,
py_modules = [ " eth2spec " ] ,
cmdclass = commands ,
2023-05-03 17:25:04 +08:00
python_requires = " >=3.9, <4 " ,
2020-01-25 01:26:10 +01:00
extras_require = {
2020-01-25 22:10:03 +01:00
" test " : [ " pytest>=4.4 " , " pytest-cov " , " pytest-xdist " ] ,
2022-09-28 12:22:53 +08:00
" lint " : [ " flake8==5.0.4 " , " mypy==0.981 " , " pylint==2.15.3 " ] ,
2023-05-05 23:03:25 +08:00
" generator " : [ " python-snappy==0.6.1 " , " filelock " , " pathos==0.3.0 " ] ,
2023-04-18 18:31:34 +08:00
" docs " : [ " mkdocs==1.4.2 " , " mkdocs-material==9.1.5 " , " mdx-truly-sane-lists==1.3 " , " mkdocs-awesome-pages-plugin==2.8.0 " ]
2020-01-25 01:26:10 +01:00
} ,
install_requires = [
2022-09-28 12:22:53 +08:00
" eth-utils>=2.0.0,<3 " ,
" eth-typing>=3.2.0,<4.0.0 " ,
" pycryptodome==3.15.0 " ,
" py_ecc==6.0.0 " ,
2022-05-14 19:47:46 +02:00
" milagro_bls_binding==1.9.0 " ,
2023-01-26 11:57:47 +01:00
" remerkleable==0.1.27 " ,
2022-11-22 21:58:29 +01:00
" trie==2.0.2 " ,
2021-05-18 12:12:01 +02:00
RUAMEL_YAML_VERSION ,
2023-06-11 15:07:39 +02:00
" lru-dict==1.2.0 " ,
2021-05-18 12:12:01 +02:00
MARKO_VERSION ,
2023-03-02 20:49:10 +00:00
" py_arkworks_bls12381==0.3.4 " ,
2023-07-20 16:45:40 +02:00
" curdleproofs @ git+https://github.com/nalinbhardwaj/curdleproofs.pie@f27d630c44c5c1d5a568a4b0026aa7115904a469#egg=curdleproofs&subdirectory=curdleproofs " ,
2020-01-25 01:26:10 +01:00
]
)