Access app_context from custom Converter in Quart - python-3.x

Is there a solution to get the app context in a class that inherit werkzeug BaseConverter class?
This is my example running in Flask:
from werkzeug.routing import BaseConverter
class CodeConverter(BaseConverter):
app = None
def to_python(self, value):
# Create an app context to get value from db
# and instantiate a class X as obj
return obj
def to_url(self, obj):
value = obj.code
title = obj.title
return "%s/%s"%(value, title)
def crate_app():
...
app.url_map.converters['code'] = CodeConverter
CodeConverter.app = app
...

Well, this works for me.
from werkzeug.routing import BaseConverter
class CodeConverter(BaseConverter):
app = None
async def get_object(self, app, value):
async with app.app_context():
# and instantiate a class X as obj
return obj
def to_python(self, value):
pool = concurrent.futures.ThreadPoolExecutor()
result = pool.submit(asyncio.run, self.get_object(self.__class__.app, value)).result()
return result
def to_url(self, obj):
value = obj.code
title = obj.title
return "%s/%s"%(value, title)
def crate_app():
...
app.url_map.converters['code'] = CodeConverter
CodeConverter.app = app
...

Related

How to select related objects with only one query

Models:
class Tag(BaseModel):
tag_name = models.CharField(max_length=250)
slug = models.SlugField()
def save(self, *args, **kwargs):
self.slug = slugify(self.tag_name)
super(Tag, self).save(*args, **kwargs)
def __str__(self):
return str(self.tag_name)
class Tags(BaseModel):
filtertype = models.CharField(max_length=250)
tags = models.ManyToManyField(Tag)
My current solution:
def get(self,request,version):
filtertype = request.query_params.get('filtertype', '')
filtertypes = filtertype.split(",")
tagsList = Tags.objects.filter(filtertype__in=filtertypes).values_list('tags', flat=True).distinct()
queryset = Tag.objects.filter(id__in=tagsList)
context = {"request": request}
serialized = TagListSerializers(queryset, many=True, context=context)
return Response(serialized.data)
Im trying to get all the relevant Tag base on Tags/filtertype. Im wondering how can I do it with only one query.
you can do the query part with this code:
queryset = Tag.objects.filter(tags__filtertype__in=filtertypes)

How to capture a field instance during django-import-export upload

I'd like to import data into my resource minus the school field because the logged in user already belongs to a specific school. How would I do it without having the school field in my excel???
class uploadStudents(LoginRequiredMixin,View):
context = {}
def get(self,request):
form = UploadStudentsForm()
self.context['form'] = form
return render(request,'upload.html',self.context)
def post(self, request):
form = UploadStudentsForm(request.POST , request.FILES)
data_set = Dataset()
if form.is_valid():
file = request.FILES['file']
extension = file.name.split(".")[-1].lower()
resource = ImportStudentsResource()
if extension == 'csv':
data = data_set.load(file.read().decode('utf-8'), format=extension)
else:
data = data_set.load(file.read(), format=extension)
result = resource.import_data(data_set, dry_run=True, collect_failed_rows=True, raise_errors=True)
if result.has_validation_errors() or result.has_errors():
messages.success(request,f'Errors experienced during import.')
print("error", result.invalid_rows)
self.context['result'] = result
return redirect('import_students')
else:
result = resource.import_data(data_set, dry_run=False, raise_errors=False)
self.context['result'] = None
messages.success(request,f'Students uploaded successfully.')
else:
self.context['form'] = UploadStudentsForm()
return render(request, 'upload.html', self.context)
The resource
class ImportStudentsResource(resources.ModelResource):
school = fields.Field(attribute = 'school',column_name='school', widget=ForeignKeyWidget(School, 'name'))
klass = fields.Field(attribute = 'klass',column_name='class', widget=ForeignKeyWidget(Klass, 'name'))
stream = fields.Field(attribute = 'stream',column_name='stream', widget=ForeignKeyWidget(Stream, 'name'))
class Meta:
model = Student
fields = ('school','student_id','name','year','klass','stream')
import_id_fields = ('student_id',)
import_order = ('school','student_id','name','year','klass','stream')
Either remove 'school' from your 'fields' declaration, or add it to the 'exclude' list.
docs
Edit
To include a school_id which is associated with the logged in user, you'll need to create the Resource with this school_id:
Resource
class ImportStudentsResource(resources.ModelResource):
def __init__(self, school_id):
super().__init__()
self.school_id = school_id
def before_save_instance(self, instance, using_transactions, dry_run):
instance.school_id = self.school_id
post()
def post(self, request):
# skipped existing code
school_id = get_school_id_from_logged_in_user(self.request)
resource = ImportStudentsResource(school_id)

