Pylint super constructor doesn't trigger E1120 - python-3.x

Pylint has an existing error E1120 which will trigger when a value is missing from a constructor. This, however, doesn't trigger in inheritance. For example, look at this:
class Parent(object):
def __init__(self, x):
self.x = x
class Child(Parent):
def __init__(self):
super().__init__()
if __name__ == "__main__":
c = Child()
p = Parent()
As you can see, the Parent class constructor takes an argument x but the Child, which inherits from it, is not passing in anything.
If we run pylint --errors-only X.py just for the errors we get this one:
X.py 13:8: E1120: No value for argument 'x' in constructor call (no-value-for-parameter)
This is for the direct call to Parent() at the end of the file. There is no error generated from the instantiation of Child() nor from call to super().__init__() which is an error. Specifically, running this directly with python results in:
Traceback (most recent call last):
File "X.py", line 12, in <module>
c = Child()
File "X.py", line 8, in __init__
super().__init__()
TypeError: __init__() missing 1 required positional argument: 'x'
Therefore I would expect pylint to catch this as an error. Am I missing something? Or is this an issue in pylint?
Relevant versions:
pylint 2.1.1
astroid 2.0.4
Python 3.5.2 (default, Nov 23 2017, 16:37:01)

Related

Class assignment: object not callable [duplicate]

As a starting developer in Python I've seen this error message many times appearing in my console but I don't fully understand what does it means.
Could anyone tell me, in a general way, what kind of action produces this error?
That error occurs when you try to call, with (), an object that is not callable.
A callable object can be a function or a class (that implements __call__ method). According to Python Docs:
object.__call__(self[, args...]): Called when the instance is “called” as a function
For example:
x = 1
print x()
x is not a callable object, but you are trying to call it as if it were it. This example produces the error:
TypeError: 'int' object is not callable
For better understaing of what is a callable object read this answer in another SO post.
The other answers detail the reason for the error. A possible cause (to check) may be your class has a variable and method with the same name, which you then call. Python accesses the variable as a callable - with ().
e.g. Class A defines self.a and self.a():
>>> class A:
... def __init__(self, val):
... self.a = val
... def a(self):
... return self.a
...
>>> my_a = A(12)
>>> val = my_a.a()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
>>>
The action occurs when you attempt to call an object which is not a function, as with (). For instance, this will produce the error:
>>> a = 5
>>> a()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
Class instances can also be called if they define a method __call__
One common mistake that causes this error is trying to look up a list or dictionary element, but using parentheses instead of square brackets, i.e. (0) instead of [0]
The exception is raised when you try to call not callable object. Callable objects are (functions, methods, objects with __call__)
>>> f = 1
>>> callable(f)
False
>>> f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
I came across this error message through a silly mistake. A classic example of Python giving you plenty of room to make a fool of yourself. Observe:
class DOH(object):
def __init__(self, property=None):
self.property=property
def property():
return property
x = DOH(1)
print(x.property())
Results
$ python3 t.py
Traceback (most recent call last):
File "t.py", line 9, in <module>
print(x.property())
TypeError: 'int' object is not callable
The problem here of course is that the function is overwritten with a property.

Why can't I pickle my custom exception in Python

I am using Python 3.6. I defined a custom exception following this page: https://docs.python.org/3.6/tutorial/errors.html
class MyException(Exception):
def __init__(self, a):
self.a = a
Now, if I try to pickle + unpickle this exception, I get the following error:
>> e = MyException(a=1); pickle.loads(pickle.dumps(e))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-44-413e2ac6234d> in <module>
----> 1 e = MyException(a=1); pickle.loads(pickle.dumps(e))
TypeError: __init__() missing 1 required positional argument: 'a'
Does anyone know why?
Seems to be that the Exception baseclass has special treatment for named arguments (likely in its implementation of __new__)
you can fix this by properly calling the base class in your __init__ method:
>>> class MyException(Exception):
... def __init__(self, a):
... super().__init__(a)
... self.a = a
...
>>> pickle.loads(pickle.dumps(MyException(a=1)))
MyException(1,)

multiprocessing.Pool cannot return OrderedDict subclass with additional argument

