Python - Using classes as default values of another class' attribute - NameError - python

I'm creating a structure of classes for a wrapper of an API I'm currently writing.
I have multiple classes defined inside my models file. I want to assign the default value of some attributes of classes to other classes. When I do this, I get a NameError because sometimes I try to use classes that are defined below the current class, thus Python does not know these classes yet. I've tried multiple solutions but none of them seem to work. Does anybody know an alternative or has experience with this?
my classes I've defined:
class RateResponse(BaseModel):
def __init__(self,
provider=Provider()
):
self.provider = provider
class Provider(ObjectListModel):
def __init__(self):
super(Provider, self).__init__(list=[], listObject=ProviderItem)
#property
def providerItems(self):
return self.list
class ProviderItem(BaseModel):
def __init__(self,
code=None,
notification=Notification(),
service=Service()
):
self.code = code
self.notification = notification
self.service = service
As you can see above, I'm initialising the attribute 'provider' on the class RateResponse with the an empty object of the class Provider, which is defined below it. I'm getting a NameError on this line because it's defined below RateResponse.
provider=Provider()
NameError: name 'Provider' is not defined
The simple solution to above would be to shift the places of the classes. However, this is only a snippet of my file that is currently 400 lines long, all with these types of classes and initializations. It would be impossible to order them all correctly.
I've looked up some solutions where I thought I could return an empty object of a class by a string. I thought the function would only evaluate after all the classes were defined, but I was wrong. This is what I tried:
def getInstanceByString(classStr):
return globals()[classStr]()
class RateResponse(BaseModel):
def __init__(self,
provider=getInstanceByString('Provider')
):
self.provider = provider
But to no avail. Does anybody have experience with this? Is this even possible within Python? Is my structure just wrong? Any help is appreciated. Thanks.

This code might not mean what you want it to mean:
class RateResponse(BaseModel):
def __init__(self,
provider=Provider()
):
...
This code is saying that when this class is declared you want to make an instance of Provider which will be the default value for the provider parameter.
You may have meant that the default argument should be a new instance of Provider for each client that makes an instance of RateResponse.
You can use the Mutable Default Argument pattern to get the latter:
class RateResponse(BaseModel):
def __init__(self, provider=None):
if provider is None:
provider = Provider()
...
However, if you really do want a single instance when the client wants the default you could add a single instance below the Provider definition:
class Provider(ObjectListModel):
...
Singleton_Provider = Provider()
Then the RateResponse class could still use the current pattern, but instead perform this assignment inside the if:
if provider is None:
provider = Singleton_Provider
At the time that the assignment is performed, the Singleton_Provider will have been created.

Related

Python : Passing parameters by reference down chain

I am trying to pass a variable (MySQL connection class instance) down into a method and then into a class, the issue is that it needs to be done 'by reference' as the main class can change the value. The variable in the final class does not update though:
application:
def __init__(self, quart_instance) -> None:
self._db_object : mysql_connection.MySQLConnection = None
def initialise_app(self):
self.view_blueprint = health_view.create_blueprint(self._db_object)
Health View:
def create_blueprint(db_connector : mysql_connection.MySQLConnection):
view = View(db_connector)
class View:
def __init__(self, db_connector):
self._db_connector = db_connector
When the application performs the database connection in the background in the application I was expecting self._db_connector in the view to update. Any help would be appreciated as I am very confused.
Don't confuse changing the state of an object with changing the value of a variable; the former is visible through all references to that object, the latter only affects that particular variable.
For this to work, the application's _db_object and the view's db_connector must refer to the same object at all times.
There are essentially two solutions:
Give MySQLConnection a default state, so you can create one immediately to pass along to View rather than starting with None and modify it later, or
Wrap MySQLConnection in another object that you can do the same with
Both options have both benefits and drawbacks.

Calling a custom method in a Graphene python resolver

Hello I simply want to avoid repeating code for each query, and I was wondering if I could call a method from inside a resolver a such:
# pseudo code
class Query(graphene.ObjectType):
field = graphene.Field(SomeType)
def do_boring_task(parent, info, arg):
return "I did something"
def resolve_field(parent, info):
did_something = parent.do_boring_task(arg) # <-- is this possible ?
# do something here
return resolved_fields
I always get a "graphql.error.located_error.GraphQLLocatedError: 'NoneType' object has no attribute 'do_boring_task'" error
Is it possible to do that the way I described it, or is this something that should be done using middleware?
Thanks
Classes inheriting from graphene.ObjectType are different than a normal class, resolve_field and do_boring_task are by default static methods.
Note that first argument of resolve_field is parent and not self, do_boring_task is a classmethod (static method in other languages) of Query class and does not exist in parent schema, that explains your error.
A quick fix for your problem is as shown below, define the function, outside of the class.
def do_boring_task(args):
return "I did something"
class Query(graphene.ObjectType):
field = graphene.Field(SomeType)
def resolve_field(parent, info):
did_something = do_boring_task(arg)
# do something here
return resolved_fields
Refer these in the blog for more details
Implicit Static Method
Resolvers Outside the class

Pass the name of the class to a function, assign to a class attribute, outside of a method

