Skip to content

Commit

Permalink
Defer imports for faster overall import time: 19 ms -> 5 ms (#234)
Browse files Browse the repository at this point in the history
  • Loading branch information
hugovk authored Feb 13, 2025
2 parents c6455cf + 147cbbc commit 13f71a3
Show file tree
Hide file tree
Showing 8 changed files with 33 additions and 25 deletions.
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ repos:
- id: debug-statements
- id: end-of-file-fixer
- id: forbid-submodules
- id: requirements-txt-fixer
- id: trailing-whitespace
exclude: \.github/ISSUE_TEMPLATE\.md|\.github/PULL_REQUEST_TEMPLATE\.md

Expand Down
2 changes: 1 addition & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mkdocs==1.6.1
mkdocs-include-markdown-plugin
mkdocs-material
mkdocstrings[python]==0.27.0
mkdocs-include-markdown-plugin
pygments
pymdown-extensions==10.14.3
4 changes: 4 additions & 0 deletions requirements-mypy.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mypy==1.15.0
pytest
types-freezegun
types-setuptools
2 changes: 1 addition & 1 deletion src/humanize/i18n.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

import gettext as gettext_module
from threading import local
from typing import TYPE_CHECKING

TYPE_CHECKING = False
if TYPE_CHECKING:
import os
import pathlib
Expand Down
4 changes: 3 additions & 1 deletion src/humanize/lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

from __future__ import annotations

from typing import Any
TYPE_CHECKING = False
if TYPE_CHECKING:
from typing import Any

__all__ = ["natural_list"]

Expand Down
16 changes: 10 additions & 6 deletions src/humanize/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,24 @@
from __future__ import annotations

import math
import re
import sys
from typing import TYPE_CHECKING

from .i18n import _gettext as _
from .i18n import _ngettext, decimal_separator, thousands_separator
from .i18n import _ngettext_noop as NS_
from .i18n import _pgettext as P_

TYPE_CHECKING = False
if TYPE_CHECKING:
import sys

if sys.version_info >= (3, 10):
from typing import TypeAlias
else:
from typing_extensions import TypeAlias

# This type can be better defined by typing.SupportsInt, typing.SupportsFloat
# but that's a Python 3.8 only typing option.
NumberOrString: TypeAlias = "float | str"
# This type can be better defined by typing.SupportsFloat
# but that's a Python 3.8 only typing option.
NumberOrString: TypeAlias = float | str


def _format_not_finite(value: float) -> str:
Expand Down Expand Up @@ -165,6 +165,8 @@ def intcomma(value: NumberOrString, ndigits: int | None = None) -> str:
else:
orig = str(value)
orig = orig.replace(".", decimal_sep)
import re

while True:
new = re.sub(r"^(-?\d+)(\d{3})", rf"\g<1>{thousands_sep}\g<2>", orig)
if orig == new:
Expand Down Expand Up @@ -429,6 +431,8 @@ def scientific(value: NumberOrString, precision: int = 2) -> str:
n = fmt.format(value)
part1, part2 = n.split("e")
# Remove redundant leading '+' or '0's (preserving the last '0' for 10⁰).
import re

part2 = re.sub(r"^\+?(\-?)0*(.+)$", r"\1\2", part2)

new_part2 = []
Expand Down
24 changes: 12 additions & 12 deletions src/humanize/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,20 @@

from __future__ import annotations

import collections.abc
import datetime as dt
import math
import typing
from enum import Enum
from functools import total_ordering
from typing import Any

from .i18n import _gettext as _
from .i18n import _ngettext
from .number import intcomma

TYPE_CHECKING = False
if TYPE_CHECKING:
from collections.abc import Iterable
from typing import Any

__all__ = [
"naturaldate",
"naturalday",
Expand All @@ -37,7 +39,7 @@ class Unit(Enum):
MONTHS = 6
YEARS = 7

def __lt__(self, other: typing.Any) -> typing.Any:
def __lt__(self, other: Any) -> Any:
if self.__class__ is other.__class__:
return self.value < other.value
return NotImplemented
Expand All @@ -62,9 +64,7 @@ def _abs_timedelta(delta: dt.timedelta) -> dt.timedelta:
return delta


def _date_and_delta(
value: typing.Any, *, now: dt.datetime | None = None
) -> tuple[typing.Any, typing.Any]:
def _date_and_delta(value: Any, *, now: dt.datetime | None = None) -> tuple[Any, Any]:
"""Turn a value into a date and a timedelta which represents how long ago it was.
If that's not possible, return `(None, value)`.
Expand Down Expand Up @@ -327,7 +327,7 @@ def _quotient_and_remainder(
divisor: float,
unit: Unit,
minimum_unit: Unit,
suppress: collections.abc.Iterable[Unit],
suppress: Iterable[Unit],
) -> tuple[float, float]:
"""Divide `value` by `divisor` returning the quotient and remainder.
Expand Down Expand Up @@ -368,7 +368,7 @@ def _carry(
ratio: float,
unit: Unit,
min_unit: Unit,
suppress: typing.Iterable[Unit],
suppress: Iterable[Unit],
) -> tuple[float, float]:
"""Return a tuple with two values.
Expand Down Expand Up @@ -401,7 +401,7 @@ def _carry(
return value1, value2


def _suitable_minimum_unit(min_unit: Unit, suppress: typing.Iterable[Unit]) -> Unit:
def _suitable_minimum_unit(min_unit: Unit, suppress: Iterable[Unit]) -> Unit:
"""Return a minimum unit suitable that is not suppressed.
If not suppressed, return the same unit:
Expand Down Expand Up @@ -430,7 +430,7 @@ def _suitable_minimum_unit(min_unit: Unit, suppress: typing.Iterable[Unit]) -> U
return min_unit


def _suppress_lower_units(min_unit: Unit, suppress: typing.Iterable[Unit]) -> set[Unit]:
def _suppress_lower_units(min_unit: Unit, suppress: Iterable[Unit]) -> set[Unit]:
"""Extend suppressed units (if any) with all units lower than the minimum unit.
>>> from humanize.time import _suppress_lower_units, Unit
Expand All @@ -449,7 +449,7 @@ def _suppress_lower_units(min_unit: Unit, suppress: typing.Iterable[Unit]) -> se
def precisedelta(
value: dt.timedelta | int | None,
minimum_unit: str = "seconds",
suppress: typing.Iterable[str] = (),
suppress: Iterable[str] = (),
format: str = "%0.2f",
) -> str:
"""Return a precise representation of a timedelta.
Expand Down
5 changes: 1 addition & 4 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,7 @@ commands =

[testenv:mypy]
deps =
mypy==1.12
pytest
types-freezegun
types-setuptools
-r requirements-mypy.txt
commands =
mypy . {posargs}

Expand Down

0 comments on commit 13f71a3

Please sign in to comment.