Mock a logger defined in the constructor using pytest

I have this class defined:
class User():
def __init__(self):
self.logger = Logger('user.log')
def get_data(self):
_data = {
'username': 'abc'
}
_payload = json.dumps(_data)
self.logger.info("Loaded payload")
return _payload
The test case written for get_data():
#mock.patch('mymodule.file_user.Logger')
def test_get_data(self,mock_logger):
assert User().get_data() == "'username': 'abc'"
mock_logger.info.assert_called_once_with(
'Loaded payload')
The mocking here fails giving the assertion error "Expected 'info' to be called once. Called 0 times."
Logger is a class, self.logger.info() is an instance method. So you need to get the instance of mock_logger via .return_value.
E.g.
logger.py:
class Logger():
def __init__(self, filepath) -> None:
pass
def info(message):
print(message)
user.py:
import json
from logger import Logger
class User():
def __init__(self):
self.logger = Logger('user.log')
def get_data(self):
_data = {
'username': 'abc'
}
_payload = json.dumps(_data)
self.logger.info("Loaded payload")
return _payload
test_user.py:
import unittest
from unittest import mock
from user import User
class TestUesr(unittest.TestCase):
#mock.patch('user.Logger')
def test_get_data(self, mock_logger):
mock_logger_instance = mock_logger.return_value
user = User()
actual = user.get_data()
self.assertEqual(actual, '{"username": "abc"}')
mock_logger_instance.info.assert_called_once_with('Loaded payload')
if __name__ == '__main__':
unittest.main()
unit test result:
⚡ coverage run /Users/dulin/workspace/github.com/mrdulin/python-codelab/src/stackoverflow/66366372/test_user.py && coverage report -m --include='./src/**'
.
----------------------------------------------------------------------
Ran 1 test in 0.002s
OK
Name Stmts Miss Cover Missing
-----------------------------------------------------------------------
src/stackoverflow/66366372/logger.py 5 2 60% 3, 6
src/stackoverflow/66366372/test_user.py 13 0 100%
src/stackoverflow/66366372/user.py 10 0 100%
-----------------------------------------------------------------------
TOTAL 28 2 93%

inheritance and init pattern with asyncio in python

Searching the web i could not find a lot of answers regarding classes and init-patterns in python for inheritance. I would like to use something like the following pattern. Are there any disadvantages for this pattern? One maybe is that there could be no init method for the child.
import asyncio
class Foo(object):
def __init__(self):
self.something = None
#classmethod
async def create(cls, something):
self = cls()
self.something = something
return self
class FooChild(Foo):
def __init__(self):
#...
super().__init__()
#classmethod
async def create(cls, something):
self = await super().create(something)
#...
return self
async def main():
something = "something"
foo = await FooChild.create(something)
if __name__ == '__main__':
asyncio.run(main())

How do i mock an attribute within nested constructor using unittest

This is what i am trying to test :
src/DBOps.py
class DBOps() :
class dynamodbOps() :
def __init__(self,db_table) :
dynamodb = boto3.resource('dynamodb')
self.table = dynamodb.Table(db_table)
def GetDBItem(self,pool):
response = self.table.get_item(Key={'pool' : pool})
And this is the test case that is unsuccessful :
class test_GetDBItem(unittest.TestCase) :
def setUp(self):
self.db_ops = DBOps()
db_table = "test_table"
self.dyn = self.db_ops.dynamodbOps(db_table)
#mock.patch('src.DBOps')
def test_run_query_with_item(self, getItem_mock) :
getItem_mock.dynamodbOps.table.get_item.return_value = {"Blah":"Blah Blah"}
pool = 'some_pool'
response = self.dyn.GetDBItem(pool)
I am trying to mock the 'table.get_item' call and failing at it no matter what i try. Any pointers would be great!
Figured it out as below :
class test_GetDBItem(unittest.TestCase) :
def setUp(self):
db_ops = DBOps()
db_table = "test_table"
self.dyn = db_ops.dynamodbOps(db_table)
def test_run_query_with_item(self) :
with patch.object(self.dyn.table, 'get_item') as getItem_mock :
getItem_mock.return_value = {"Blah":"Blah Blah"}
pool = 'some pool'
response = self.dyn.GetDBItem(quadra_pool)

Resources