Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions fire/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,11 @@ def _Fire(component, args, parsed_flag_args, context, name=None):

is_callable = inspect.isclass(component) or inspect.isroutine(component)
is_callable_object = callable(component) and not is_callable
if (inspect.isclass(component)
and _IsClassOrStaticMethodAccess(component, remaining_args)):
# Classmethods and staticmethods don't need an instance, so skip __init__
# and let the object handler below access the method on the class.
is_callable = False
is_sequence = isinstance(component, (list, tuple))
is_map = isinstance(component, dict) or inspectutils.IsNamedTuple(component)

Expand Down Expand Up @@ -619,6 +624,19 @@ def _Fire(component, args, parsed_flag_args, context, name=None):
return component_trace


def _IsClassOrStaticMethodAccess(cls, args):
"""Returns whether the next arg names a classmethod or staticmethod of cls."""
if not args:
return False
for name in (args[0], args[0].replace('-', '_')):
try:
attr = inspect.getattr_static(cls, name)
except AttributeError:
continue
return isinstance(attr, (classmethod, staticmethod))
return False


def _GetMember(component, args):
"""Returns a subcomponent of component by consuming an arg from args.

Expand Down
6 changes: 6 additions & 0 deletions fire/core_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,12 @@ def testClassMethod(self):
7,
)

def testStaticAndClassMethodsSkipConstructor(self):
component = tc.ErrorInConstructorWithStaticAndClassMethods
self.assertEqual(core.Fire(component, command=['static_fn', 'alpha']),
'alpha')
self.assertEqual(core.Fire(component, command=['class-fn', '6']), 7)

def testCustomSerialize(self):
def serialize(x):
if isinstance(x, list):
Expand Down
14 changes: 14 additions & 0 deletions fire/test_components.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,20 @@ def __init__(self, value='value'):
raise ValueError('Error in constructor')


class ErrorInConstructorWithStaticAndClassMethods:

def __init__(self):
raise ValueError('Error in constructor')

@staticmethod
def static_fn(args):
return args

@classmethod
def class_fn(cls, args):
return args + 1


class WithHelpArg:
"""Test class for testing when class has a help= arg."""

Expand Down
Loading