Skip to content

Commit

Permalink
Allow custom types to define their own serialization with __str__.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 260078541
Change-Id: I2999e0caaaf962708ab1de4272b1df58327b2ada
  • Loading branch information
dbieber authored and copybara-github committed Jul 26, 2019
1 parent 9629074 commit 18ba635
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 5 deletions.
12 changes: 11 additions & 1 deletion docs/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ if __name__ == '__main__':
Now we can draw stuff :).

```bash
$ python example.py move 3 3 on move 3 6 on move 6 3 on move 6 6 on move 7 4 on move 7 5 on __str__
$ python example.py move 3 3 on move 3 6 on move 6 3 on move 6 6 on move 7 4 on move 7 5 on
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Expand All @@ -428,6 +428,16 @@ $ python example.py move 3 3 on move 3 6 on move 6 3 on move 6 6 on move 7 4 on

It's supposed to be a smiley face.

### Custom Serialization

You'll notice in the BinaryCanvas example, the canvas with the smiley face was
printed to the screen. You can determine how a component will be serialized by
defining its `__str__` method.

If a custom `__str__` method is present on the final component, the object is
serialized and printed. If there's no custom `__str__` method, then the help
screen for the object is shown instead.

### Can we make an even simpler example than Hello World?

Yes, this program is even simpler than our original Hello World example.
Expand Down
2 changes: 2 additions & 0 deletions docs/using-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ the arguments of the class's \_\_init\_\_ function. Arguments must be specified
by name, using the flags syntax. See the section on
[calling a function](#calling-a-function) for more details.

Similarly, when passing arguments to a callable object (an object with a custom
`__call__` function), those arguments must be passed using flags syntax.

## Using Flags with Fire CLIs <a name="using-flags"></a>

Expand Down
12 changes: 9 additions & 3 deletions fire/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,15 @@ def _PrintResult(component_trace, verbose=False):
# and move serialization to its own module.
result = component_trace.GetResult()

if hasattr(result, '__str__'):
# If the object has a custom __str__ method, rather than one inherited from
# object, then we use that to serialize the object.
class_attrs = completion.GetClassAttrsDict(type(result))
str_attr = class_attrs.get('__str__')
if str_attr and str_attr.defining_class is not object:
print(str(result))
return

if isinstance(result, (list, set, frozenset, types.GeneratorType)):
for i in result:
print(_OneLineResult(i))
Expand All @@ -253,9 +262,6 @@ def _PrintResult(component_trace, verbose=False):
print(_DictAsString(result, verbose))
elif isinstance(result, tuple):
print(_OneLineResult(result))
elif isinstance(result, complex):
# Print "3+4j" instead of "(3+4j)".
print(str(result).strip('()'))
elif isinstance(result, value_types.VALUE_TYPES):
if result is not None:
print(result)
Expand Down
1 change: 0 additions & 1 deletion fire/inspectutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ def Py2GetArgSpec(fn):

def GetFullArgSpec(fn):
"""Returns a FullArgSpec describing the given callable."""

original_fn = fn
fn, skip_arg = _GetArgSpecInfo(fn)

Expand Down

0 comments on commit 18ba635

Please sign in to comment.