Unable to call method from extended class - python-3.10

I have a Parent class that I extended into a child class, and the goal is to reuse an already created working functionality, but it seems an error occurred when using the parent class method
from sr import BaseClient
class Client(BaseClient):
def __init__(self, credentials=None):
....
def _request(self,path: str, params):
pass
class Address(Client):
def get_address(self, **kwargs):
return self._request('path', kwargs)
Running test
import pytest
from .... import Addresses
def test_get_address():
res = Addresses.get_address({'query': 'some',.....other here})
The error is pointing to the parent method called from the child class(Addresses)
FAILED tests/test_api.py::test_get_addresses - AttributeError: 'dict' object has no attribute '_request'

This is because you're trying to call get_address as a static method, and the dict you're giving to the function ({'query': 'some',.....other here}) is passed as the self argument. This is why you get an error that a dict has no attribute _request, because it doesn't.
Perhaps you meant to instantiate the class first, like Address().get_address()?

Related

mypy TypeVar include bound class as well as subclasses

class Super:
#classmethod
def instantiate(cls) -> What goes here?:
return cls()
class Sub(Super):
pass
class Sub2(Super):
pass
When writing typehints, what's the canonical way to say a method should return an instance of the super class or any of its subclasses. Closest I could find is TypeVar("Super", bound="Super") but this still raises an error for the Super class in mypy
here you can use typing.Type to type-hint cls like this:
from typing import TypeVar, Type
C = TypeVar("C")
class Super:
#classmethod
def instantiate(cls: Type[C]) -> C:
return cls()
class Sub(Super):
pass
class Sub2(Super):
pass
reveal_type(Sub.instantiate()) # note: Revealed type is 'tmp.Sub*'
reveal_type(Sub2.instantiate()) # note: Revealed type is 'tmp.Sub2*'

Django TypeError when trying to use custom base ModelForm or custom error_class

