Inherit parent class attributes, __init__, etc - python

I am trying to use a parent class as a blueprint for new classes.
E.g. the FileValidator contains all generic attributesand methods for a generic file. Then I want to create for example a ImageValidator inheriting everything from the FileValidator but with additional, more specific attribtues, methods. etc. In this example the child class is called: FileValidatorPlus
My understanding was, that if I inherit the parent class I can just plug-in more attributes/methods without repeating anything, like just adding min_size. But the following code gives: TypeError: FileValidatorPlus.__init__() got an unexpected keyword argument 'max_size'
class File:
def __init__(self, file_size=100):
self.file_size = file_size
class FileValidator(object):
error_messages = {'max_size': 'some error msg'}
def __init__(self, max_size=None):
self.max_size = max_size
def __call__(self, file):
print(self.max_size > file.file_size)
class FileValidatorPlus(FileValidator):
error_messages = {'min_size': 'some other error msg'}
def __init__(self, min_size=None):
super(FileValidatorPlus, self).__init__()
self.error_messages.update(super(FileValidatorPlus, self).error_messages)
self.min_size = min_size
validator = FileValidatorPlus(max_size=10, min_size=20)
print(validator.error_messages)
print(validator.max_size)
print(validator.min_size)
Full Traceback:
Traceback (most recent call last):
File "/usr/local/lib/python3.10/code.py", line 90, in runcode
exec(code, self.locals)
File "<input>", line 1, in <module>
TypeError: FileValidatorPlus.__init__() got an unexpected keyword argument 'max_size'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/opt/.pycharm_helpers/pydev/_pydev_bundle/pydev_code_executor.py", line 108, in add_exec
more, exception_occurred = self.do_add_exec(code_fragment)
File "/opt/.pycharm_helpers/pydev/pydevconsole.py", line 90, in do_add_exec
command.run()
File "/opt/.pycharm_helpers/pydev/_pydev_bundle/pydev_console_types.py", line 35, in run
self.more = self.interpreter.runsource(text, '<input>', symbol)
File "/usr/local/lib/python3.10/code.py", line 74, in runsource
self.runcode(code)
File "/usr/local/lib/python3.10/code.py", line 94, in runcode
self.showtraceback()
File "/usr/local/lib/python3.10/code.py", line 148, in showtraceback
sys.excepthook(ei[0], ei[1], last_tb)
File "/opt/.pycharm_helpers/pydev/pydevconsole.py", line 112, in info
traceback.print_exception(type, value, tb)
NameError: name 'traceback' is not defined
Traceback (most recent call last):
File "/opt/.pycharm_helpers/pydev/pydevconsole.py", line 284, in process_exec_queue
interpreter.add_exec(code_fragment)
File "/opt/.pycharm_helpers/pydev/_pydev_bundle/pydev_code_executor.py", line 132, in add_exec
return more, exception_occurred
UnboundLocalError: local variable 'exception_occurred' referenced before assignment
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/opt/.pycharm_helpers/pydev/pydevconsole.py", line 511, in <module>
pydevconsole.start_server(port)
File "/opt/.pycharm_helpers/pydev/pydevconsole.py", line 407, in start_server
process_exec_queue(interpreter)
File "/opt/.pycharm_helpers/pydev/pydevconsole.py", line 292, in process_exec_queue
traceback.print_exception(type, value, tb, file=sys.__stderr__)
UnboundLocalError: local variable 'traceback' referenced before assignment
Process finished with exit code 1

You need to add max_size as a parameter in your FileValidatorPlus constructor.
If you want FileValidatorPlus to inherit this field from the super's constructor, you must not define a __init__ method.
In other words, if you want FileValidatorPlus to inherit max_size parameter from FileValidator, you should delete __init__ because the subclass only inherits constructor properties when they don't have their own constructor.
But in your case I think that it would be a better solution just to add min_size=None to FileValidatorPlus.__init__:
def __init__(self, max_size=None, min_size=None):
super(FileValidatorPlus, self).__init__(max_size)

I got also different error :
TypeError: __init__() got an unexpected keyword argument 'max_size'
and the solution would be :
def __init__(self, max_size=None, min_size=None):
super(FileValidatorPlus, self).__init__(max_size)
Output:
{'min_size': 'some other error msg', 'max_size': 'some error msg'}
10
20

Related

marshmallow NewType can not be turned into a dataclass, python 3.10