Python 3.7:
I have a class definition, where a class attribute is assigned a value based on the class name, and the value is used in a decorator within the class.
I'm looking for a pronoun for "the class currently being defined".
Here's an example:
class MyClass:
# NameError: name '__class__' is not defined
class_logger = find_logger(__class__.__name__)
# __init__ is not important
def __init__(self):
# This works!
self.logger = find_logger(__class__.__name__)
#mydecorator(class_logger)
# mymethod is not important
def mymethod(self):
return 1
What is a suitable pronoun for "the class currently being defined"?
(This is similar to How to get the current Python class name in __init__ regardless of the class of "self"?, but there, the question was "in the definition of init", and at the time was for 2.7. Python 3.x solved that problem.)
It isn't guaranteed that the class object exists and is accessible to the user when the class definition hasn't finished evaluating. Even if it was accessible, it might not be initialized to the extent that you could do anything useful with it.
That said, you may be able to get the name of the class. __qualname__ is an attribute that holds the qualified name of the class / function / method / descriptor / generator instance. You should be able to access it from within the class' definition.
class Fred:
print("Fred's qualname:", __qualname__)
class Barney:
print("Barney's qualname:", __qualname__)
Result:
Fred's qualname: Fred
Barney's qualname: Fred.Barney
If your class isn't defined at the file-level, you might need to do some string manipulation to separate its name from the rest of the path. For example, change the above example to print("Barney's qualname:", __qualname__.rpartition(".")[-1]) to get just "Barney" rather than "Fred.Barney".
Despite my best efforts, I couldn't find documentation that explicitly confirms that __qualname__ has a sensible value when accessed as a regular name and not as an attribute. I'm not fully convinced that this is well-defined behavior, so I don't think I can unreservedly endorse it for production-quality code.
To work with class name during its definition you can also use a metaclass with __prepare__ method:
def find_logger(name):
return name + '_logger'
class PrepareClassLogger(type):
def __prepare__(name, bases, **kwargs):
return {'class_logger': find_logger(name)}
class MyClass(metaclass=PrepareClassLogger):
pass
print(MyClass.class_logger) # MyClass_logger

python: set a class variable programmatically before other class variables get set?

i have a case where i create a class inside an outer function and then return that class. the class has a specified parent class. i would like that class variable to be accessible by class methods on the parent class, these methods are called at class initialization time. in summary, i need to be able to set a class variable (not hardcoded) so that it is available before initializing other, hardcoded class variables.
here's some sample code to make that clearer:
class Parent(object):
class_var = None
#classmethod
def get_class_var_times_two(cls):
return cls.class_var * 2
def outer_function(class_var_value):
class Child(Parent):
other_var = Parent.get_class_var_times_two() # <-- at this point, somehow Child's class_var is set to class_var_value
Not sure if this is even possible in python. Maybe class_var_value doesn't need to be passed through the outer function. I tried using metaclasses and forcing the variable through in the class attribute dictinoary, but couldn't figure out how to set class_var on Child early enough so that it was set prior to initializing other_var. If that was possible, then this would all work. Any thoughts are appreciated!
Edit: also considered making other_var a lazy property, but that isn't an option for my use case.
Calling Parent.get_class_var_times_two() calls the function with cls = Parent, and so consequently the value of Parent.class_var will be used (regardless of what context you call the function from).
So, what you want to do is call Child.get_class_var_times_two(). Trouble is, Child doesn't get defined until the class block finishes. You therefore need to do something like this (assuming you don't use a metaclass):
def outer_function(class_var_value):
class Child(Parent):
class_var = class_var_value
Child.other_var = Child.get_class_var_times_two()

Python/pylint E1101 Need assistance about proper object definition

Need a little help understanding what I am doing wrong. Probably pretty basic, but I haven't wrapped my brain around it.
My code is this:
class baseElement(object):
def __init__(self):
self.Portal = ''
self.locator = ''
def present(self):
return self.Portal.PTF.Presence_of_Element(self.locator)
def visible(self):
return self.Portal.PTF.Is_Element_Visible(self.locator)
class baseActiveElement(baseElement):
def hover(self):
self.Portal.PTF.Mouse_over_element(self.locator)
def click(self):
self.Portal.PTF.Click_on_Element(self.locator)
def get(self):
return self.locator
I define the Portal when I instantiate objects from these bases and it includes some functions to perform the specified actions. This works. No problems there.
But pylint complains thusly:
E1101: 8,15:baseElement.present: Instance of 'str' has no 'PTF' member
E1101: 11,15:baseElement.visible: Instance of 'str' has no 'PTF' member
E1101: 15,8:baseActiveElement.hover: Instance of 'str' has no 'PTF' member
E1101: 18,8:baseActiveElement.click: Instance of 'str' has no 'PTF' member
What should I be doing to not cause this error?
Edit:
If I change my init to this:
class baseElement(object):
def __init__(self):
self.Portal = object
self.Portal.PTF = self.Portal.PTF
self.locator = ''
The pylint objection goes away, and I can see the value of defining portal as a base object, since it will eventually be a real object, but defining Portal.PTF as itself looks like nonsense to me.
The recommended python way is to initialize self.Portal and self.locator to None in __init__ if your API does not require client code to supply values for these attributes to the __int__ method (in which case, your class API is probably lacking a method to set the value of these two attributes).
Pylint tries to do type inference: if the only affectation to self.Portal it can see in your code is with a string, it will infer that the type of the attribute is str, and use this to check calls performed on self.Portal.
If you write:
class baseElement(object):
def __init__(self, portal, locator):
self.Portal = portal
self.locator = locator
It will try know that it knows nothing about the type of portal and locator.
If you have in the same module code such as:
from somewhere import PortalClass, LocatorClass
# [...]
element = SomeClassDerivingFromBaseElement(PortalClass(), LocatorClass())
then Pylint will be able to use this to gather some knowledge about the possible type of portal and locator, and it will be able to analyze the definitions of PortalClass and LocatorClass for attributes such as PTF, and probably check the prototype of Presence_of_Element.
Sidenote: I suggest to try to achieve some consistency in the naming of your classes, attributes and methods. Pylint will help you and you can customize the regexps it uses to match the naming conventions you use.

Categories

Resources