Do it exist a helper function how data_get (Laravel) in Django? - django

The data_get function retrieves a value from a nested array or object using "dot" notation:
$data = ['products' => ['desk' => ['price' => 100]]];
$price = data_get($data, 'products.desk.price');
// 100
More detail in Laravel Doc

I do this function:
def get_data(data, dot_path, default=None):
arr_paths = dot_path.split('.')
result = data
for path in arr_paths:
try:
if isinstance(result, (dict, list, tuple)):
result = result[path]
else:
result = None
except KeyError as e:
result = None
if not result:
result = default
return result

Related

Pytest raise Error and return value from Mock

I have the the following method in a RedisDriver class:
def get(self, key):
key_str = str(key)
try:
master = self.connection.master_for(self.service)
value = master.get(key_str)
except RedisError as err:
error_str = "Error while retrieving value from redis : " + str(err)
return {"success": False, "error": error_str}
I want to check is the error message is correct:
I tried the following:
#mock.patch("code.redis_driver.redis_sentinel")
#mock.patch("code.redis_driver.RedisDriver.get", side_effect=RedisError)
def test_redis_driver_delete(mocked_sentinel, mock_redis_sentinel):
mocked_master = mock.Mock()
mock_redis_sentinel.master_for.return_value = mocked_master
redis_driver = RedisDriver(mock_redis_sentinel)
result = redis_driver.get("test")
assert result == {"success": False, "error": "test"}
This does not work since an exception is raised:
E redis.exceptions.RedisError
Since this does not work I try the following:
#mock.patch("code.redis_driver.redis_sentinel")
#mock.patch("code.redis_driver.RedisDriver.get", side_effect=RedisError)
def test_redis_driver_delete(mocked_sentinel, mock_redis_sentinel):
mocked_master = mock.Mock()
mock_redis_sentinel.master_for.return_value = mocked_master
redis_driver = RedisDriver(mock_redis_sentinel)
with pytest.raises(RedisError) as exception:
result = redis_driver.get("test")
assert result == {"success": False, "error": str(exception)}
This always passes, whatever I set result to. How can I catch the expected output?
Solved it by mocking the whole class and use side_effect on the get method:
#mock.patch("code.redis_driver.RedisDriver")
def test_redis_driver_delete(mock_redis_sentinel):
mocked_master = mock.Mock()
mocked_master.get.side_effect = RedisError("error")
mock_redis_sentinel.master_for.return_value = mocked_master
redis_driver = RedisDriver(mock_redis_sentinel)
result = redis_driver.get("test")
assert result == {"success": False, "error": "Error while retrieving value from redis : error"}

Unable to create a record in except loop of try-except odoo10

