C++ namespace imported as a "class" instead of "module"

Hello,

I have a simple class, “Trial” living under “mytry” namespace.
I would like to import “Trial” into my main scope just like I import TH1D from ROOT.
So I wish to do something like:

>>> from ROOT.mytry import *
>>> my_instance = Trial()

But I am having a trouble that “mytry” is recognized as a class instead of a module.
This seems to prevent me to import “Trial” from “mytry”.
Detailed description follows below.

Here’s a header file & LinkDef.h for my class:

Trial.hh

#ifndef TRIAL_HH
#define TRIAL_HH
namespace mytry{
  class Trial{
  public:
    Trial(){};
    virtual ~Trial(){};
  };
}
#endif

LinkDef.h

#ifdef __CINT__
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ namespace mytry;
#pragma link C++ class mytry::Trial+;
#endif

In addition I use rootcint to generate CINT dictionary source code and compile/link together.
As a result, I can import “Trial” in PyROOT:

>>> from ROOT import mytry
>>> mytry.Trial
<class '__main__.mytry::Trial'>

But I cannot “import Trial” from “mytry” namespace:

>>> import ROOT
>>> from ROOT.mytry import *
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named mytry
>>> print ROOT.mytry
<class 'ROOT.mytry'>

As said above, “mytry” is recognized as a “class” instead of a module.

Is there a way to make PyROOT recognize “mytry” as a module so that I can import “Trial” into main?

Thank you for your time and help.
Please let me know if something is unclear.

Kazu

Kazu,

yes, all C++ namespaces are represented as classes, as modules can not be dynamically extended. Classes can be imported from, but for this specific use, there are two chicken-and-egg problems. First, mytry isn’t known (being top-level) until it is accessed, and second the same is true for Trial (as it is also created lazily).

So, this is the most that works today:[code]import ROOT

if not auto-loadable, load dict for mytry here

ROOT.mytry # bring mytry alive
from ROOT.mytry import Trial # tickle lazy creation of Trial, ‘*’ won’t do that
my_instance = Trial() # use …[/code]
This is all on the TODO list to fix (e.g. the latter just needs to define all), but has been in flux as ROOT has been improving unloading and laziness in the back.

Cheers,
Wim

Dear Wim,

Thank you for your reply!
From the separate post, that’s what I hoped to be a solution.
Here’s a post I found: ‘using namespace’ equivalent

But this does not seem to work. In particular, I tried and get the following error:

>>> import ROOT
>>> ROOT.mytry
<class 'ROOT.mytry'>
>>> from ROOT.mytry import Trial
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named mytry

What am I missing?
Thank you for your time and I’m sorry for questioning further.

Kazu

Kazu,

which version of ROOT are you using?

Cheers,
Wim

Hi Wim,

I am using 5.34.07 on my machine.

Best regards.

Kazu

Kazu,

ouch; turns out to be a bug that only happens if the namespace is auto-loaded (it’s not a problem if the namespace’s dictionary is loaded separately). Workaround is:[code]import ROOT, sys
sys.modules[‘ROOT.mytry’] = ROOT.mytry
from ROOT.mytry import Trial

etc.[/code]

Will fix in a bit …

Thanks,
Wim

I see. Thank you very much for debugging and sharing the result.
I am looking forward to a fix!

Best regards.

Kazu

Kazu,

it has improved somewhat, as in this now works:import ROOT from ROOT.mytry import TrialI really don’t see how I can get away w/o that first ‘import ROOT’ (chicken-and-egg problem). I may be able to do ‘from ROOT.mytry import ', but my first couple of tries were all unsatisfactory so far: there is a lot of laziness builtin to PyROOT and ROOT/meta and '’ would attempt to tickle all and everything, leading to bad side-effects.

Cheers,
Wim

Hi Wim,

Thanks for the update. This is good enough for my package users who use PyROOT.

Is this in the development branch?

Kazu

Kazu,

is in master and v5-34-00-patches.

Cheers,
Wim