Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added __format__ method #76

Open
wants to merge 8 commits into
base: 2023-01-26-no-more-py2
Choose a base branch
from
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
7 changes: 6 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ notifications:
branches:
only:
- master
- format-method
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm reading your comments in the PR thread and seeing that message about CI failures. Once this is in a state ready to merge we can remove this extra branch, right?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I'll squash the commits, rebase out the development branch, and provide some examples.

after_success:
- coveralls
matrix:
include:
- python: "2.7"
env: CI=ci2
- python: "3.3"
- python: "3.4"
env: CI=ci3
- python: "3.5"
env: CI=ci3
- python: "3.6"
env: CI=ci3
script: make $CI
install: ""
13 changes: 13 additions & 0 deletions bitmath/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,19 @@ def __str__(self):
global format_string
return self.format(format_string)

def __format__(self, format_spec):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the purpose of updating the documentation later, can you tell me some of the limitations of this? Additional more complex examples would be even better. Even just a gist w/ you playing around with this in a python interpreter showing example input and output would be helpful. Like, as a user, still you use the various instance attributes in formatting? I think so, since the __format__ method ultimately calls out to self.format, but I'd like some more examples and such 😄

"""String representation of this object with custom formatting, such as specified number of digits."""
global format_string
try:
# replace any format spec added into global format_string with the format_spec used in this invocation
value_end = format_string.index('{value') + 6
brace_index = format_string.index('}', value_end)
format_string_custom = format_string[:value_end] + ':' + format_spec + format_string[brace_index:]
except ValueError:
# no {value} found in format_string, so cannot customize; fall back to global format_string
format_string_custom = format_string
return self.format(format_string_custom)

def format(self, fmt):
"""Return a representation of this instance formatted with user
supplied syntax"""
Expand Down
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.1',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python',
'Topic :: Scientific/Engineering :: Mathematics',
'Topic :: Software Development :: Libraries :: Python Modules',
Expand Down
36 changes: 36 additions & 0 deletions tests/test_representation.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,39 @@ def test_print_byte_singular(self):
one_Byte = bitmath.Byte(1.0)
actual_result = one_Byte.format(fmt_str)
self.assertEqual(expected_result, actual_result)

def test_inline_format(self):
"""Inline string formatting interpolates default format_string values"""
expected_result = 'size: 3.1215 MiB'
size = bitmath.MiB(3.1215)
actual_result = 'size: {size}'.format(size=size)
self.assertEqual(expected_result, actual_result)

def test_inline_format_customized(self):
"""Inline formats obey inline format specifications"""
expected_result = 'size: 3.1 MiB'
size = bitmath.MiB(3.1215)
actual_result = 'size: {size:.1f}'.format(size=size)
self.assertEqual(expected_result, actual_result)

def test_inline_format_override(self):
"""Inline formats use module defaults, overriding only format spec"""
orig_fmt_str = bitmath.format_string
bitmath.format_string = "{unit} {value:.3f}"
expected_result = 'size: MiB 3.1'
size = bitmath.MiB(3.1215)
actual_result = 'size: {size:.1f}'.format(size=size)
self.assertEqual(expected_result, actual_result)
bitmath.format_string = orig_fmt_str

def test_inline_format_cant_override(self):
"""Inline formats use module defaults, changing nothing if no {value} component"""
orig_fmt_str = bitmath.format_string
bitmath.format_string = "{power} {binary}"
expected_result = 'size: 20 0b1100011111000110101001111'
size = bitmath.MiB(3.1215)
# will not obey instant formatting, because global format_string doesn't allow that;
# obeys the global format_string instead
actual_result = 'size: {size:.1f}'.format(size=size)
self.assertEqual(expected_result, actual_result)
bitmath.format_string = orig_fmt_str
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see it repeated in test_inline_format_override as well. Do you think this duplication could be cleaned up by adding this to a tearDown() method? Seems like a cheap and safe way to ensure we don't forget to do that again in later tests.