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

__class__ assignment error message confusing #48850

Closed
terryjreedy opened this issue Dec 8, 2008 · 6 comments
Closed

__class__ assignment error message confusing #48850

terryjreedy opened this issue Dec 8, 2008 · 6 comments
Labels
3.11 only security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error

Comments

@terryjreedy
Copy link
Member

BPO 4600
Nosy @terryjreedy, @benjaminp, @aroberge, @merwok, @Trundle, @jonashaag, @florentx, @iritkatriel
Files
  • 4600.diff
  • 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 2021-07-05.17:46:03.217>
    created_at = <Date 2008-12-08.21:25:21.926>
    labels = ['interpreter-core', 'type-bug', '3.11']
    title = '__class__ assignment error message confusing'
    updated_at = <Date 2021-07-05.19:15:08.837>
    user = 'https://github.com/terryjreedy'

    bugs.python.org fields:

    activity = <Date 2021-07-05.19:15:08.837>
    actor = 'terry.reedy'
    assignee = 'none'
    closed = True
    closed_date = <Date 2021-07-05.17:46:03.217>
    closer = 'terry.reedy'
    components = ['Interpreter Core']
    creation = <Date 2008-12-08.21:25:21.926>
    creator = 'terry.reedy'
    dependencies = []
    files = ['20937']
    hgrepos = []
    issue_num = 4600
    keywords = ['patch']
    message_count = 6.0
    messages = ['77343', '77381', '129643', '129646', '396989', '397017']
    nosy_count = 9.0
    nosy_names = ['terry.reedy', 'benjamin.peterson', 'aroberge', 'stutzbach', 'eric.araujo', 'Trundle', 'jonash', 'flox', 'iritkatriel']
    pr_nums = []
    priority = 'normal'
    resolution = 'out of date'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue4600'
    versions = ['Python 3.11']

    @terryjreedy
    Copy link
    Member Author

    ob.__class__ = ob2
    gives some confusing TypeError messages.
    >>> c.__class__ = 1
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: __class__ must be set to new-style class, not 'int' object

    Problem: 'new-style' is obsolete in 3.0. It is also too inclusive...

    >>> c.__class__ = object
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: __class__ assignment: only for heap types

    object *is* 'new-style'. I presume 'heap type' means 'class defined by
    class statement'. If so, let us say so, since beginning programmers may
    not know what a 'heap type' is. If the above is incorrect, then this
    experienced programmer also does not know what it means in Python
    context ;-).

    Proposal: when someone tries to set __class__ to an inappropriate
    object, give similar error message for instances and heap classes.

    TypeError: __class__ must be set to a class defined by a class
    statement, not 'xxx' [object].

    where 'object', without the brackets, is added for non-classes, as it is
    today.

    >>> c.__class__ = object
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: __class__ assignment: only for heap types

    C, the class of c, *is* a heap type. The different problem, the target
    being an instance of heap class, should get a different message. 'Heap'
    is still possibly confusing. Proposal:

    TypeError: __class__ assignment: only for instances of classes defined
    by class statements.

    @terryjreedy terryjreedy added interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error labels Dec 8, 2008
    @terryjreedy
    Copy link
    Member Author

    Related issue that applies to recent 2.x. Language/data model/Objects,
    values, and types says 'An object’s type is also unchangeable.'. This
    should be changed or deleted.

    @jonashaag
    Copy link
    Mannequin

    jonashaag mannequin commented Feb 27, 2011

    Here comes a patch, changing the behaviour to:

    ./python -q
    >>> class C:
    ...   pass
    ... 
    >>> (1).__class__ = 1
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: __class__ must be set to a class defined by a class statement, not 'int' object
    >>> (1).__class__ = object
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: class__ must be set to a class defined by a class statement, not 'object'
    >>> (1).__class__ = C
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: __class__ assignment: only for instances of classes defined by class statements

    @benjaminp
    Copy link
    Contributor

    This is not really accurate:

    >>> class x(int): pass
    ... 
    >>> class y(object): pass
    ... 
    >>> x().__class__ = y
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: __class__ assignment: 'x' object layout differs from 'y'
    >>> y().__class__ = x
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: __class__ assignment: 'y' object layout differs from 'x'

    @iritkatriel
    Copy link
    Member

    The error messages are different now:

    >>> class C: pass
    ...
    >>> c = C()
    >>> c.__class__ = 1
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: __class__ must be set to a class, not 'int' object
    >>> c.__class__ = object
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: __class__ assignment only supported for mutable types or ModuleType subclasses
    >>>

    @terryjreedy
    Copy link
    Member Author

    I neglected to mention above what c is. I Irit guessed right as

    >>> class C: pass
    ... 
    >>> c = C()

    is what I (also) usually do for examples and testing.

    Removing "new-style" elsewhere solved the issue with the error message for "ob.__class__ = non_class_object". The new error message for "ob.__class__ = someclass" replaces 'heap' with 'mutable'. But it can still be confusing as the qualification in

    __class__ assignment only supported for mutable types or ModuleType subclasses

    applies to both type(ob) and someclass and the same error is given if either does not qualify. The use of the plural 'types' allows but does not mandate this interpretation. Also, "mutable types" means that the types are mutable, not their instances. Although 'list' is sometimes referred to as a 'mutable type' because its instances are, 'list' itself is not mutable and does not qualify here.

    I am closing this issue, which is about the error message, because the new message is accurate when understood. I cannot think of any better one-line message. Explaining the background needed to understand should be done elsewhere.

    Andre, I nosied you in case the above would help you improve Friendly's explanation of this error. I was a bit confused myself until I did more experiments.

    Note: Even when type(ob) and someclass both 'qualify', the assignment will fail if instances are 'incompatible'. Let M be a subclass of types.ModuleType.

    c.__class__ = M  # fails with

    TypeError: __class__ assignment: 'M' object layout differs from 'C'

    The difference is obvious by looking as dir(c) and dir(M('somename')).

    @terryjreedy terryjreedy added the 3.11 only security fixes label Jul 5, 2021
    @terryjreedy terryjreedy changed the title __class__ assignment: new-style? heap? == confusing __class__ assignment error message confusing Jul 5, 2021
    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.11 only security fixes interpreter-core (Objects, Python, Grammar, and Parser dirs) type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    3 participants