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

Misleading error from type() when passing unknown keyword argument #61381

Closed
cjw296 opened this issue Feb 11, 2013 · 10 comments
Closed

Misleading error from type() when passing unknown keyword argument #61381

cjw296 opened this issue Feb 11, 2013 · 10 comments
Labels
docs Documentation in the Doc dir easy stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@cjw296
Copy link
Contributor

cjw296 commented Feb 11, 2013

BPO 17179
Nosy @terryjreedy, @ncoghlan, @cjw296, @merwok, @durban, @iritkatriel

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-12-06.00:07:05.660>
created_at = <Date 2013-02-11.08:26:41.175>
labels = ['easy', 'type-bug', 'library', 'docs']
title = 'Misleading error from type() when passing unknown keyword argument'
updated_at = <Date 2021-12-06.00:07:05.656>
user = 'https://github.com/cjw296'

bugs.python.org fields:

activity = <Date 2021-12-06.00:07:05.656>
actor = 'iritkatriel'
assignee = 'docs@python'
closed = True
closed_date = <Date 2021-12-06.00:07:05.660>
closer = 'iritkatriel'
components = ['Documentation', 'Library (Lib)']
creation = <Date 2013-02-11.08:26:41.175>
creator = 'cjw296'
dependencies = []
files = []
hgrepos = []
issue_num = 17179
keywords = ['easy']
message_count = 10.0
messages = ['181884', '182064', '182065', '182118', '182142', '182175', '182211', '182304', '182310', '406936']
nosy_count = 8.0
nosy_names = ['terry.reedy', 'ncoghlan', 'cjw296', 'eric.araujo', 'daniel.urban', 'docs@python', 'Ramchandra Apte', 'iritkatriel']
pr_nums = []
priority = 'normal'
resolution = 'out of date'
stage = 'resolved'
status = 'closed'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue17179'
versions = ['Python 3.3', 'Python 3.4']

@cjw296
Copy link
Contributor Author

cjw296 commented Feb 11, 2013

>>> from types import new_class
>>> from datetime import datetime
>>> new_class('tdatetime', (datetime, ), kwds={'foo':'bar'})
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/src/Python-3.3.0/Lib/types.py", line 52, in new_class
    return meta(name, bases, ns, **kwds)
TypeError: type() takes 1 or 3 arguments

I'm guessing ns and kwds should be combined before being passed through to meta? (meta is 'type' in this case)

@cjw296 cjw296 added the stdlib Python modules in the Lib dir label Feb 11, 2013
@merwok merwok added the easy label Feb 13, 2013
@merwok merwok changed the title TypeError: type() takes 1 or 3 arguments Incorrect use of type function in types.new_class Feb 13, 2013
@cjw296
Copy link
Contributor Author

cjw296 commented Feb 13, 2013

Eric, surely this is a bugfix candidate for 3.3.1?

@merwok
Copy link
Member

merwok commented Feb 13, 2013

I'm guessing ns and kwds should be combined before being passed through to meta?
Possibly; can you try that?

surely this is a bugfix candidate for 3.3.1?
If we get a patch with a test in time, otherwise 3.3.2.

@durban
Copy link
Mannequin

durban mannequin commented Feb 14, 2013

I don't think this is a bug:

>>> from datetime import datetime
>>> class tdatetime(datetime, foo='bar'):
...     pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: type() takes 1 or 3 arguments
>>>

@RamchandraApte
Copy link
Mannequin

RamchandraApte mannequin commented Feb 15, 2013

@daniel Urban
Me too.

@RamchandraApte RamchandraApte mannequin added the type-bug An unexpected behavior, bug, or error label Feb 15, 2013
@terryjreedy
Copy link
Member

As far as I know, currently, the only valid 'keyword' argument for a class statement is 'metaclass' and that is so advanced that it is not mentioned in *8.7. Class definitions* but only in the linked section *3.3.3. Customizing class creation*. The types.newclass doc also only mentions 'metaclass' as a possible keyword. (Maybe it should currently say that that is the only possibility, but perhaps the window was being left open for possible additions in the future.) So I agree that passing anything else is a bug and should raise. If so, this issue should be closed.

@ncoghlan
Copy link
Contributor

The types.new_class docs are quite clear that the supplied keyword arguments are equivalent to those provided in the type header (if you want to pre-populate the namespace, that's what exec_body is for). The problem here is that the dual signature of type (retrieving the type of an existing object, or creating a new one), and the fact that type.__prepare__ ignores all arguments, means the error message is thoroughly misleading when you pass an unknown keyword argument:

>>> type.__prepare__(foo=1)
{}
>>> type("Example", (), {}, foo=1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: type() takes 1 or 3 arguments

>>> class Example(foo=1): pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: type() takes 1 or 3 arguments

>>> import types
>>> types.new_class("Example", (), dict(foo=1))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ncoghlan/devel/py3k/Lib/types.py", line 52, in new_class
    return meta(name, bases, ns, **kwds)
TypeError: type() takes 1 or 3 arguments

The reason type.__prepare__ ignores its arguments is to make it easy for people to use type to anchor a custom metaclass hierarchy and call super().__prepare__(name, bases, **kwds) without needing to worry much about filtering the keyword arguments. (The class machinery intercepts the metaclass hint and never passes it to __prepare__ or the metaclass constructor).

That means the real change needed here is to update type's error message for bad arguments to properly report unknown keyword errors when using the PEP-3115 metaclass API.

@ncoghlan ncoghlan added the docs Documentation in the Doc dir label Feb 16, 2013
@ncoghlan ncoghlan changed the title Incorrect use of type function in types.new_class Misleading error from type() when passing unknown keyword argument Feb 16, 2013
@cjw296
Copy link
Contributor Author

cjw296 commented Feb 18, 2013

Some background: I hit this problem when adding Python 3 compatibility
to one of my libraries, where I had the following code:

from types import ClassType
...
class_ = ClassType(n, (sometype, ), dict(class_attr1='foo', 
class_attr2='bar')

It wasn't at all clear how to port this to Python 3, given that
ClassType was gone.

types.new_class looks fair game, but the help is not exactly helpful:

new_class(name, bases=(), kwds=None, exec_body=None)
Create a class object dynamically using the appropriate metaclass.

No indication there as to what type should be passed for kwds or exec_body.

I guessed and, by the sound of it, guessed wrong.
I'd certainly agree that the error message is very misleading.

cheers,

Chris

@ncoghlan
Copy link
Contributor

For the simple case where you don't need to provide a metaclass hint, the simplest conversion is actually directly to the 3-argument form of type().

As far as the docstring goes, I don't want to make it as long as the full docs, but it could probably stand to be longer than it is.

@iritkatriel
Copy link
Member

This seems to have been fixed by now. I get this on 3.11:

>>> from types import new_class
>>> from datetime import datetime
>>> new_class('tdatetime', (datetime, ), kwds={'foo':'bar'})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/iritkatriel/src/cpython-1/Lib/types.py", line 77, in new_class
    return meta(name, resolved_bases, ns, **kwds)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: tdatetime.__init_subclass__() takes no keyword arguments

@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
docs Documentation in the Doc dir easy stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

5 participants