When i call the below function through API;
In both try and except conditions I have to keep log in separate table named api.log.
While the function enters in except condition, error occurs on creating record on api.log table
Here is the code:
#http.route('/tax_master',type="json",methodn ['POST'],auth="public",csrf=Falenter code herese)
def create_tax_master(self,**kw):
kw = http.request.params
obj_tax_master = request.env['tax.master']
obj_account_tax = request.env['account.tax']
flag = kw.get('flag')
vals = {}
result = False
if kw.get('name'):
vals['name'] = kw.get('name')
if kw.get('value'):
vals['value'] = kw.get('value')
if kw.get('scope'):
vals['scope'] = kw.get('scope')
if kw.get('is_excise'):
vals['is_excise'] = kw.get('is_excise')
if kw.get('description'):
vals['description'] = kw.get('description')
if kw.get('amount_type'):
vals['amount_type']= kw.get('amount_type')
if 'is_excise' in kw and kw.get('is_excise') not in [1,0]:
result = json.dumps({
"statusCode":02,
"statusDesc":"The value for the field is_excise should be 0 or 1"})
try:
if flag == 'create':
tax_id = obj_tax_master.sudo().create(vals).id
result = json.dumps({"id":tax_id,
"statusCode":01,
"statusDesc":"Successfully Created"
})
elif flag == 'write':
if kw.get('id'):
tax_id_rec = obj_tax_master.sudo().browse([int(kw.get('id'))])
if tax_id_rec.active == False:
result = json.dumps({
'statusCode': 02,
'statusDesc': 'The Tax is Archived.Updation is not possible now',
})
else:
tax_id_rec.sudo().write(vals)
tax_id = kw.get('id')
result = json.dumps({"id":tax_id,
"statusCode":01,
"statusDesc":"Successfully Updated"
})
else:
result = json.dumps({
'statusCode' : 02,
'statusDesc' : 'Please provide valid id to update the record',
})
elif flag == 'delete':
tax_id = obj_tax_master.sudo().browse(int(kw.get('id')))
if tax_id.active == False:
result = json.dumps({
'statusCode': 02,
'statusDesc': 'The record is already archived!!!',
})
else:
tax_id.write({'active':False})
taxes = obj_account_tax.sudo().search([('tax_master_id','=',kw.get('id'))])
for tax in taxes:
tax.write({'active':False})
result = json.dumps({
'statusCode' : 01,
'statusDesc' : 'The record is archived successfully!!!',
})
data = json.loads(result)
self.create_api_log('tax_master', flag, kw, data)
return data
except Exception,e:
result = json.dumps({'statusCode' : 02,'statusDesc' : str(e),})
data = json.loads(result)
self.create_api_log('tax_master', flag, kw, data)
return data
It is solved by using commit function.

Scheduling tasks with dynamic arguments to run periodically with celery in django

