Skip to content

Deprecate delegation of int to __trunc__ #89140

Description

@mdickinson
BPO 44977
Nosy @rhettinger, @mdickinson, @serhiy-storchaka, @ZackerySpytz
PRs
  • bpo-44977: Deprecate delegation of int to __trunc__ #31031
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2022-02-03.09:44:44.771>
    created_at = <Date 2021-08-22.09:17:57.051>
    labels = ['interpreter-core', '3.11']
    title = 'Deprecate delegation of int to __trunc__'
    updated_at = <Date 2022-02-03.09:44:44.770>
    user = 'https://github.com/mdickinson'

    bugs.python.org fields:

    activity = <Date 2022-02-03.09:44:44.770>
    actor = 'serhiy.storchaka'
    assignee = 'none'
    closed = True
    closed_date = <Date 2022-02-03.09:44:44.771>
    closer = 'serhiy.storchaka'
    components = ['Interpreter Core']
    creation = <Date 2021-08-22.09:17:57.051>
    creator = 'mark.dickinson'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 44977
    keywords = ['patch']
    message_count = 12.0
    messages = ['400063', '400064', '400073', '400074', '400076', '400078', '400079', '400080', '400082', '412190', '412431', '412432']
    nosy_count = 4.0
    nosy_names = ['rhettinger', 'mark.dickinson', 'serhiy.storchaka', 'ZackerySpytz']
    pr_nums = ['31031']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = None
    url = 'https://bugs.python.org/issue44977'
    versions = ['Python 3.11']

    Activity

    1. mdickinson commented on Aug 22, 2021

      @mdickinson
      MemberAuthor

      The int constructor, when applied to a general Python object obj, first looks for an int method, then for an index method, and then finally for a trunc method.

      The delegation to __trunc__ used to be useful: it meant that users could write a custom class SomeNumber with the property that:

      • SomeNumber instances supported 'int' calls, returning a truncated value, but
      • SomeNumber instances weren't usable in indexing, chr() calls, and all the various other calls that implicitly invoked __int__.
      class SomeNumber:
          def __trunc__(self):
             <return truncated value for self>

      However, with Python >= 3.10, we no longer use __int__ implicitly for argument conversion in internal code. So the second point above is no longer a concern, and SomeNumber can now simply be written as

      class SomeNumber:
          def __int__(self):
             <return truncated value for self>

      This decouples int from __trunc__ and leaves __trunc__ as simply the support for the math.trunc function.

    2. mdickinson commented on Aug 22, 2021

      @mdickinson
      MemberAuthor

      This decouples int from __trunc__ and leaves __trunc__ as simply the support for the math.trunc function.

      Argh; copy and paste fail - I left out the crucial line.

      I propose deprecating the delegation of int to __trunc__: calls to int(a) where type(a) implements __trunc__ but not __int__ or __index__ would raise a DeprecationWarning, and at some point in the future int(a) would become a TypeError.

    3. serhiy-storchaka commented on Aug 22, 2021

      @serhiy-storchaka
      Member

      Completely agree.

    4. rhettinger commented on Aug 22, 2021

      @rhettinger
      Contributor

      Afterwards, do __trunc__ and math.trunc() still need to exist?

      They were mostly unused. Now they would also be unnecessary. Just having them around would be a point of confusion.

    5. mdickinson commented on Aug 22, 2021

      @mdickinson
      MemberAuthor

      A GitHub code search shows a substantial number of uses of math.trunc out in the wild:

      https://github.com/search?q=math.trunc+extension%3Apy&type=Code

      So unfortunately, getting rid of math.trunc and __trunc__ looks a bit too much as though it would cause gratuitous breakage.

    6. rhettinger commented on Aug 22, 2021

      @rhettinger
      Contributor

      Possibly, we could have math.trunc() call __int__, letting us deprecate __trunc__.

      That would let users avoid gratuitous aliasing such as that in _pydecimal.py:

         __trunc__ = __int__
    7. serhiy-storchaka commented on Aug 22, 2021

      @serhiy-storchaka
      Member

      I do not think that math.trunc() for UUID or IP4Address makes sense.

    8. mdickinson commented on Aug 22, 2021

      @mdickinson
      MemberAuthor

      I think the needs are sufficiently different that __trunc__ still has value as its own thing, and it's a natural counterpart to __floor__ and __ceil__ (out of all the directed rounding modes, rounding towards zero probably turns up more often than rounding towards +inf or -inf).

      __int__ has the disadvantage that it must return an int, so it's not useful for other Python-based numeric systems with their own rational number / integer pairing. For example, with gmpy2, truncating an mpq instance returns an mpz instance, which is what I'd expect and want - if I'm working with huge values then it would be annoying for math.trunc to do the inefficient thing and return a plain int.

      >>> from gmpy2 import mpq
      >>> math.trunc(mpq(22, 7))
      mpz(3)

      SymPy behaves similarly:

      >>> from sympy import Rational
      >>> type(math.trunc(Rational(22, 7)))
      <class 'sympy.core.numbers.Integer'>

      On the other side, there are conversions to integer that it doesn't make sense to think of as truncation. It would be odd for a UUID to be a valid input to math.trunc, for example:

      >>> int(uuid.uuid4())
      43341414945793370480422623795805641537
    9. rhettinger commented on Aug 22, 2021

      @rhettinger
      Contributor

      I retract the suggestion to deprecate __trunc__.

    10. changed the title [-]Deprecate delegation of int to __trunc__?[/-] [+]Deprecate delegation of int to __trunc__[/+] on Oct 15, 2021
    11. changed the title [-]Deprecate delegation of int to __trunc__?[/-] [+]Deprecate delegation of int to __trunc__[/+] on Oct 15, 2021
    12. ZackerySpytz commented on Jan 31, 2022

      ZackerySpytzmannequin
      Mannequin

      I have created a patch for this issue. Please consider having a look.

    13. serhiy-storchaka commented on Feb 3, 2022

      @serhiy-storchaka
      Member

      New changeset b4bd1e1 by Zackery Spytz in branch 'main':
      bpo-44977: Deprecate delegation of int to __trunc__ (GH-31031)
      b4bd1e1

    14. serhiy-storchaka commented on Feb 3, 2022

      @serhiy-storchaka
      Member

      Thanks Zackery.

    15. transferred this issue fromon Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    No one assigned

      Labels

      3.11only security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions