I am trying to write a class and call it this is my code
import jwt
class generate_jwt():
def __init__(self):
self.name = 'jwt token manager'
def encode_with_hsa(self, secret, expiration_time, payload):
exp_time = {'exp': expiration_time}
return jwt.encode(payload, exp_time, secret, algorithm='HS256')
snake = generate_jwt()
so = {'secret':'ff'}
print(snake.encode_with_hsa('dd', 434234, so))
But this shows TypeError: encode() got multiple values for argument 'algorithm' when calling the class and returing the value
I fixed your code by doing something like:
import jwt
class generate_jwt():
def __init__(self):
self.name = 'jwt token manager'
def encode_with_hsa(self, secret, expiration_time, payload):
exp_time = {'exp': expiration_time}
return jwt.encode(payload, secret, algorithm='HS256', exp_time)
snake = generate_jwt()
so = {'secret':'ff'}
print(snake.encode_with_hsa('dd', 434234, so))
Checkout the definition of encode function here:
def encode(self,
payload, # type: Union[Dict, bytes]
key, # type: str
algorithm='HS256', # type: str
headers=None, # type: Optional[Dict]
json_encoder=None # type: Optional[Callable]
):
So, you have to go by the definition of the function, i.e. how the arguments are passed (order of the arguments).
Note: I am not sure where you need the exp_time. You can just remove it as it is optional.
Related
I am fairly new to FastAPI(migrating from Django) and I am trying to create a generic CRUD operations class that I can inherit and use across my CBV endpoints.
Something like this :
class AbstractCrud
model: Base = NotImplemented
session: Session = NotImplemented
def get_items(self, limit, **filters):
""" Read operation """
def get_item(self, pk: int):
def create_item(self, obj: BaseModel):
""" Create operation """
def update_item(self, pk: int, **params):
""" Update operation"""
def delete_item(self, pk: int):
""" Delete operation """
router = InferringRouter()
#cbv(router)
class UserAPI(AbstractCrud):
router.tags = ["User"]
router.prefix = "/users"
model = User
session: Session = Depends(get_db)
# my endpoints
#e.g. #router.get(...)
#cbv(router)
class PostAPI(AbstractCrud):
router.tags = ["Post"]
router.prefix = "/posts"
model = Post
session: Session = Depends(get_db)
# my endpoints
#e.g. #router.get(...)
I get the following error if I try to do the above:
fastapi.exceptions.FastAPIError: Invalid args for response field! Hint: check that <class 'sqlalchemy.orm.decl_api.Base'> is a valid pydantic field type
For now, I am able to achieve this as follows:
class AbstractCrud
model: Base = NotImplemented
session: Session = NotImplemented
def get_items(self, limit, **filters):
""" Read operation """
def get_item(self, pk: int):
def create_item(self, obj: BaseModel):
""" Create operation """
def update_item(self, pk: int, **params):
""" Update operation"""
def delete_item(self, pk: int):
""" Delete operation """
class UserCrud(AbstractCrud):
def __init__(self, session: Session):
self.session = session
self.model = User
class PostCrud(AbstractCrud):
def __init__(self, session: Session):
self.session = session
self.model = Post
router = InferringRouter()
#cbv(router)
class UserAPI:
router.tags = ["User"]
router.prefix = "/users"
def __init__(self, session=Depends(get_db)):
self.session = session
self.crud = UserCrud(self.session)
# my endpoints
#e.g. #router.get(...)
#cbv(router)
class PostAPI:
router.tags = ["Post"]
router.prefix = "/posts"
def __init__(self, session=Depends(get_db)):
self.session = session
self.crud = PostCrud(self.session)
# my endpoints
#e.g. #router.get(...)
Although this is working fine for me now, I can't help but think if there is a better(or correct) way to do this.
Also, Is my use of a single router variable across multiple classes correct?
I want to assign a value of None to a field that fails to validate in Pydantic. The validator has a list of fields that it tries to validate.
To validate each field using data, fields_set, e = validate_model(model, raw_data) I need to know the model of each field.
I would like to have something like this for a validator.
Is there a way to discover the type of the field that is being validated???
#validator('*', pre=True)
def validate_name(cls, value: str):
model_of_field = ..... Some method to discover the field's Type(s)
data, fields_set, e = validate_model(model_of_field, value)
return value
Example that declares a separate validator method for each field
Note that the field is named "name1" on purpose to fail the validation and make it return None.
from typing import Any, Optional
from pydantic import BaseModel, validator, validate_model, ValidationError
class NameModel(BaseModel):
name: str
class AgeModel(BaseModel):
age: int
class MyModel(BaseModel):
name_data: Optional[NameModel]
age_data: Optional[AgeModel]
#classmethod
def pre_validate_any_field_and_return_none_on_validation_error(cls, model: Any, value: Any):
data, fields_set, e = validate_model(model, value)
if e:
return None
else:
return value
#validator('name_data', pre=True)
def validate_name(cls, value: str):
return cls.pre_validate_any_field_and_return_none_on_validation_error(NameModel, value)
#validator('age_data', pre=True)
def validate_age(cls, value: int):
return cls.pre_validate_any_field_and_return_none_on_validation_error(AgeModel, value)
my_data = {
'name_data': {'name1': 'Hello_a'},
'age_data': {'age': 120}
}
my_object: MyModel = MyModel(**my_data)
print(my_object)
You should use the __fields__ property as documented here: https://pydantic-docs.helpmanual.io/usage/models/#model-properties. It will give you something like this:
class Model(BaseModel):
value: int
#validator("value", pre=True)
def validate_value(cls, v):
print(cls.__fields__)
# Do your logic here
return v
Model(1)
This would print:
{'value': ModelField(name='value', type=int, required=True)}
I am trying to add a custom decorator to secure fastapi endpoints to list of users. The incoming payload has JWT data in the header and/or cookies.
With out the decorator, fastapi_jwt_auth allows/denies to the endpoints as long as the token is valid. However when adding the custom decorator, it fails to pass the header/cookie payload to the decorator to be parsed and return the correct response if valid/invalid.
From what I could understand from this post it should be able to obtain the payload from the router function. However it only seems to create a blank class object.
from functools import wraps
from fastapi import Depends
from fastapi.responses import JSONResponse
from fastapi_jwt_auth import AuthJWT
def auth(users: Union[List[str], None, str] = None):
def decorator_auth(func):
#wraps(func)
def wrapper_auth(*args, **kwargs):
Authorize.jwt_required()
jwt_username = Authorize.get_raw_jwt()['username']
if jwt_username not in users:
return JSONResponse(
status_code=401,
content={"detail": "Unauthorized"} )
return func(*args, **kwargs)
return wrapper_auth
return decorator_auth
#app.get('/data')
def secure_data(Authorize: AuthJWT = Depends()):
Authorize.jwt_required()
return JSONResponse(
status_code=200,
content={"detail": "Payload only all with valid tokens."})
#app.get('/data1')
#auth(users=['user1', 'user3')
def secure_data_1(Authorize: AuthJWT = Depends()):
return JSONResponse(
status_code=200,
content={"detail": "Payload only for User 1 and User 3."})
#app.get('/data2')
#auth(users=['user2'])
def secure_data2(Authorize: AuthJWT = Depends()):
return JSONResponse(
status_code=200,
content={"detail": "Payload only for User 2."} )
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.
def do_redirect():
raise cherrypy.HTTPRedirect("/login.html")
def check_auth(call_func):
# do check ...
if check_success():
return
call_func()
cherrypy.tools.auth = cherrypy.Tool('before_handler', check_auth)
cherrypy.tools.auth.call_func = do_redirect
I want to set the function do_redirect as check_auth's parameter,
but it throw the follow exception:
TypeError: check_auth() takes exactly 1 argument (0 given)
but it can works if modify to follow code:
def check_auth(call_func):
# do check ...
if check_success():
return
cherrypy.tools.auth.call_func()
cherrypy.tools.auth = cherrypy.Tool('before_handler', check_auth)
cherrypy.tools.auth.call_func = do_redirect
how to set the callable function parameters of 'before_handler' in cherrypy?
There are a couple of way on setting the argument for a tool, take a look to this example:
import cherrypy as cp
def check_success():
return False
def do_redirect():
raise cp.HTTPRedirect("/login.html")
def fancy_redirect():
raise cp.HTTPRedirect("/fancy_login.html")
def secret_redirect():
raise cp.HTTPRedirect("/secret_login.html")
def check_auth(call_func=do_redirect):
# do check ...
if check_success():
return
call_func()
cp.tools.auth = cp.Tool('before_handler', check_auth, priority=60)
class App:
#cp.expose
#cp.tools.auth() # use the default
def index(self):
return "The common content"
#cp.expose
def fancy(self):
return "The fancy content"
#cp.expose
#cp.tools.auth(call_func=secret_redirect) # as argument
def secret(self):
return "The secret content"
#cp.expose
def login_html(self):
return "Login!"
#cp.expose
def fancy_login_html(self):
return "<h1>Please login!</h1>"
#cp.expose
def secret_login_html(sel):
return "<small>Psst.. login..</small>"
cp.quickstart(App(), config={
'/fancy': {
'tools.auth.on': True,
'tools.auth.call_func': fancy_redirect # from config
}
})
Try this
cherrypy.tools.auth = HandlerWrapperTool(newhandler=auth_fn)
or
class AuthHandler(Tool):
def __init__(self, auth_fn):
self._point = 'before_handler'
self._name = 'auth_handler'
self._priority = 10
self._auth_fn = auth_fn
def callable(self):
# implementation