I have a tasks that contains dynamic arguments I want to run periodically, how do I pass dynamic elements to the tasks arguments when the task is being called in django celery beat?
Here is the task I want to run periodically:
#task(bind=True)
def generate_export(export_type, xform, export_id=None, options=None):
"""
Create appropriate export object given the export type.
param: export_type
param: xform
params: export_id: ID of export object associated with the request
param: options: additional parameters required for the lookup.
binary_select_multiples: boolean flag
end: end offset
ext: export extension type
dataview_pk: dataview pk
group_delimiter: "/" or "."
query: filter_query for custom queries
remove_group_name: boolean flag
split_select_multiples: boolean flag
index_tag: ('[', ']') or ('_', '_')
show_choice_labels: boolean flag
language: language labels as in the XLSForm/XForm
"""
username = xform.user.username
id_string = xform.id_string
end = options.get("end")
extension = options.get("extension", export_type)
filter_query = options.get("query")
remove_group_name = options.get("remove_group_name", False)
start = options.get("start")
export_type_func_map = {
Export.XLS_EXPORT: 'to_xls_export',
Export.CSV_EXPORT: 'to_flat_csv_export',
Export.DHIS2CSV_EXPORT: 'to_dhis2csv_export',
Export.CSV_ZIP_EXPORT: 'to_zipped_csv',
Export.SAV_ZIP_EXPORT: 'to_zipped_sav',
Export.GOOGLE_SHEETS_EXPORT: 'to_google_sheets',
}
if xform is None:
xform = XForm.objects.get(
user__username__iexact=username, id_string__iexact=id_string)
dataview = None
if options.get("dataview_pk"):
dataview = DataView.objects.get(pk=options.get("dataview_pk"))
records = dataview.query_data(dataview, all_data=True,
filter_query=filter_query)
total_records = dataview.query_data(dataview,
count=True)[0].get('count')
else:
records = query_data(xform, query=filter_query, start=start, end=end)
if filter_query:
total_records = query_data(xform, query=filter_query, start=start,
end=end, count=True)[0].get('count')
else:
total_records = xform.num_of_submissions
if isinstance(records, QuerySet):
records = records.iterator()
export_builder = ExportBuilder()
export_builder.TRUNCATE_GROUP_TITLE = True \
if export_type == Export.SAV_ZIP_EXPORT else remove_group_name
export_builder.GROUP_DELIMITER = options.get(
"group_delimiter", DEFAULT_GROUP_DELIMITER
)
export_builder.SPLIT_SELECT_MULTIPLES = options.get(
"split_select_multiples", True
)
export_builder.BINARY_SELECT_MULTIPLES = options.get(
"binary_select_multiples", False
)
export_builder.INCLUDE_LABELS = options.get('include_labels', False)
export_builder.INCLUDE_LABELS_ONLY = options.get(
'include_labels_only', False
)
export_builder.INCLUDE_HXL = options.get('include_hxl', False)
export_builder.INCLUDE_IMAGES \
= options.get("include_images", settings.EXPORT_WITH_IMAGE_DEFAULT)
export_builder.VALUE_SELECT_MULTIPLES = options.get(
'value_select_multiples', False)
export_builder.REPEAT_INDEX_TAGS = options.get(
"repeat_index_tags", DEFAULT_INDEX_TAGS
)
export_builder.SHOW_CHOICE_LABELS = options.get('show_choice_labels',
False)
export_builder.language = options.get('language')
# 'win_excel_utf8' is only relevant for CSV exports
if 'win_excel_utf8' in options and export_type != Export.CSV_EXPORT:
del options['win_excel_utf8']
export_builder.set_survey(xform.survey, xform)
# change the dhis2csv exports to standard csv format
if extension == 'dhis2csv':
extension = 'csv'
temp_file = NamedTemporaryFile(suffix=("." + extension))
columns_with_hxl = export_builder.INCLUDE_HXL and get_columns_with_hxl(
xform.survey_elements)
# get the export function by export type
func = getattr(export_builder, export_type_func_map[export_type])
try:
func.__call__(
temp_file.name, records, username, id_string, filter_query,
start=start, end=end, dataview=dataview, xform=xform,
options=options, columns_with_hxl=columns_with_hxl,
total_records=total_records
)
except NoRecordsFoundError:
pass
except SPSSIOError as e:
export = get_or_create_export(export_id, xform, export_type, options)
export.error_message = str(e)
export.internal_status = Export.FAILED
export.save()
report_exception("SAV Export Failure", e, sys.exc_info())
return export
# generate filename
basename = "%s_%s" % (
id_string, datetime.now().strftime("%Y_%m_%d_%H_%M_%S_%f"))
if remove_group_name:
# add 'remove group name' flag to filename
basename = "{}-{}".format(basename, GROUPNAME_REMOVED_FLAG)
if dataview:
basename = "{}-{}".format(basename, DATAVIEW_EXPORT)
filename = basename + "." + extension
# check filename is unique
while not Export.is_filename_unique(xform, filename):
filename = increment_index_in_filename(filename)
file_path = os.path.join(
username,
'exports',
id_string,
export_type,
filename)
# seek to the beginning as required by storage classes
temp_file.seek(0)
export_filename = default_storage.save(file_path,
File(temp_file, file_path))
temp_file.close()
dir_name, basename = os.path.split(export_filename)
# get or create export object
export = get_or_create_export(export_id, xform, export_type, options)
export.filedir = dir_name
export.filename = basename
export.internal_status = Export.SUCCESSFUL
# do not persist exports that have a filter
# Get URL of the exported sheet.
if export_type == Export.GOOGLE_SHEETS_EXPORT:
export.export_url = export_builder.url
# if we should create a new export is true, we should not save it
if start is None and end is None:
export.save()
return export
and this is where I call the tasks in the celery beat schedule:
CELERY_BEAT_SCHEDULE = {
'download_csv': {
'task': 'onadata.libs.utils.export_tools.generate_export',
# There are 4 ways we can handle time, read further
'schedule': crontab(minute='*'),
# If you're using any arguments
'args': ()
}
}
how do I pass parameters into the arguments for the tasks??
There is no way to pass argument dynamically in Celery Beat. I think your function is not suitable with periodic task.
Instead of giving a factor directly to the generate_export function, it must be changed to get the required items within the function. Or change to a simple asynchronous operation.
I faced a similar problem. The args field in beat_schedule is fixed at startup and does not change afterward.
But there is a hackish way to pass different arguments to your task.
Use the before_task_publish signal to add custom data in headers.
from celery.signals import before_task_publish
#before_task_publish.connect
def before_publish(sender=None, headers=None, body=None, **kwargs):
if sender == "tasks.generate_export":
headers["custom_args"] = {
"export_type": "some_val"
"xform": "some_val"
"export_id": get_export_id()
"options": options_dict
}
By default, Celery uses JSON serializer. So, make sure the data you add to headers are JSON serializable. Alternatively, you can use pickle to serialize the data, but it brings security concerns with it.
Now you can access these headers in a bound task.
#task(bind=True)
def generate_export(self):
args = self.request.get("custom_args", None)
# do something with args

