Bench console how to test python scripts

I would like to debug a doctype function

But when I’m calling it I get this error
NameError: name 'erpnext' is not defined

So how should I initialize bench console to use any doctype procedure ?


Use bench console command


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 ?

bench console should be run from frappe-bench directory.

I’m running it from a frappe-bench but in a production environment.

I also run it with --site parameter bench --site 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.

Thanks :slight_smile:

1 Like

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.


Also of note, the working directory of the console is /sites, whcih can be confirmed with:

import os

This means if you want to open a file, it needs to referenced from /sites.


Yes it’s exactly the point @peterg,

How the javascript are calling python function ?

Which console do you mean? Bench console (where the bench is named pinoak, normally frappe-bench) where python is executed…


Or browser console where javascript is executed

1 Like

In the python console, not in the browser javascript console.

So your question is “how does the frappe framework translate javascript callbacks into python methods?”

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 or a class method.
Consider the following:{
	method: "company_abbr",
	 doc: frm.doc, // class method, eg "self"
    // method: "",
   // args: {"company_abbr":}
}).done((r) => {
		frm.set_value( "comapny_abbr", r.message.abbr);
}).fail((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.