python class Multiple inheritance __init__ object has no attribute 'xxx' - python-3.x

i have class , it inheritance other tow class.
class Req(Proxy, Headers):
def __init__(self):
super().__init__()
class Proxy:
pass
class Headers:
def __init__(self):
self.kdl_proxy_params = config.kdl_proxy_params
def get_ua(self):
res = requests.get("https://dev.kdlapi.com/api/getua", params=self.kdl_proxy_params).json()
ua = res["data"]["ua_list"][0]
return ua
r = Req()
r.get_ua()
So I received the following error message
AttributeError: 'Req' object has no attribute 'kdl_proxy_params'
I feel that this is a question of multiple inheritance. I hope you can help me to solve my doubts.

Related

How to pass extra data to fastapi APIRouter?

This is my 1st fastapi exercise. I've my old model serving code implemented with Flask as following:
class HealthCheck(Resource):
def __init__(self, **kwargs):
super(HealthCheck, self).__init__()
self._model = kwargs['model']
self._logger = kwargs['logger']
def get(self):
if self._model:
return {"status" : "healthy"}, HTTPStatus.OK
return {"status": "unavailable"}, HTTPStatus.BAD_REQUEST
def put(self):
raise MethodNotAllowed('PUT request not supported')
# similarly other methods are disabled
# In a different module, say in App class
class App():
def __init__(self, name, logger, config):
self._logger = logger
self._model = load_model(config['model_path'])
self._flask_app = Flask(name)
api = Api(self._flask_app)
# logger and model is passed to HealthCheck resource
api.add_resource(HealthCheck, "/api/healthcheck",
resource_class_kwargs={'model': self._model, 'logger': self._logger})
How do I achieve same with fastapi APIRouter?
My example fastapi implementation is following:
class HealthResult(BaseModel):
healthy: bool
health_router = fastapi.APIRouter()
#health_router.get("/healthcheck", response_model=HealthResult, name="heathcheck")
async def heartbeat() -> HealthResult:
hb = HealthResult(healthy=True)
return hb
# in the App module
class App():
def __init__(self, name, logger, config):
self._logger = logger
self._model = load_model(config['model_path'])
self._api = fastapi.FastAPI(title=name)
self._api.include_router(health_router, prefix="/api")
# how do I pass model and logger to health_router to use that in heartbeat method?
I want to avoid using any global storage for model and logger and access in health_router from there.
Also, since my fastapi object is inside App class, how can I invoke multiple worker with uvicorn in this case?
Though I don't like it, I modified my App class as following to get around the problem - still looking for cleaner solution.
class App(metaclass=Singleton):
_MODEL: Union[None, Model] = None
_LOGGER: Union[None, CustomLogger] = None
#classmethod
def setLogger(cls, logger: CustomLogger) -> None:
cls._LOGGER = logger
#classmethod
def getLogger(cls) -> CustomLogger:
return cls._LOGGER
#classmethod
def setModel(cls, model: Model) -> None:
assert model
cls._MODEL = model
#classmethod
def getModel(cls) -> Model:
return cls._MODEL
def __init__(self, name: str, logger: CustomLogger, config: YAML) -> None:
App.setLogger(logger)
model: Model = load_model(config['model_path'])
App.setModel(model)
self._api = fastapi.FastAPI(title=name)
self._api.include_router(health_router, prefix="/api")
....
class HealthResult(BaseModel):
healthy: bool
health_router = fastapi.APIRouter()
#health_router.get("/healthcheck", response_model=HealthResult, name="heathcheck")
async def heartbeat() -> HealthResult:
model: Model = App.getModel()
hb: HealthResult = HealthResult(healthy=True) if model else HealthResult(healthy=False)
return hb
from fastapi import Request
app = FastAPI()
app.share_text = 'aaa'
# in Apirouter
#router.get("/share}", request: Request)
async def read( request: Request):
#retrieve from app context
share_text = request.app.share_text
return {}
You could retrive the app context from Request
Ref: https://fastapi.tiangolo.com/advanced/using-request-directly/#use-the-request-object-directly
Ref: https://www.starlette.io/requests/
Application The originating Starlette application can be accessed via
request.app.
Other state If you want to store additional information on the request
you can do so using request.state.
For example:
request.state.time_started = time.time()

How can I pass kwargs to class function

