Use constant variables to define phase name/ID

This commit is contained in:
Hsiao-Wei Wang 2020-04-02 14:54:48 +08:00
parent 5c7bc7e942
commit a890d1f6a0
No known key found for this signature in database
GPG Key ID: 95B070122902DEA4
1 changed files with 25 additions and 20 deletions

View File

@ -7,7 +7,7 @@ from .helpers.genesis import create_genesis_state
from .utils import vector_test, with_meta_tags from .utils import vector_test, with_meta_tags
from random import Random from random import Random
from typing import Any, Callable, Sequence, TypedDict, Protocol from typing import Any, Callable, NewType, Sequence, TypedDict, Protocol
from importlib import reload from importlib import reload
@ -19,25 +19,33 @@ def reload_specs():
# Some of the Spec module functionality is exposed here to deal with phase-specific changes. # Some of the Spec module functionality is exposed here to deal with phase-specific changes.
SpecForkName = NewType("SpecForkName", str)
PHASE0 = SpecForkName('phase0')
PHASE1 = SpecForkName('phase1')
ALL_PHASES = (PHASE0, PHASE1)
# TODO: currently phases are defined as python modules. # TODO: currently phases are defined as python modules.
# It would be better if they would be more well-defined interfaces for stronger typing. # It would be better if they would be more well-defined interfaces for stronger typing.
class Spec(Protocol): class Spec(Protocol):
version: str version: str
class Phase0(Spec): class SpecPhase0(Spec):
... ...
class Phase1(Spec): class SpecPhase1(Spec):
def upgrade_to_phase1(self, state: spec_phase0.BeaconState) -> spec_phase1.BeaconState: def upgrade_to_phase1(self, state: spec_phase0.BeaconState) -> spec_phase1.BeaconState:
... ...
# add transfer, bridge, etc. as the spec evolves # add transfer, bridge, etc. as the spec evolves
class SpecForks(TypedDict, total=False): class SpecForks(TypedDict, total=False):
phase0: Phase0 PHASE0: SpecPhase0
phase1: Phase1 PHASE1: SpecPhase1
def with_custom_state(balances_fn: Callable[[Any], Sequence[int]], def with_custom_state(balances_fn: Callable[[Any], Sequence[int]],
@ -45,16 +53,16 @@ def with_custom_state(balances_fn: Callable[[Any], Sequence[int]],
def deco(fn): def deco(fn):
def entry(*args, spec: Spec, phases: SpecForks, **kw): def entry(*args, spec: Spec, phases: SpecForks, **kw):
try: try:
p0 = phases["phase0"] p0 = phases[PHASE0]
balances = balances_fn(p0) balances = balances_fn(p0)
activation_threshold = threshold_fn(p0) activation_threshold = threshold_fn(p0)
state = create_genesis_state(spec=p0, validator_balances=balances, state = create_genesis_state(spec=p0, validator_balances=balances,
activation_threshold=activation_threshold) activation_threshold=activation_threshold)
if spec.fork == 'phase1': if spec.fork == PHASE1:
# TODO: instead of upgrading a test phase0 genesis state we can also write a phase1 state helper. # TODO: instead of upgrading a test phase0 genesis state we can also write a phase1 state helper.
# Decide based on performance/consistency results later. # Decide based on performance/consistency results later.
state = phases["phase1"].upgrade_to_phase1(state) state = phases[PHASE1].upgrade_to_phase1(state)
kw['state'] = state kw['state'] = state
except KeyError: except KeyError:
@ -217,14 +225,11 @@ def bls_switch(fn):
return entry return entry
all_phases = ['phase0', 'phase1']
def with_all_phases(fn): def with_all_phases(fn):
""" """
A decorator for running a test with every phase A decorator for running a test with every phase
""" """
return with_phases(all_phases)(fn) return with_phases(ALL_PHASES)(fn)
def with_all_phases_except(exclusion_phases): def with_all_phases_except(exclusion_phases):
@ -232,7 +237,7 @@ def with_all_phases_except(exclusion_phases):
A decorator factory for running a tests with every phase except the ones listed A decorator factory for running a tests with every phase except the ones listed
""" """
def decorator(fn): def decorator(fn):
return with_phases([phase for phase in all_phases if phase not in exclusion_phases])(fn) return with_phases([phase for phase in ALL_PHASES if phase not in exclusion_phases])(fn)
return decorator return decorator
@ -258,18 +263,18 @@ def with_phases(phases, other_phases=None):
# TODO: test state is dependent on phase0 but is immediately transitioned to phase1. # TODO: test state is dependent on phase0 but is immediately transitioned to phase1.
# A new state-creation helper for phase 1 may be in place, and then phase1+ tests can run without phase0 # A new state-creation helper for phase 1 may be in place, and then phase1+ tests can run without phase0
available_phases.add('phase0') available_phases.add(PHASE0)
phase_dir = {} phase_dir = {}
if 'phase0' in available_phases: if PHASE0 in available_phases:
phase_dir['phase0'] = spec_phase0 phase_dir[PHASE0] = spec_phase0
if 'phase1' in available_phases: if PHASE1 in available_phases:
phase_dir['phase1'] = spec_phase1 phase_dir[PHASE1] = spec_phase1
# return is ignored whenever multiple phases are ran. If # return is ignored whenever multiple phases are ran. If
if 'phase0' in run_phases: if PHASE0 in run_phases:
ret = fn(spec=spec_phase0, phases=phase_dir, *args, **kw) ret = fn(spec=spec_phase0, phases=phase_dir, *args, **kw)
if 'phase1' in run_phases: if PHASE1 in run_phases:
ret = fn(spec=spec_phase1, phases=phase_dir, *args, **kw) ret = fn(spec=spec_phase1, phases=phase_dir, *args, **kw)
return ret return ret
return wrapper return wrapper