Create Generator from queryset results - Python?

I am new to python I need to convert this following function to the generator to save memory, how can I achieve that?
question = <QuerySet [<Question: foobar?.>]>
for index, question in enumerate(questions):
if question["pk"] == self.pk:
try:
next_question = questions[index + 1]
if next_question["pk"]:
prev_next.update({"next" : next_question["pk"] })
except IndexError:
prev_next.update({"complete" : True })
try:
if index > 0:
previous_question = questions[index - 1]
if previous_question["pk"]:
prev_next.update({"prev" : previous_question["pk"] })
except IndexError:
pass
return prev_next

Build dynamic closure list from a list in order to pass it to OrderBy in Groovy

I am following this article to set the Order for sorting.
Excerpt from above article
class Language {
String name
boolean dynamic
String toString() { "name: $name, dynamic: $dynamic" }
}
def languages = [
new Language(name: 'Groovy', dynamic: true),
new Language(name: 'Java', dynamic: false),
new Language(name: 'Clojure', dynamic: true)
]
def list = ['name', 'dynamic']
sh = new GroovyShell()
closure = sh.evaluate("{ }")
def cList = list.collect { closure(it) }
println cList
// We order first on dynamic property and then name property.
def orderByDynamicAndName = new OrderBy([{ it.dynamic }, { it.name }])
Here, I would like to pass the list of closures dynamically from a list.
Say, there is a list and list may vary in element size in different applications / classes. This is main reason I wanted the dynamic closure list.
def list = ['name', 'dynamic']
From the above list, want to generate it as list of closure and pass it to OrderBy class as argument.
//Build closure list. But, not sure how to generate it from above list
def cList =
def orderByDynamicAndName = new OrderBy(cList)
Tried to refer this thread, but some how could not generate cList as desired
Tried to build cList as shown below; getting errors
def list = ['name', 'dynamic']
sh = new GroovyShell()
closure = sh.evaluate("{ fieldName -> \"it\".fieldName }")
def cList = list.collect { closure(it) }
Error:
Exception thrown
groovy.lang.MissingPropertyException: No such property: fieldName for class: java.lang.String
How to over come this?
class Language {
String name
boolean dynamic
String toString() { "name: $name, dynamic: $dynamic" }
}
def languages = [
new Language(name: 'Groovy', dynamic: true),
new Language(name: 'Java', dynamic: false),
new Language(name: 'Clojure', dynamic: true)
]
def list = ['dynamic', 'name']
def cList = list.collect{ propName-> { target-> target[propName] } }
def orderBy = new OrderBy(cList)
def sortedLanguages = languages.toSorted(orderBy)
println languages
println sortedLanguages
actually this expression
list.collect{ propName-> { target-> target[propName] } }
converts list of property names to list of closures
['dynamic', 'name'] => [ { target-> target['dynamic'] }, { target-> target['name'] } ]
and target is just a parameter name in the closure.
later, when we call sort, each closure { target-> target[propName] } will be called against an object in a sorting array and our closure returns the value by a property name.
After trial and error, below code worked for me in order to create the list of closures.
def list = ['dynamic', 'name']
def tempClosureString = list.collect { element -> "{it.$element}" }.join(',')
def cList = new GroovyShell().evaluate("[ $tempClosureString ]")
def orderByDynamicAndName = new OrderBy(cList)
I welcome if there are better alternatives.