I don't have much experience with class inheritance. I understand that you can pass any variable to class instance via *args and **kwargs which help one to accommodate child classes.
In the example bellow, I'd like to pass the title, theme and size when instantiating a class which would do for me: self.title('App') and self.set_theme('radiance'). Now I'm just replacing the attributes, i.e., self.title = 'App' and self.set_theme = 'radiance' which doesn't do what I want...
class App(ThemedTk):
def __init__(self, **kwargs):
super().__init__()
self.__dict__.update(kwargs)
dic = {
'title': 'App',
'set_theme': 'radiance',
}
app = App(**dic)
app.mainloop()
I believe you are looking for something like this
from ttkthemes import ThemedTk
class App(ThemedTk):
def __init__(self, **kwargs):
title=kwargs.pop('title','')
theme=kwargs.pop('set_theme',None)
super().__init__(**kwargs)
self.title(title)
if theme:
self.set_theme(theme)
dic = {
'title': 'App',
'set_theme': 'radiance',
}
app = App(**dic)
app.mainloop()
You can pop (kwargs.pop(key, default)) out the kwargs that don't go into the __init__ function of ThemedTk in the begining and then pass them into the respective methods later on.
Based on #AST's answer:
from ttkthemes import ThemedTk
class App(ThemedTk):
# The default value for `title` is "Tk" and
# the default value for `theme` is `None`
def __init__(self, title="Tk", theme=None, **kwargs):
super().__init__(**kwargs)
self.title(title)
# If the theme is None just skip it
if theme is not None:
self.set_theme(theme)
dic = {
'title': 'App',
'set_theme': 'radiance',
}
app = App(**dic)
app.mainloop()

Python patch of a object creation not working

app.py
class UnderTest:
def one(self):
print('In one')
email = EmailSender(None, 'messwage');
email.send()
EmailSender.py
class EmailSender:
def __init__(self, config, message):
self.mess = message;
def send(self):
print("should not be invoked")
test_under_test.py
class test_under_test(TestCase):
#patch('EmailSender.EmailSender')
def test_one(self, email):
test = UnderTest()
email.send.return_value = None;
test.one();
The 'send' method of the EmailSender should not have invoked, but, it is being invoked. When i debug instead of the Mock object in the email variable in EmailSender.one method i see original object of EmailSender, the patch is not working as expected here. what should I do?

How to set parameter for all of the methods in Inherited class