I'm in the process of upgrading to python 3.10 and in that context I thought it would be nice to also upgrade packages used. Right now, the problem is with the marshmallow packages and at this point I can't even run their example code for NewType anymore.
This is my code (taken from the comment in the NewType definition):
from marshmallow_dataclass import NewType, dataclass, List
import marshmallow.validate
IPv4 = NewType('IPv4', str, validate=marshmallow.validate.Regexp(r'^([0-9]{1,3}\\.){3}[0-9]{1,3}$'))
#dataclass
class MyIps:
ips: List[IPv4]
MyIps.Schema().load({"ips": ["0.0.0.0", "grumble grumble"]})
I only added the first line to have the necessary commands available.
When I run this I receive the following error-message:
/home/username/.local/share/virtualenvs/venv_3.10/lib/python3.10/site-packages/marshmallow_dataclass/__init__.py:373: UserWarning: ****** WARNING ****** marshmallow_dataclass was called on the class <function NewType.<locals>.new_type at 0x7fb5a077fd90>, which is not a dataclass. It is going to try and convert the class into a dataclass, which may have undesirable side effects. To avoid this message, make sure all your classes and all the classes of their fields are either explicitly supported by marshmallow_dataclass, or define the schema explicitly using field(metadata=dict(marshmallow_field=...)). For more information, see https://github.com/lovasoa/marshmallow_dataclass/issues/51 ****** WARNING ******
warnings.warn(
Traceback (most recent call last):
File "/usr/lib/python3.10/dataclasses.py", line 1197, in fields
fields = getattr(class_or_instance, _FIELDS)
AttributeError: 'function' object has no attribute '__dataclass_fields__'. Did you mean: '__dataclass_params__'?
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/username/.local/share/virtualenvs/venv_3.10/lib/python3.10/site-packages/marshmallow_dataclass/__init__.py", line 370, in _internal_class_schema
fields: Tuple[dataclasses.Field, ...] = dataclasses.fields(clazz)
File "/usr/lib/python3.10/dataclasses.py", line 1199, in fields
raise TypeError('must be called with a dataclass type or instance')
TypeError: must be called with a dataclass type or instance
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/username/.local/share/virtualenvs/venv_3.10/lib/python3.10/site-packages/marshmallow_dataclass/__init__.py", line 384, in _internal_class_schema
created_dataclass: type = dataclasses.dataclass(clazz)
File "/usr/lib/python3.10/dataclasses.py", line 1185, in dataclass
return wrap(cls)
File "/usr/lib/python3.10/dataclasses.py", line 1176, in wrap
return _process_class(cls, init, repr, eq, order, unsafe_hash,
File "/usr/lib/python3.10/dataclasses.py", line 909, in _process_class
for b in cls.__mro__[-1:0:-1]:
AttributeError: 'function' object has no attribute '__mro__'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/username/testscript.python", line 9, in <module>
MyIps.Schema().load({"ips": ["0.0.0.0", "grumble grumble"]})
File "/home/username/.local/share/virtualenvs/venv_3.10/lib/python3.10/site-packages/marshmallow_dataclass/lazy_class_attribute.py", line 33, in __get__
setattr(cls, self.name, self.func())
File "/home/username/.local/share/virtualenvs/venv_3.10/lib/python3.10/site-packages/marshmallow_dataclass/__init__.py", line 356, in class_schema
return _internal_class_schema(clazz, base_schema, clazz_frame)
File "/home/username/.local/share/virtualenvs/venv_3.10/lib/python3.10/site-packages/marshmallow_dataclass/__init__.py", line 402, in _internal_class_schema
attributes.update(
File "/home/username/.local/share/virtualenvs/venv_3.10/lib/python3.10/site-packages/marshmallow_dataclass/__init__.py", line 405, in <genexpr>
field_for_schema(
File "/home/username/.local/share/virtualenvs/venv_3.10/lib/python3.10/site-packages/marshmallow_dataclass/__init__.py", line 695, in field_for_schema
generic_field = _field_for_generic_type(typ, base_schema, typ_frame, **metadata)
File "/home/username/.local/share/virtualenvs/venv_3.10/lib/python3.10/site-packages/marshmallow_dataclass/__init__.py", line 503, in _field_for_generic_type
child_type = field_for_schema(
File "/home/username/.local/share/virtualenvs/venv_3.10/lib/python3.10/site-packages/marshmallow_dataclass/__init__.py", line 729, in field_for_schema
or _internal_class_schema(typ, base_schema, typ_frame)
File "/home/username/.local/share/virtualenvs/venv_3.10/lib/python3.10/site-packages/marshmallow_dataclass/__init__.py", line 387, in _internal_class_schema
raise TypeError(
TypeError: IPv4 is not a dataclass and cannot be turned into one.
My current install is python 3.10.6 and marshmallow_dataclasses 8.5.8. (The code was working with python 3.9 and marshmallow dataclasses 8.3.0)
Does anyone know why this is happening and how to solve this (other than downgrading, obviously)
Does anyone else have this issue? Is this new behaviour and I should adapt our code (if so, how?)? Is this a bug?
I've had a similar issue with a similar bit of code that is raising an error since trying to upgrade marshmallow_dataclasses.
import dataclasses
import marshmallow_dataclass
ARGON2_PASSWORD = marshmallow_dataclass.NewType(
"ARGON2_PASSWORD",
str,
validate=validate.Regexp(
r"[$]argon2(?:id|i)[$]v=\d{1,3}[$]m=\d{3,20},t=\d{1,4},"
r"p=\d{1,2}[$][^$]{1,100}[$][^$]{1,768}"))
#marshmallow_dataclass.add_schema
#dataclasses.dataclass
class Argon2Password:
password: ARGON2_PASSWORD
The detailed root cause is currently discussed in https://github.com/lovasoa/marshmallow_dataclass/issues/206 afaics.
For the time being, downgrading to typing-inspect==0.7.1 worked for me as a hotfix.

twitterImgBot stops working after some hours

I'm trying to get this, https://github.com/joaquinlpereyra/twitterImgBot, to work
and it works and it seems ok.
But after some hours, it stops working and this error comes up:
*python3 twitterbot.py
Traceback (most recent call last):
File "/home/user/.local/lib/python3.7/site-packages/tweepy/binder.py", line 118, in build_path
value = quote(self.session.params[name])
KeyError: 'id'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "twitterbot.py", line 209, in <module>
main()
File "twitterbot.py", line 200, in main
orders()
File "twitterbot.py", line 118, in orders
timeline.delete_tweet_by_id(tweet.in_reply_to_status_id, api)
File "/home/user/Skrivebord/twitterboot/lo/bot/timeline.py", line 12, in delete_tweet_by_id
api.destroy_status(id_to_delete)
File "/home/user/.local/lib/python3.7/site-packages/tweepy/binder.py", line 245, in _call
method = APIMethod(args, kwargs)
File "/home/user/.local/lib/python3.7/site-packages/tweepy/binder.py", line 71, in __init__
self.build_path()
File "/home/user/.local/lib/python3.7/site-packages/tweepy/binder.py", line 120, in build_path
raise TweepError('No parameter value found for path variable: %s' % name)
tweepy.error.TweepError: No parameter value found for path variable: id*
It seems like the Python has some problem because if I make a new install on a another PC it works for some hours and then stops.
Strange.
This is likely because tweet is not in reply to a status, so has an in_reply_to_status_id attribute that's None, so API.destroy_status is called with an id of None.

"StopIteration" exception while using factory_boy in django setUp() unittest

I have the following factory:
class ContactFactory(DjangoModelFactory):
name = Faker('company')
industry = Iterator(Industry.objects.all())
class Meta:
model = 'sales.contact'
#post_generation
def requested_devices(self, create, extracted, **kwargs):
if create:
self.requested_devices.add(MSize.objects.first())
And I'm trying to write a test such as:
class TestUserCanAskQuestion(TestCase):
#classmethod
def setUpTestData(cls):
call_command('insert_initial_data')
def setUp(self):
self.contact = ContactFactory()
But everytime I run the test, it results in "StopIteration" error.
Here is the full stack trace:
ERROR: test_dummy (comminquiry.tests.test_views.TestUserCanAskQuestion)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/mnt/c/Users/Alire/Projects/mm/mm-bpmui/src/comminquiry/tests/test_views.py", line 32, in test_dummy
a = ContactFactory.build()
File "/mnt/c/Users/Alire/Projects/mm/venv/lib/python3.5/site-packages/factory/base.py", line 546, in build
return cls._generate(enums.BUILD_STRATEGY, kwargs)
File "/mnt/c/Users/Alire/Projects/mm/venv/lib/python3.5/site-packages/factory/base.py", line 500, in _generate
return step.build()
File "/mnt/c/Users/Alire/Projects/mm/venv/lib/python3.5/site-packages/factory/builder.py", line 272, in build
step.resolve(pre)
File "/mnt/c/Users/Alire/Projects/mm/venv/lib/python3.5/site-packages/factory/builder.py", line 221, in resolve
self.attributes[field_name] = getattr(self.stub, field_name)
File "/mnt/c/Users/Alire/Projects/mm/venv/lib/python3.5/site-packages/factory/builder.py", line 375, in __getattr__
extra=context,
File "/mnt/c/Users/Alire/Projects/mm/venv/lib/python3.5/site-packages/factory/declarations.py", line 196, in evaluate
value = next(iter(self.iterator))
File "/mnt/c/Users/Alire/Projects/mm/venv/lib/python3.5/site-packages/factory/utils.py", line 136, in __iter__
value = next(self.iterator)
StopIteration
----------------------------------------------------------------------
Ran 1 test in 2.433s
If I move the ContactFactory() outside of class, the error disappears.
I'm I missing something? or it's a bug in factory boy or django?
(I'm using factory_boy==2.11.1 and django==2.1.2)
As #dirkgroten had suggested, one the fields was returning an empty queryset. This was the root cause of the error.

Can't use class constructor argument in Python

I can't get what I'm doing wrong here. I'm defining a class with the following code:
import sqlite3 as lite
import sys
import os.path
class database:
def __init__(self,dbfname):
if os.path.isfile(dbfname):
self.con = lite.connect(dbfname)
else:
self.con = self.createDBfile(dbfname)
#Other methods...
Then, when I try to make an instance of the class
base = database("mydb.db")
I get an error saying that there is no "global" variable named dbfname .
Traceback (most recent call last):
File "testdb.py", line 67, in <module>
base = database("mydb.db")
File "testdb.py", line 13, in __init__
self.con = self.createDBfile(dbfname)
File "testdb.py", line 15, in createDBfile
if os.path.isfile(dbfname):
NameError: global name 'dbfname' is not defined
What would be the correct way to use the argument variable dbfname ?
This code looks fine. The error isn't in the code you posted though; it's in testdb.py on line 15 in the createDBfile() method (not in the __init__()).
How do I know this? Well, lets carefully look at the traceback Python gives us:
Traceback (most recent call last):
File "testdb.py", line 67, in <module>
base = database("mydb.db")
File "testdb.py", line 13, in __init__
self.con = self.createDBfile(dbfname)
File "testdb.py", line 15, in createDBfile
if os.path.isfile(dbfname):
NameError: global name 'dbfname' is not defined
Like the first line says, the most recent call is last. So you read a traceback from down to up (and not from up to down).
The very last line is the actual error, but just before that is:
File "testdb.py", line 15, in createDBfile
if os.path.isfile(dbfname):
So it says that in the file testdb.py, on line 15, in the method createDBfile() an error occurred. Python also prints out the contents of this line 15.
Above that is the call to the createDBfile() method in your __init__() function, and above that the call to the __init__() function (by creating the class instance).
You didn't post the contents of this createDBfile() method, so I can't tell you where exactly the error is. I suspect you did something wrong with the function arguments (perhaps as simple as a typo?)

Dynamically alter traceback/stack frame function name

From time to time, I write a generic function in Python that gets called multiple times with different arguments. Usually, this is driven by a definition somewhere else.
For example:
def issue_sql_query(name, select_stmt):
...
QUERIES = [
"get_user_rows", "SELECT name, rowid FROM table WHERE type == 'USER';"
...
]
results = []
for name, select_stmt in QUERIES:
results.append((name, issue_sql_query(name, select_stmt)))
If there's an exception in the generic function (i.e., issue_sql_query or somewhere deeper), I have relatively little info in the traceback to identify which definition caused the error.
What I'd like to do is dynamically rename or augment the function name/stack frame so that tracebacks would include some identifying info.
What would be nice is something like this:
File "test.py", line 21, in <module>
results.append((name, issue_sql_query(select_stmt)))
File "test.py", line 11, in issue_sql_query(name="get_user_rows")
raise RuntimeError("Some error")
RuntimeError: Some error
I could, of course, stick exception handling at the generic points and rebuild the exception using traceback to have more context, which is pretty straightforward and likely the right choice. It gets a little tricky when you have multiple levels of generic functions, but that's certainly possible to handle.
Any other ideas on how to accomplish this? Did I miss some easy way to change the stack frame name?
Edit:
Adding an example traceback showing a relatively not useful traceback:
Traceback (most recent call last):
File "C:\Python27\lib\runpy.py", line 162, in _run_module_as_main
"__main__", fname, loader, pkg_name)
File "C:\Python27\lib\runpy.py", line 72, in _run_code
exec code in run_globals
File "c:\tmp\report.py", line 767, in <module>
main()
File "c:\tmp\report.py", line 750, in main
charts.append(report.get_chart(title, definition))
File "c:\tmp\report.py", line 614, in get_chart
return self.get_bar_chart(title, definition)
File "c:\tmp\report.py", line 689, in get_bar_chart
definition, cursor, **kwargs))
File "c:\tmp\report.py", line 627, in create_key_table
for row in cursor.execute(full_select_stmt):
sqlite3.OperationalError: near "==": syntax error
You could create wrapper functions for each named query so that you can control the exception thrown:
>>> fns = {}
>>> def issue_sql_query(name, stmt):
... if name not in fns:
... def f(name, stmt):
... # run query here
... raise Exception(name)
...
... fns[name] = f
... return fns[name](name, stmt)
...
>>>
>>> issue_sql_query('b', 'SQL')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 9, in issue_sql_query
File "<stdin>", line 5, in f
Exception: b
>>> issue_sql_query('a', 'SQL')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 9, in issue_sql_query
File "<stdin>", line 5, in f
Exception: a
>>>

Categories