Yes, It worked
i need to change frappe.utils.format_date function but none of hooks.py method and monkey_patching method worked for me!!!
in second method when i use function just after load_monkey_patches()
, value has been returned from my new function but in other places such as site, value returned from frappe.
any idea?
can you explain with some examples for build_my_thing works?
could you please explain more what the problem you did?
Write these in your custom app
Override class method:
from erpnext.selling.doctype.sales_order.sales_order import SalesOrder
SalesOrder.validate = yourmethod
Override standard method:
from frappe import utils
utils.cstr = yourmethod
Where in the init.py file ?
Can someone please confirm frappe.core doctype classes are also part of this? I am trying to override “UserPermission” class (from frappe.core.doctype) and it is not working. However docTypes in ERPNext I am able to.
There is a hook for that.
Let’s continue this discussion
Monkey patch is ok. Using hooks.py is ok.
Now let’s get into more details.
There is a non-Class method that I override successfully.
File to be overridden: frappe.desk.reportview.py
Method to be overridden: get_form_params(), the original code is shown below:
def get_form_params():
“”“Stringify GET request parameters.”“”
data = frappe._dict(frappe.local.form_dict)
clean_params(data)
validate_args(data)
return data
The clean_params(data) and validate_args(data) will call other functions within reportview.py.
Now I want to add a custom function just before
return data
The problem is that I need to copy the whole of reportview.py to my new override.py because some function doesn’t do a “return”; “data” will be lost during the chain of calls.
The new block looks like:
def get_form_params():
“”“Stringify GET request parameters.”“”
data = frappe._dict(frappe.local.form_dict)
frappe.desk.reportview.clean_params(data) ← added frappe.desk.reportview. so it will reference the original reportview.py
frappe.desk.reportview.validate_args(data) ← added frappe.desk.reportview. so it will reference the original reportview.py
new_function(data) ← the new function I need to process “data”
return data
I don’t want to copy N functions from reportview.py to override.py because it will be a nightmare to maintain.
I’m kinda stuck.
Any advice?
I rise a problem…
This solution works only if your sites have the same app installed, because monkeypatch is applied on the same ERP instance and affects multiple sites.
The side effect of this solution result in calling a module that could be not installed in other sites and produce an error.
For example, suppose app1 override a method of erpnext, and suppose to have the following configuration:
- site1: erpnext, app1
- site2: erpnext, app2
Monkeypatch will affect both the sites not only site1, and produce an error in site2 because frappe couldn’t not find app1 because the instance is the same…
Frappe’s team should take in charge this request, fix should be applied in Frappe core and we don’t have to think to complex and futile workaroud because, solution should came from Frappe.
monkey patch to overrides report functions ?
i did in my hook.py
import erpnext.stock.report.stock_balance.test_stock_balance
import custom_app.update_table
erpnext.stock.report.stock_balance.test_stock_balance.TestStockBalance = custom_app.update_table.TestStockBalance
and create edit my app.init.py file like monkey patch put i do not know in monkey patch folder what should i do
Well described the problem of the framework.
Python monkey patch whether in hooks.py or init.py is still not the right way to go IMHO.
At least (if not multi extension), the overriding of non-class method should be in a proper hook point (similary to overriding the whitelisted method) so there is no need for work around.
Note: I saw this problem araised from time to time, hope Framework team has permanent fix soon.