I am trying to have a simple subclass of OrderedDict that gets created by a Pool then returned.
It seems that the pickling process when returning the created object to the pool tries to re-instantiate the object and fails due to the required additional argument in the __init__ function.
This is a minimal (non) working example:
from collections import OrderedDict
from multiprocessing import Pool
class Obj1(OrderedDict):
def __init__(self, x, *args, **kwargs):
super().__init__(*args, **kwargs)
self.x = x
def task(x):
obj1 = Obj1(x)
return obj1
if __name__ == '__main__':
with Pool(1) as pool:
for x in pool.imap_unordered(task, (1,2,3)):
print(x.x)
If I do this I get the following error.
Exception in thread Thread-3:
Traceback (most recent call last):
File "/usr/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run()
File "/usr/lib/python3.6/threading.py", line 864, in run
self._target(*self._args, **self._kwargs)
File "/usr/lib/python3.6/multiprocessing/pool.py", line 463, in _handle_results
task = get()
File "/usr/lib/python3.6/multiprocessing/connection.py", line 251, in recv
return _ForkingPickler.loads(buf.getbuffer())
TypeError: init() missing 1 required positional argument: 'x'
Again this fails when the task functions returns to the pool and I guess the object gets pickled?
If I changed OrderedDict by a simple dict it works flawlessly....
I have a workaround to use kwargs and retrieve the attribute of interest but I am stumped about the error to start with. Any ideas?
You can define __getstate__() and __setstate__() methods for your class.
In those functions you can make sure that x is handled as well. For example:
def __getstate__(self):
return self.x, self.items()
def __setstate__(self, state):
self.x = state[0]
self.update(state[1])
BTW, from CPython 3.6 there is no reason to use OrderedDict, since dictionary order is insertion order. This was originally an implementation detail in CPython. In Python 3.7 it was made part of the language.

SQLAlchemy 1.2 AttributeError: 'list' object has no attribute 'Session'

I was trying to use the code snippet from this tutorial:
http://newcoder.io/scrape/part-4/
The following is the file with the class definition:
from sqlalchemy.orm import sessionmaker
from .models import Deals, db_connect, create_deals_table
class Test(object):
def __init__(self, args):
"""
Initializes database connection and sessionmaker.
Creates deals table.
"""
engine = db_connect()
create_deals_table(engine)
self.Session = sessionmaker(bind=engine)
def add_item(self):
session = self.Session()
tester = Deals(title="test 3 deal",location='here', price=2.00)
session.add(tester)
session.commit()
When I call Test.add_item(args), the following error is generated.
(sql) [bucket#localhost heap]$ python heap.py test Traceback (most
recent call last): File "heap.py", line 13, in <module>
main(sys.argv) File "heap.py", line 8, in main
Test.add_item(args) File "/home/bucket/src/heap/game/engine.py", line 17, in add_item
session = self.Session() AttributeError: 'list' object has no attribute 'Session'
The code worked fine and added a row when I ran the the same code as a python script with no class definition.
You're trying to call an instance method on the class itself: Test.add_item(args)
You define the method as only having self and no parameters. This means that you need to call it on an instance of the class, and pass it no arguments
test = Test()
test.add_item()
The reason you're getting that particular error is because you're calling the function with the list argument args getting used as the parameter self, and then the self.Session() line is attempting to get the attribute Session from the args object. You need to fix either the method definition or your call to it (e.g., def add_item(self, args):)

python3 object has no attriubute

I have a file called entities.py, which contains the following code:
class EntityClass:
entities = {}
def __init__(self, parent=None):
.......
def show_all(self):
......
But then, when I run python 3 and type the command as follows:
>>> import entities
>>> ent = entities.EntityClass()
>>> ent.show_all()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'EntityClass' object has no attribute 'show_all'
show_all should clearly be an attribute for EntityClass.
This of course worked perfectly in Python 2, and I'm assuming it's a Python 3 issue...
Is there a work around for this?
From the code posted, it looks like your indentation levels are wrong, you have declared the show_all() method on the module, not the class.
def_show_all(self): Should be indented to the same level as entities = {}
class EntityClass:
entities ={}
def __init__(self,parent=None):
.......
def show_all(self):
......

Resources