Skip to content

Commit

Permalink
Merge pull request #42 from hugovk/fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
hugovk committed Aug 25, 2022
2 parents afdde01 + 289f8ee commit e0a0ef0
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 68 deletions.
11 changes: 8 additions & 3 deletions src/humanize/filesize.py
Expand Up @@ -60,17 +60,22 @@ def naturalsize(

if abs_bytes == 1 and not gnu:
return "%d Byte" % bytes_
elif abs_bytes < base and not gnu:

if abs_bytes < base and not gnu:
return "%d Bytes" % bytes_
elif abs_bytes < base and gnu:

if abs_bytes < base and gnu:
return "%dB" % bytes_

for i, s in enumerate(suffix):
unit = base ** (i + 2)

if abs_bytes < unit and not gnu:
return (format + " %s") % ((base * bytes_ / unit), s)
elif abs_bytes < unit and gnu:

if abs_bytes < unit and gnu:
return (format + "%s") % ((base * bytes_ / unit), s)

if gnu:
return (format + "%s") % ((base * bytes_ / unit), s)
return (format + " %s") % ((base * bytes_ / unit), s)
57 changes: 29 additions & 28 deletions src/humanize/number.py
Expand Up @@ -145,8 +145,8 @@ def intcomma(value: NumberOrString, ndigits: int | None = None) -> str:
new = re.sub(r"^(-?\d+)(\d{3})", rf"\g<1>{sep}\g<2>", orig)
if orig == new:
return new
else:
return intcomma(new)

return intcomma(new)


powers = [10**x for x in (3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 100)]
Expand Down Expand Up @@ -213,27 +213,26 @@ def intword(value: NumberOrString, format: str = "%.1f") -> str:

if value < powers[0]:
return negative_prefix + str(value)
for ordinal, power in enumerate(powers[1:], 1):

for ordinal_, power in enumerate(powers[1:], 1):
if value < power:
chopped = value / float(powers[ordinal - 1])
chopped = value / float(powers[ordinal_ - 1])
if float(format % chopped) == float(10**3):
chopped = value / float(powers[ordinal])
singular, plural = human_powers[ordinal]
return (
negative_prefix
+ " ".join(
[format, _ngettext(singular, plural, math.ceil(chopped))]
)
) % chopped
else:
singular, plural = human_powers[ordinal - 1]
chopped = value / float(powers[ordinal_])
singular, plural = human_powers[ordinal_]
return (
negative_prefix
+ " ".join(
[format, _ngettext(singular, plural, math.ceil(chopped))]
)
) % chopped

singular, plural = human_powers[ordinal_ - 1]
return (
negative_prefix
+ " ".join([format, _ngettext(singular, plural, math.ceil(chopped))])
) % chopped

return negative_prefix + str(value)


Expand Down Expand Up @@ -334,10 +333,11 @@ def fractional(value: NumberOrString) -> str:
# this means that an integer was passed in
# (or variants of that integer like 1.0000)
return f"{whole_number:.0f}"
elif not whole_number:

if not whole_number:
return f"{numerator:.0f}/{denominator:.0f}"
else:
return f"{whole_number:.0f} {numerator:.0f}/{denominator:.0f}"

return f"{whole_number:.0f} {numerator:.0f}/{denominator:.0f}"


def scientific(value: NumberOrString, precision: int = 2) -> str:
Expand Down Expand Up @@ -464,13 +464,14 @@ def clamp(

if isinstance(format, str):
return token + format.format(value)
elif callable(format):

if callable(format):
return token + format(value)
else:
raise ValueError(
"Invalid format. Must be either a valid formatting string, or a function "
"that accepts value and returns a string."
)

raise ValueError(
"Invalid format. Must be either a valid formatting string, or a function "
"that accepts value and returns a string."
)


def metric(value: float, unit: str = "", precision: int = 3) -> str:
Expand Down Expand Up @@ -515,15 +516,15 @@ def metric(value: float, unit: str = "", precision: int = 3) -> str:

value /= 10 ** (exponent // 3 * 3)
if exponent >= 3:
ordinal = "kMGTPEZY"[exponent // 3 - 1]
ordinal_ = "kMGTPEZY"[exponent // 3 - 1]
elif exponent < 0:
ordinal = "mμnpfazy"[(-exponent - 1) // 3]
ordinal_ = "mμnpfazy"[(-exponent - 1) // 3]
else:
ordinal = ""
ordinal_ = ""
value_ = format(value, ".%if" % (precision - (exponent % 3) - 1))
if not (unit or ordinal) or unit in ("°", "′", "″"):
if not (unit or ordinal_) or unit in ("°", "′", "″"):
space = ""
else:
space = " "

return f"{value_}{space}{ordinal}{unit}"
return f"{value_}{space}{ordinal_}{unit}"
89 changes: 54 additions & 35 deletions src/humanize/time.py
Expand Up @@ -151,7 +151,8 @@ def naturaldelta(
_ngettext("%d microsecond", "%d microseconds", delta.microseconds)
% delta.microseconds
)
elif min_unit == Unit.MILLISECONDS or (

if min_unit == Unit.MILLISECONDS or (
min_unit == Unit.MICROSECONDS and 1000 <= delta.microseconds < 1_000_000
):
milliseconds = delta.microseconds / 1000
Expand All @@ -160,47 +161,59 @@ def naturaldelta(
% milliseconds
)
return _("a moment")
elif seconds == 1:

if seconds == 1:
return _("a second")
elif seconds < 60:

if seconds < 60:
return _ngettext("%d second", "%d seconds", seconds) % seconds
elif 60 <= seconds < 120:

if 60 <= seconds < 120:
return _("a minute")
elif 120 <= seconds < 3600:

if 120 <= seconds < 3600:
minutes = seconds // 60
return _ngettext("%d minute", "%d minutes", minutes) % minutes
elif 3600 <= seconds < 3600 * 2:

if 3600 <= seconds < 3600 * 2:
return _("an hour")
elif 3600 < seconds:

if 3600 < seconds:
hours = seconds // 3600
return _ngettext("%d hour", "%d hours", hours) % hours

elif years == 0:
if days == 1:
return _("a day")

if not use_months:
return _ngettext("%d day", "%d days", days) % days
else:
if not num_months:
return _ngettext("%d day", "%d days", days) % days
elif num_months == 1:
return _("a month")
else:
return _ngettext("%d month", "%d months", num_months) % num_months

if not num_months:
return _ngettext("%d day", "%d days", days) % days

if num_months == 1:
return _("a month")

return _ngettext("%d month", "%d months", num_months) % num_months

elif years == 1:
if not num_months and not days:
return _("a year")
elif not num_months:

if not num_months:
return _ngettext("1 year, %d day", "1 year, %d days", days) % days
elif use_months:

if use_months:
if num_months == 1:
return _("1 year, 1 month")
else:
return (
_ngettext("1 year, %d month", "1 year, %d months", num_months)
% num_months
)
else:
return _ngettext("1 year, %d day", "1 year, %d days", days) % days

return (
_ngettext("1 year, %d month", "1 year, %d months", num_months)
% num_months
)

return _ngettext("1 year, %d day", "1 year, %d days", days) % days

return _ngettext("%d year", "%d years", years).replace("%d", "%s") % intcomma(years)

Expand Down Expand Up @@ -265,12 +278,16 @@ def naturalday(value: dt.date | dt.datetime, format: str = "%b %d") -> str:
# Date arguments out of range
return str(value)
delta = value - dt.date.today()

if delta.days == 0:
return _("today")
elif delta.days == 1:

if delta.days == 1:
return _("tomorrow")
elif delta.days == -1:

if delta.days == -1:
return _("yesterday")

return value.strftime(format)


Expand Down Expand Up @@ -323,10 +340,11 @@ def _quotient_and_remainder(
"""
if unit == minimum_unit:
return value / divisor, 0
elif unit in suppress:

if unit in suppress:
return 0, value
else:
return divmod(value, divisor)

return divmod(value, divisor)


def _carry(
Expand Down Expand Up @@ -361,10 +379,11 @@ def _carry(
"""
if unit == min_unit:
return value1 + value2 / ratio, 0
elif unit in suppress:

if unit in suppress:
return 0, value2 + value1 * ratio
else:
return value1, value2

return value1, value2


def _suitable_minimum_unit(min_unit: Unit, suppress: typing.Iterable[Unit]) -> Unit:
Expand Down Expand Up @@ -405,16 +424,16 @@ def _suppress_lower_units(min_unit: Unit, suppress: typing.Iterable[Unit]) -> se
['MICROSECONDS', 'MILLISECONDS', 'DAYS']
"""
suppress = set(suppress)
for u in Unit:
if u == min_unit:
for unit in Unit:
if unit == min_unit:
break
suppress.add(u)
suppress.add(unit)

return suppress


def precisedelta(
value: dt.timedelta | int,
value: dt.timedelta | int | None,
minimum_unit: str = "seconds",
suppress: typing.Iterable[str] = (),
format: str = "%0.2f",
Expand Down
2 changes: 1 addition & 1 deletion tests/test_i18n.py
Expand Up @@ -158,7 +158,7 @@ def test_default_locale_path_null__file__() -> None:
def test_default_locale_path_undefined__file__() -> None:
i18n = importlib.import_module("humanize.i18n")
del i18n.__file__
i18n._get_default_locale_path() is None
assert i18n._get_default_locale_path() is None


class TestActivate:
Expand Down
3 changes: 2 additions & 1 deletion tests/test_time.py
Expand Up @@ -629,6 +629,8 @@ def test_precisedelta_suppress_units(


def test_precisedelta_bogus_call() -> None:
assert humanize.precisedelta(None) == "None"

with pytest.raises(ValueError):
humanize.precisedelta(1, minimum_unit="years", suppress=["years"])

Expand All @@ -640,7 +642,6 @@ def test_time_unit() -> None:
years, minutes = time.Unit["YEARS"], time.Unit["MINUTES"]
assert minutes < years
assert years > minutes
assert minutes == minutes

with pytest.raises(TypeError):
_ = years < "foo"

0 comments on commit e0a0ef0

Please sign in to comment.