multimethod uses Spec() instead of parse_anonymous_spec()
- simplify logic in multimethod - remove the requirement of multimethod invocations to walk up the stack.
This commit is contained in:
parent
88cb11758b
commit
61b859193d
@ -26,11 +26,11 @@
|
|||||||
"""
|
"""
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
from llnl.util.lang import caller_locals, get_calling_module_name
|
from llnl.util.lang import caller_locals
|
||||||
|
|
||||||
import spack.architecture
|
import spack.architecture
|
||||||
import spack.error
|
import spack.error
|
||||||
from spack.spec import parse_anonymous_spec
|
from spack.spec import Spec
|
||||||
|
|
||||||
|
|
||||||
class SpecMultiMethod(object):
|
class SpecMultiMethod(object):
|
||||||
@ -46,11 +46,6 @@ class SpecMultiMethod(object):
|
|||||||
to find one that matches the package's spec. If it finds one
|
to find one that matches the package's spec. If it finds one
|
||||||
(and only one), it will call that method.
|
(and only one), it will call that method.
|
||||||
|
|
||||||
The package author is responsible for ensuring that only one
|
|
||||||
condition on multi-methods ever evaluates to true. If
|
|
||||||
multiple methods evaluate to true, this will raise an
|
|
||||||
exception.
|
|
||||||
|
|
||||||
This is intended for use with decorators (see below). The
|
This is intended for use with decorators (see below). The
|
||||||
decorator (see docs below) creates SpecMultiMethods and
|
decorator (see docs below) creates SpecMultiMethods and
|
||||||
registers method versions with them.
|
registers method versions with them.
|
||||||
@ -76,7 +71,7 @@ def __init__(self, default=None):
|
|||||||
functools.update_wrapper(self, default)
|
functools.update_wrapper(self, default)
|
||||||
|
|
||||||
def register(self, spec, method):
|
def register(self, spec, method):
|
||||||
"""Register a version of a method for a particular sys_type."""
|
"""Register a version of a method for a particular spec."""
|
||||||
self.method_list.append((spec, method))
|
self.method_list.append((spec, method))
|
||||||
|
|
||||||
if not hasattr(self, '__name__'):
|
if not hasattr(self, '__name__'):
|
||||||
@ -91,6 +86,7 @@ def __get__(self, obj, objtype):
|
|||||||
# element in the list. The first registered function
|
# element in the list. The first registered function
|
||||||
# will be the one 'wrapped'.
|
# will be the one 'wrapped'.
|
||||||
wrapped_method = self.method_list[0][1]
|
wrapped_method = self.method_list[0][1]
|
||||||
|
|
||||||
# Call functools.wraps manually to get all the attributes
|
# Call functools.wraps manually to get all the attributes
|
||||||
# we need to be disguised as the wrapped_method
|
# we need to be disguised as the wrapped_method
|
||||||
func = functools.wraps(wrapped_method)(
|
func = functools.wraps(wrapped_method)(
|
||||||
@ -178,10 +174,6 @@ def install(self, prefix):
|
|||||||
self.setup()
|
self.setup()
|
||||||
# Do more common install stuff
|
# Do more common install stuff
|
||||||
|
|
||||||
There must be one (and only one) @when clause that matches the
|
|
||||||
package's spec. If there is more than one, or if none match,
|
|
||||||
then the method will raise an exception when it's called.
|
|
||||||
|
|
||||||
Note that the default version of decorated methods must
|
Note that the default version of decorated methods must
|
||||||
*always* come first. Otherwise it will override all of the
|
*always* come first. Otherwise it will override all of the
|
||||||
platform-specific versions. There's not much we can do to get
|
platform-specific versions. There's not much we can do to get
|
||||||
@ -189,11 +181,12 @@ def install(self, prefix):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, spec):
|
def __init__(self, spec):
|
||||||
pkg = get_calling_module_name()
|
|
||||||
if spec is True:
|
if spec is True:
|
||||||
spec = pkg
|
self.spec = Spec()
|
||||||
self.spec = (parse_anonymous_spec(spec, pkg)
|
elif spec is not False:
|
||||||
if spec is not False else None)
|
self.spec = Spec(spec)
|
||||||
|
else:
|
||||||
|
self.spec = None
|
||||||
|
|
||||||
def __call__(self, method):
|
def __call__(self, method):
|
||||||
# Get the first definition of the method in the calling scope
|
# Get the first definition of the method in the calling scope
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
def target_factory(spec_string, target_concrete):
|
def target_factory(spec_string, target_concrete):
|
||||||
spec = Spec(spec_string) if spec_string else Spec()
|
spec = Spec(spec_string) if spec_string else Spec()
|
||||||
print spec, spec_string, "AAAAA"
|
|
||||||
if target_concrete:
|
if target_concrete:
|
||||||
spec._mark_concrete()
|
spec._mark_concrete()
|
||||||
substitute_abstract_variants(spec)
|
substitute_abstract_variants(spec)
|
||||||
@ -27,18 +27,15 @@ def argument_factory(argument_spec, left):
|
|||||||
# If it's not anonymous, allow it
|
# If it's not anonymous, allow it
|
||||||
right = target_factory(argument_spec, False)
|
right = target_factory(argument_spec, False)
|
||||||
except Exception:
|
except Exception:
|
||||||
print "HAHA"
|
|
||||||
right = parse_anonymous_spec(argument_spec, left.name)
|
right = parse_anonymous_spec(argument_spec, left.name)
|
||||||
return right
|
return right
|
||||||
|
|
||||||
|
|
||||||
def check_satisfies(target_spec, argument_spec, target_concrete=False):
|
def check_satisfies(target_spec, argument_spec, target_concrete=False):
|
||||||
|
|
||||||
left = target_factory(target_spec, target_concrete)
|
left = target_factory(target_spec, target_concrete)
|
||||||
right = argument_factory(argument_spec, left)
|
right = argument_factory(argument_spec, left)
|
||||||
|
|
||||||
print left, 'left', left.name
|
|
||||||
print right, right.name
|
|
||||||
# Satisfies is one-directional.
|
# Satisfies is one-directional.
|
||||||
assert left.satisfies(right)
|
assert left.satisfies(right)
|
||||||
if argument_spec:
|
if argument_spec:
|
||||||
|
@ -21,7 +21,7 @@ class Multimethod(MultimethodBase):
|
|||||||
url = 'http://www.example.com/example-1.0.tar.gz'
|
url = 'http://www.example.com/example-1.0.tar.gz'
|
||||||
|
|
||||||
#
|
#
|
||||||
# These functions are only valid for versions 1, 2, and 3.
|
# These functions are only valid for versions 1, 3, and 4.
|
||||||
#
|
#
|
||||||
@when('@1.0')
|
@when('@1.0')
|
||||||
def no_version_2(self):
|
def no_version_2(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user