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

Incorrect handling of subtypes of datetime types #92

Open
macdjord opened this issue Mar 6, 2023 · 0 comments
Open

Incorrect handling of subtypes of datetime types #92

macdjord opened this issue Mar 6, 2023 · 0 comments

Comments

@macdjord
Copy link

macdjord commented Mar 6, 2023

  • PrettyPrinter version: 0.18.0
  • Python version: 3.11.2
  • Operating System: Win10

Description

If you have a user-created subtype of one of the datetime types, e.g. time, date, or datetime, and you prettyprint an instance of that subtype, the prettyprinted representation will use the class name of the base type, rather than the subtype.

What I Did

import datetime as _dt
import prettyprinter as _prettyprinter


class Timestamp(_dt.datetime):
    """Standardized datatype for timestamps, i.e. a datetime which is always UTC"""

    def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0, microsecond=0, tzinfo=_dt.timezone.utc, *, fold=0):
        # Call the parent method to create the object
        self = super().__new__(cls, year, month, day, hour, minute, second, microsecond, tzinfo, fold=fold)

        # Confirm the object is in UTC
        # (We have to do this after creating the object, rather than just checking the `tzinfo` arg,
        # because the parent method handles the case of loading a Pickled object.)
        if self.tzinfo != _dt.timezone.utc:
            raise ValueError(f"Timestamp must have UTC timezone; got {self!r}")
        if self.fold:
            raise ValueError(f"Timestamp are always UTC, so nonzero 'fold' is meaningless; got {self!r}")

        return self


ts = Timestamp(2023, 1, 1)
_prettyprinter.pprint(ts)

Output:

datetime.datetime(
    year=2023,
    month=1,
    day=1,
    tzinfo=datetime.timezone.utc
)

Expected output:

Timestamp(
    year=2023,
    month=1,
    day=1,
    tzinfo=datetime.timezone.utc
)

The Fix

The fix for this is actually pretty simple. In pretty_stdlib.py there are functions to handle the datetime classes. These functions call pretty_call_alt() and similar functions with hard-coded references to the datetime classes. These hardcoded references should be replaced with the actual type of the passed-in instance. E.g., in def pretty_datetime(dt, ctx):, calls to pretty_call_alt(ctx, datetime, ...) should be changed to pretty_call_alt(ctx, type(dt), ...).

Curiously, it is only the datetime and pytz classes that have this problem; all the other types handled in that file, e.g. UUIDs, defaultdicts, dequeues, etc., all use type(...) already.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant