You’re right but it’s in bench console that I want to test.
I’m going into my frappe repo, then bench console and in this new python console I try to run the function erpnext.stock.doctype.material_request.material_request.make_purchase_order
The return from console is this error NameError: name 'erpnext' is not defined
So I execute import erpnext and retry
Now the error is AttributeError: 'module' object has no attribute 'stock'
So my question is how should I initialize this console to import all erpnext packages ?
I’m running it from a frappe-bench but in a production environment.
I also run it with --site parameter bench --site mysite.com console
So if I understand you all environment should be here ?
I don’t have any import to execute ?
From my php experience with composer we have to call a class loader to load all classes in one run, so I’d like to know if we have an equivalent loader to run in bench console.
Just like with any py controller, you’ll have to import anything you want to use. If there’s a way to have bench import some set list on console start, I’d be interested to learn about it.
This question is subsidiary since it could help me to understand how the “application” is booted to load all necessary procedures.
And it’s a good one to understand the frappe architecture.
Gotcha. Here goes:
From the browser a callback is written addressing either a dotted.path.to.method or a class method.
Consider the following:
frappe.call({
method: "company_abbr",
doc: frm.doc, // class method, eg "self"
// method: "dotted.path.to.method",
// args: {"company_abbr": frm.doc.company}
}).done((r) => {
frm.set_value( "comapny_abbr", r.message.abbr);
}).fail((f) => {
console.log(f);
}); // 'always' and 'then' are also acceptable and useful
A common gotcha is that the API really wants keyword arguments, so if you python method definition looks like def get_co_abbr(abbr): it’s going to fail. The keyword its expecting is company_abbrin this example.
#correct python method definition, not a class method
@frappe.whitelist() # required
def get_co_abbr(company_abbr):
# method definition that is a class method
# whitelist not required
def get_co_abbr(self):
self.company_abbr = frappe.get_value ...
return self.company_abbr
For a return value (callback), the return statement of the python method is added to r.message as an attribute. “r” is a convention, not a requirement, but it makes your code more readable and consistent should you desire to contribute. In this example the return would look like return {"abbr": abbr}. If you wanted to return it without a keyword return abbr where abbr is a variable holding the value you want should work just fine.
Note that the class method of callbacks only work on doctypes and the dotted.path.type is required for pages.
That’s the basics anyway. To your question about how to access something in a repl-like environment once a browser has made a callback? I’d consider using pdb or webpdb, which are built in python debugging tools that allow you to step through your code once it’s hit a method. I’m not an expert in either of those, but there are some folks on the forum that do use them as part of their normal workflows.