I wanted to have for error_class rendering in forms. I saw this definition and put it into a file in my app directory:
from django.forms.util import ErrorList
class DivErrorList(ErrorList):
def __unicode__(self):
return self.as_divs()
def as_divs(self):
if not self: return u''
return u'<div class="errorlist">%s</div>' % \
''.join([u'<div class="error">%s</div>' % e for e in self])
But, when I try to use it in my view:
from sporty import DivErrorList
...
form = LocationForm(request.POST or None, error_class=DivErrorList)
if form.is_valid():
I get this error, when submitting the form with an error:
TypeError: 'module' object is not callable
/usr/local/lib/python2.7/dist-packages/django/forms/forms.py in _clean_fields, line 293.
This is at the form.is_valid() line. If I don't use the error_class, it works fine (only without the desired .
Next, I tried to instead, create a base ModelForm class that uses the DivErrorList in my app directory:
from django.forms import ModelForm
from sporty import DivErrorList
class MyModelForm(ModelForm):
def __init__(self, *args, **kwargs):
kwargs_new = {'error_class': DivErrorList}
kwargs_new.update(kwargs)
super(MyModelForm, self).__init__(*args, **kwargs_new)
and then I defined my ModelForm based on that class and no longer used the error_class argument on the form creation:
from sporty import MyModelForm
from sporty.models import Location
class LocationForm(MyModelForm):
class Meta:
model = Location
Now, when I try to even view the form (not submitting it with any data), I get this error:
TypeError: Error when calling the metaclass bases module.init() takes at most 2 arguments (3 given)
/home/pcm/workspace/sportscaster/sporty/forms.py in , line 5
I'm at a loss on both of these. Any ideas? I'd prefer the latter, as all my forms will want to use for error reporting (I'd like to actually render the form as divs too, as some point.
Googling around, I found a discussion on type errors and metaclass bases. The issue was that I had a class, MyModelForm, in a file MyModelForm.py, and was then importing the module attempting to use it like a class:
from sporty import MyModelForm
The solution was to place MyModelForm class into a file modelforms.py and do:
from sporty.modelforms import MyModelForm
I did the same with DivErrorList, placing the class in the modelforms.py file.

Is it possible to dynamically name attributes in an App Engine Model?

setattr allows you to dynamically name attributes in Python classes. I'm trying to do something similar with an App Engine Model:
class MyModel(db.Model):
def __init__(self, *args, **kwargs):
super(MyModel, self).__init__(*args, **kwargs)
# Doesn't fully work
setatr(self, 'prop1', db.ListProperty(db.Key))
setatr(self, 'prop2', db.StringListProperty())
# Works fully
# prop1 = db.ListProperty(db.Key))
# prop2 = db.StringListProperty())
This code compiles, but when I call model.prop1.append(key) later on, I get this error:
AttributeError: 'ListProperty' object has no attribute 'append'
I suspect this is because prop1 is declared in models instead of self.prop1, but I don't fully understand the syntax's significance.
Has anyone accomplished this, or does anyone have any insight into syntactic differences?
I think you're looking for the db.Expando class (instead of db.Model).
This SO question:
Adding a user supplied property (at runtime) to an instance of Expando class in google app engine?
gives an example of what you want to do.
Not sure but would this work maybe:
class MyModel(db.Model):
#classmethod
def new(cls, *args, **kwargs):
setattr(cls, 'props1', db.ListProperty(db.Key))
setattr(cls, 'props2', db.StringListProperty())
mymodel = cls(*args, **kwargs)
delattr(cls, 'props1')
delattr(cls, 'props2')
return mymodel

How ugly is my code implementing polymorphic models?

I am using Polymorphic Models.
Simple Question: My code below works without using this line below, which I see in other people's code. What is it supposed to do?
#super(GeneralModel, self).__init__(*args, **kwargs)
Messy Question: I have a feeling my code below, although it seems to work, is not the most beautiful solution.
Synopsis of what I am doing: I am instantiating (or making) a new datastore model entity based on a 'unclean' JSON object posted to the server. 1st I want to do some general input data cleaning specified in the general (or super) model and then 2nd do some special methods, which is specified in each special (or sub-class) model as def parse.
class GeneralModel(polymodel.PolyModel):
lat_long_list = db.ListProperty(db.GeoPt)
zooms = db.ListProperty(int)
def __init__(self, *args, **kwargs):
self.lat_long_list = [ db.GeoPt( pt[0] , pt[1] ) for pt in zip( kwargs["lat"] , kwargs["lon"] ) ]
del kwargs["lat"]
del kwargs["lon"]
if "zooms" not in kwargs: kwargs["zooms"] = ZOOMS # some default
for property,value in kwargs.items():
setattr(self,property,value)
#super(NamedModel, self).__init__(*args, **kwargs)
self.parse()
def parse(self):
raise NotImplementedError('Need to define this for each category')
class SpecialModel(GeneralModel):
stringText = db.StringProperty()
words_list = db.StringListProperty()
def parse( self ):
self.words_list = self.stringText.split(",")
This is how I test whether my code works:
>>>kwargs={'stringText':'boris,ted','lat':[0,1,2,3],'lon':[0,1,2,8],'zooms':[0,10]}
>>>entity=SpecialModel(key_name="tester",**kwargs)
>>>entity.words_list
['boris', 'ted']
The 'super' line calls the constructor of the parent entity. If you don't include it, the parent constructor will not be called, and your model will not be initialized properly. You should, in fact, be calling this first, before any of your own initialization.
However, overriding the constructor on models is strongly discouraged. The constructor is not just used when you call it, but also by the system to construct instances that are being loaded from the datastore, and in the latter case, the arguments - and the expected behaviour - are different, and implementation dependent.
Instead, you should probably define a factory method, like so:
class MyModel(db.PolyModel):
#classmethod
def create(cls, foo, bar):
# Do some stuff
return cls(foo, bleh)

How to correctly serialize a base class to JSON in silverlight?

I have the following structure:
class Base
{
}
class Child : Base
{
}
When I try to do the following:
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Base));
serializer.WriteObject(stream, data);
It fails with the error message:
Type
'MyNamespace.Child'
with data contract name
'Child:http://schemas.datacontract.org/2004/07/MyNamespace'
is not expected. Add any types not
known statically to the list of known
types - for example, by using the
KnownTypeAttribute attribute or by
adding them to the list of known types
passed to DataContractSerializer.
Does anyone know how to correctly serialize just the child class?
If you add the KnownType attribute (from System.Runtime.Serialization) to the base class for the child class then it will work:
[KnownType(typeof(Child))]
class Base
{}
class Child : Base
{}
This is needed because the serializer doesn't load your child type when you set it up to serialize the base class (at least this is my understanding).

Resources