Darren Dale wrote:
I am working on reorganizing our config system to work with Fernando's tconfig, and I could use some advice. Currently, a lot of the configuration code lives in __init__.py and rcsetup.py. I am thinking of a layout like this:
api # mpl's entry point: all imports come from here
checkdep # checks for dependencies like ghostscript, dvipng, etc.
configobj # external project, required by tconfig
cutils # configuration utilities, like get_home, is_writable_dir, etc.
mplconfig.py # reads new config files using tconfig
mpltraits # defines mpl traits like colors, markers, linestyles
rcparams # configuration using old matplotlibrc files
rcsetup # provides defaults, setup, for rcparams
tconfig # Fernando's traited config, requires traits and configobj
verbose # defines the Verbose class used throughout mpl
the __init__ file would import from config.api: rcParams, which would be the existing dict if the old config system is active, or a dict wrapping the new config object, along with rc, rcdefaults, etc.
Does this sound reasonable, or could anyone suggest a better organization? Should every trait used by mpl be defined in mpltraits, that is, should mpltraits provide an interface to enthought traits? Or should mpltraits only provide traits that are not predefined by enthought? Is config/ a bad place for verbose?
I don't see any point in having mpltraits provide anything that is predefined; at most you could list in comments or the docstring the predefined traits that are being used.
The Verbose class could be more generally useful than just for mpl config, but this is true of cbook and of at least some of the things you will put in cutils. Your proposed config location is OK, but I wonder whether it would not be better to consolidate all of these utility things that have no dependencies into a single namespace that can be imported without pulling in the whole mpl configuration machinery at the same time.
I *think* that maybe this is the big advantage of using a minimal matplotlib/__init__.py and letting matplotlib/api.py be the normal entry point. It means you can do "from matplotlib import cbook", for example, and nothing gets executed other than cbook (in the extreme case where matplotlib/__init__.py is empty). If you have all sorts of things in matplotlib/__init__.py, including the global rcParams, then you can't access cbook.is_stringlike, for example, without doing the whole creation of rcParams. So, the approach of using minimal __init__.py at the base package level helps reduce the problems of circular imports and makes the whole package structure more modular.
The problem for us in making that change is that all present code (user and internal) that reads "import matplotlib as mpl", for example, would have to be changed to "import matplotlib.api as mpl". This is easy to do internally, but the breakage of user code is a problem.
I'm an amateur; I trust the experts will promptly straighten out any errors in my conjectures above.