I am currently learning Object Oriented Programming in Python. I have some issues with understanding how to pass to all methods that I inherite from Parten class. I will show you example of code.
Below you can see my Parent class (it's simple api wrapper).
class AlphaVantageClient:
_URL = "https://www.alphavantage.co/query?"
def __init__(self, api_key=None):
self.__api_key = api_key
def show_base_url(self):
print(self._URL)
def set_api_key(self, api_key: str):
self.__api_key = api_key
def __call_api(self, query_parameters: dict,**kwargs):
"""
The structure looks like:
co./query?function{}&symbol{}
:param query_parameters:
:return: response
"""
query_parameters["apikey"] = self.__api_key
response = requests.get(
AlphaVantageClient._URL,
params=query_parameters,
proxies=self.__proxy
)
validate_http_status(response)
return response.json()
def company_overview(self, ticker: str, **kwargs):
query_parameters = {
"function": "OVERVIEW",
"symbol": ticker
}
return self.__call_api(query_parameters, **kwargs)
def balance_sheet(self, ticker: str, **kwargs):
query_parameters = {
"function": "BALANCE_SHEET",
"symbol": ticker
}
return self.__call_api(query_parameters, **kwargs)
def income_statement(self, ticker: str, **kwargs):
query_parameters = {
"function": "INCOME_STATEMENT",
"symbol": ticker
}
return self.__call_api(query_parameters, **kwargs)
def cash_flow(self, ticker: str, **kwargs):
query_parameters = {
"function": "CASH_FLOW",
"symbol": ticker
}
return self.__call_api(query_parameters, **kwargs)
And below there is my child class in which I want to inheritate from AlphaVantageClient class all of the methods.
class Stock(AlphaVantageClient):
def __init__(self, ticker: str):
super().__init__()
self.ticker = ticker
self.client = AlphaVantageClient()
def set_api_key(self, api_key):
self.client.set_api_key(api_key)
But my problem is that as you see in AlphaVantegeClient all of my methods has parameter symbol, I would like to set in one line or something like that for all of the methods to have my symbol parameter set to self.ticker from Stock class. Is it possible to do that ? Or I need to somehow refactor Parent class code ?
You misunderstand how inheritance works. When you create a class Stock that subclasses (inherits from) class AlphaVantageClient it automatically gets all of the attributes and methods of that parent class as if you defined them as part of the new subclass.
You should absolutely not have this line in the init: self.client = AlphaVantageClient(). By subclassing (inheriting) from AlphaVantageClient it already is an instance of AlphaVantageClient and that creates a separate additional instance of and AlphaVantageClient separate from the one it is.
In your Stock class you do not have to redefine set_api_key() unless you are trying to change it for some reason and you are not. This method is just trying to save the api_key into an internal class attribute and it already does that so just leave it out/un-redefined in Stock.
You do not need to rework AlphaVantageClient, but you do need to have stubs in Stock since they need to substitute in the saved ticker parameter into the calls to the parent. Like this:
class Stock(AlphaVantageClient):
def __init__(self, ticker: str, api_key=None):
super().__init__(api_key)
self.ticker = ticker
def company_overview(self, **kwargs):
return super().company_overview(self.ticker, **kwargs)
def balance_sheet(self, **kwargs):
return super().balance_sheet(self.ticker, **kwargs)
def income_statement(self, **kwargs):
return super().income_statement(self.ticker, **kwargs)
def cash_flow(self, **kwargs):
return super().cash_flow(self.ticker, **kwargs)
Thank you for you answer. I don't know if I get it correctly.
class AlphaVantageClient:
_URL = "https://www.alphavantage.co/query?"
def __init__(self, api_key=None, symbol=None):
self.__api_key = api_key
self.__proxy = {}
self.__validate_api_key()
self.__data_type = 'json'
self.__symbol = symbol
def set_api_key(self, api_key: str):
self.__api_key = api_key
def __call_api(self, query_parameters: dict,**kwargs):
"""
The structure looks like:
co./query?function{}&symbol{}
:param query_parameters:
:return: response
"""
query_parameters["apikey"] = self.__api_key
response = requests.get(
AlphaVantageClient._URL,
params=query_parameters,
proxies=self.__proxy
)
validate_http_status(response)
return response.json()
def company_overview(self, symbol: str, **kwargs):
query_parameters = {
"function": "OVERVIEW",
"symbol": symbol
}
return self.__call_api(query_parameters, **kwargs)
def balance_sheet(self, symbol: str, **kwargs):
query_parameters = {
"function": "BALANCE_SHEET",
"symbol": symbol
}
return self.__call_api(query_parameters, **kwargs)
def income_statement(self, symbol: str, **kwargs):
query_parameters = {
"function": "INCOME_STATEMENT",
"symbol": symbol
}
return self.__call_api(query_parameters, **kwargs)
def cash_flow(self, symbol: str, **kwargs):
query_parameters = {
"function": "CASH_FLOW",
"symbol": symbol
}
return self.__call_api(query_parameters, **kwargs)
class Stock(AlphaVantageClient):
def __init__(self, symbol: str):
super().__init__(symbol)
self.symbol = symbol
self.client = AlphaVantageClient(symbol)
def set_api_key(self, api_key):
self.client.set_api_key(api_key)
Now my classes look like this. And I try to create instance of my class and call one of methods like below:
from client import AlphaVantageClient, Stock
stock = Stock(symbol="FB")
stock.income_statement()
And I get an error:
tests\test_client.py:5: in <module>
stock.income_statement()
E TypeError: income_statement() missing 1 required positional argument: 'symbol'
So I don't know if I don't understand you correctly or I just explained my problem in wrong way. So I will try once more:
If I call my AlphaVantageClient, I want to use it in the way that I create instance of that class and I call methods providing as an parameter symbol of stock e.g
client = AlphaVantageClient()
income_statement = client.income_statement(symbol="FB")
But if I create a Stock class I would like to have symbol stored in class and don't need to provide it as a paramtere in my methods: All the methods should use that symbol that I provided when I created Stock class as default. So the usage should look like below:
stock = Stock(symbol="FB")
income_statement = stock.income_statement()
And this way I will fetch the data for "FB" in all of my methods.
Is it possible ? If yes, can you explain me little more how to achive it.

AttributeError at /login/ type object 'super' has no attribute 'save'

Request Method: POST
Request URL: http://127.0.0.1:8000/login/?next=/post/new/
Django Version: 2.1.4
Exception Type: AttributeError
Exception Value:
type object 'super' has no attribute 'save'
Exception Location: C:\Users\User\Desktop\progetti\django_project\users\models.py in save, line 14
this error happen when i insert LoginRequiredMixin in this class in views.py
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['title', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
in urls.py
urlpatterns = [
------
path('post/new/', PostCreateView.as_view(), name='post-create'),
------
]
this is models.py that refers to user:
from django.db import models
from django.contrib.auth.models import User
from PIL import Image
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg',
upload_to='profile_pics')
def __str__(self):
return f'{self.user.username} Profile'
def save(self):
super.save()
img = Image.open(self.image.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.image.path)
Here:
def save(self):
super.save()
You need to call super, ie:
def save(self):
super().save()
Also, Model.save() can takes quite a few arguments, that you need to both accept and pass to the super().save() call, so the correct implementation is:
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
And finally, I would definitly not use Model.save() to process the image - this should be done in the form to avoid executing this code over and over each time the model is saved.

Resources