Problem updating Locust script to 1.x: TypeError: __init__() takes 1 positional argument but 2 were given - locust

Having changed (0.x style)
class MyBaseLocust(Locust):
def __init__(self):
super(MyLocust, self).__init__()
to (1.x style)
class MyBaseUser(User):
def __init__(self):
super(MyBaseUser, self).__init__()
I get:
[2020-07-17 14:16:33,694] XXX/CRITICAL/locust.runners: Unhandled exception in greenlet: <Greenlet at 0x28639396378: <lambda>>
Traceback (most recent call last):
...
in spawn_users
hatch()
File "c:\venv\project\lib\site-packages\locust\runners.py", line 165, in hatch
new_user = user_class(self.environment)
TypeError: __init__() takes 1 positional argument but 2 were given
(this has been asked a couple of times so I thought I'd add it here)

Here’s how it should be in 1.x
class MyBaseUser(HttpUser):
abstract = True
def __init__(self, parent):
super().__init__(parent)
(the main thing is the added parent parameter, but abstract is needed to avoid registering the base user as something that should be executed)

Related

How to define a recursive Iterable type?

I am trying to define a recursive Iterable type Iterable_of_TOIs:
# from __future__ import annotations
from typing import overload, Optional, Iterable, Union
class ToI:
"""
ToI = Token or Iterable of ToIs
"""
Iterable_of_ToIs = Iterable[Union[ToI, 'Iterable_of_ToIs']]
#overload
def __init__(self, *, token: str) -> None:
...
#overload
def __init__(self, *, iterable: Iterable_of_ToIs) -> None:
...
# actual implementation
def __init__(
self,
token: Optional[str] = None,
iterable: Optional[Iterable_of_ToIs] = None
) -> None:
self.token: Optional[str] = token
self.iterable: Optional[Iterable_of_ToIs] = iterable
But mypy complains
with error: Name 'Iterable_of_ToIs' is not defined or
with error: Cannot resolve name "Iterable_of_ToIs" (possible cyclic definition)
if I move the definition of Iterable_of_ToIs out of the class scope.
What am I doing wrong?
Apparently, I am doing wrong not that much.
Regarding error: Name 'Iterable_of_ToIs' is not defined:
in the section Motivation of PEP 613 (Status Accepted) I found:
Type aliases are declared as top level variable assignments.
Yikes! Couldn't find this rule for Python 3.9 or prior in any other doc, especially not in PEP 484.
But anyway... it explains the error. So, ok, let's move the line to the top level.
Regarding error: Cannot resolve name "Iterable_of_ToIs" (possible cyclic definition):
seems to be not yet supported: https://github.com/python/mypy/issues/731

python37: Does #dataset call super.__init__(...)?

Suppose I have a complicated class with a lot of inputs. This class is not a dataclass class. Further, if I import it explicitly, I would like it to complain if I do not provide all of the arguments.
However, for interfacing purposes and clean code, I would like to define default values for the constructors and pass around arguments for the complex class as, more or less, a 'defined' dict.
This is a good task for the dataclass, and I have defined a dataclass class containing all the arguments with defaults, and which I modify and manipulate.
#dataclass
ComplicatedClassArgs:
arg1: int
arg2: bool = False
...
My question amounts to: can I write the following, and expect and/or tell the dataclass to call super.init(...) with all the named attributes I have defined?
#dataclass
ComplicatedClassArgs(ComplicatedClass):
arg1: int
arg2: bool = False
def some_meta_arg_manipulation_function(...):
pass
def some_other_arg_related_function(...):
pass
Such that I know I have composed a more advanced inner class behavior with a dataclass entry point?
I might have misunderstood your use case, but it looks to me like inheritance is the wrong tool for the job here. How about a simple #classmethod?
#dataclass
ComplicatedClassArgs:
arg1: int
arg2: bool
#classmethod
def from_dict(cls, kwargs=None):
""""ComplicatedClassArgs factory.
This method provides sensible default values that
may or may not be replaced through the input kwargs.
"""
if kwargs is None:
kwargs = {}
default_params = {
'arg1': 1,
'arg2': False
}
return cls(**{**default_params, **kwargs})
>>> ComplicatedClassArgs()
Traceback (most recent call last):
...
TypeError: __init__() missing .. required positional arguments
>>> ComplicatedClassArgs.from_dict()
ComplicatedClassArgs(arg1=1, arg2=False)

autoreload and function decorator

I am fairly new to decorators but am experiencing unexpected behavior revolving around autoreload in an interactive workflow with decorated functions. Its best explained by example (note these are all cells in a jupyter notebook):
The decorator:
%%file testdec.py
def decorated(func):
print("decorating")
def wrapped(*args, **kwargs):
return func(*args, **kwargs)
return wrapped
Where the decorator is used:
%%file testmod.py
from testdec import decorated
#decorated
def thisfunc():
print("old output")
def _thisfunc1():
print("old output 1")
thisfunc1 = decorated(_thisfunc1)
I would use the following to call the decorated functions:
from testmod import *
thisfunc()
thisfunc1()
outputs:
decorating
decorating
old output
old output 1
Now updating testmod.py with:
%%file testmod.py
from testdec import decorated
#decorated
def thisfunc():
print("new output")
def _thisfunc1():
print("new output 1")
thisfunc1 = decorated(_thisfunc1)
and calling the functions again:
thisfunc()
thisfunc1()
gives the following, note the old output from the first method:
decorating
decorating
old output
new output 1
However, explicitly reimporting from this module:
from testmod import *
thisfunc()
thisfunc1()
results in:
new output
new output 1
Ideally the #decorated function (e.g. with the # and not the second method) would autoreload transparently as the second method does. Is there something I can do to achieve this? What am I missing for decorated functions. For now we're manually disabling decorators when editing interactively in order to have the benefits of autoreload.
Thanks.

In the following code why does the last line of execution give an error?

In the following code why does the last line of execution give an error ? Shouldn't the dot operator in x.bf() pass on the instance 'x' to the function bf ( like x.af() would ) ?
class A:
a = 6
def af (self):
return "Hello-People"
class B:
b = 7
def bf (self):
return "Bye-People"
>>> x = A()
>>> b = B()
>>> x.bf = B.bf
>>> x.bf()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bf() missing 1 required positional argument: 'self'
x.bf = B.bf is your error, because B is a class, not an instance of the object.
You can't assign x.bf directly to the class.
You need to assign x.bf to the instance 'b.bf' or instantiate the class properly
ie. Either change that line to:
# Where we instantiated class B and invoke bf via lazy loading (loading at the last possible minute)
x.bf = B().bf
or
# Use the existing instance of B and call bf
x.bf = b.bf
More information:
A and B are your classes. They don't do anything until you instantiate them.
x and b are your object instances. x is an instance of A, and b is an instance of B
Whenever you instantiate a class, you need to conform to it's constructor signature. In this case, the classes require no additional parameters besides self. However, self only gets passed if the class is invoked via ();
'x = A()' and 'b = B()' conform to that signature
The error you encountered is basically python telling you that you called something, a function or a class without passing in a required variable.

Printing a subclass string

I have a "Superclass" and a "subclass"
class Triangle(GeoMetricObject):
def __init__(self,side1=1,side2=1,side3=1):
super().__init__()
self.__side1= side1
self.__side2= side2
self.__side3= side3
def getPerimeter(self,side1,side2,side3):
return side1+side2+side3
def __str__(self):
return super().__str__()+"side1:"+(self.__side1)+"side2:"+(self.__side2)+"side3:"+(self.__side3)
from GeometricObject import GeoMetricObject,Triangle
The second file , which runs the modules above.
def main():
s1= int(input("What is the length of the first side? "))
s2= int(input("What is the length of the second side? "))
s3= int(input("What is the length of the third side? "))
side1=s1
side2=s2
side3=s3
t1 = Triangle(s1,s2,s3)
l = GeoMetricObject()
print("Default color of Triangle:",l.getColor())
print("The Perimeter of Triangle : ",t1.getPerimeter(side1,side2,side3,))
print(Triangle())
main()
My problem is that I can seem to get the proper output from the subclass str properly. It gives me this error;
Traceback (most recent call last):
File "C:\Program Files (x86)\Wing IDE 101 4.1\src\debug\tserver\_sandbox.py", line 15, in <module>
File "C:\Program Files (x86)\Wing IDE 101 4.1\src\debug\tserver\_sandbox.py", line 14, in main
File "c:\Users\Fergus\Desktop\GeometricObject.py", line 26, in __str__
return super().__str__()+"side1:"+(self.__side1)+"side2:"+(self.__side2)+"side3:"+(self.__side3)
builtins.TypeError: Can't convert 'int' object to str implicitly
I am not sure how to fix this problem. I not a very good programmer , mostly a biologist.
You are trying to convert implictly int to string when you do your addition. You can't do an addition between these different types. However, if you convert your ints to string, no problem
replace this:
super().__str__()+"side1:"+(self.__side1)+"side2:"+(self.__side2)+"side3:"+(self.__side3)
by this:
super().__str__()+"side1:"+str(self.__side1)+"side2:"+str(self.__side2)+"side3:"+str(self.__side3)
Don't have python3 to check but it should work.