inlab-geo/espresso

Tab completion

Closed this issue · 3 comments

If I open ipython/similar and do

import cofi_espresso
cofi_espresso.<TAB>

or

from cofi_espresso import <TAB>

I see a list containing both modules and classes (e.g. both xray_tomography and XrayTomography). I think this is confusing and it would be better just to see the class.

I think this is related to this SO issue.

I'm not sure what the best solution is. However, I found the following email that I had sent Hannes when he first started looking into how to do this:

Re. importlib: I think you can do something like the following. 


inversiontestproblems/
|    __init__.py                 <— (A)
|    contrib/   
|    |    __init__.py            <— (blank)
|    |    first-example-directory/
|    |    |    __init__.py       <— (B)
|    |    another-directory/
|    |    |    __init__.py       <— (C)
|    |    |    data/
|    |    |    |    __init__.py  <— (blank)
|    |    |    |    data.dat


with the following __init__.py files

__init__.py (A):

import importlib
# Get the object ‘Ex1’ from ‘first-example-directory’ and rename it ‘ExampleOne'
ExampleOne = getattr(importlib.import_module("inversiontestproblems.contrib.first-example-directory”), “Ex1”)
# Get the object ‘MyTestProblem’ from ‘another-directory’ and rename it ‘ExampleTwo'
ExampleTwo = getattr(importlib.import_module(“inversiontestproblems.contrib.another-directory”),”MyTestProblem”)


__init__.py (B):

class Ex1:
    def __init__(self):
     …….



__init__.py (C):

from importlib.resources import open_text

def loaddata(file):
    # Code to read a data file
    with open(file,’r’) as fp:
          fp.readlines()
          …..
     return data


class MyTestProblem:
    def __init__(self):
          …..
     def _getdata(self):
         # Automagically resolve location/type of distributed data and hand to loaddata()
         data = loaddata(open_text(__package__+”.data”,”data.dat”))
         …...
     



Then users can do something like:

from inversiontestproblems import ExampleOne as example
ex = example()
ex.forward()

and simply changing ‘ExampleOne’ to ‘ExampleTwo’ should work seamlessly.

I think there are variations on this theme, e.g. you can do something like

import module as ClassName
ClassName = ClassName.ClassName

Keen to hear thoughts -- I'm not sure what the right thing to do is!

jwhhh commented

This SO answer looks promising.

But this only helps

import cofi_espresso
cofi_espresso.<TAB>

not

from cofi_espresso import <TAB>

An experimental implementation can be found in this tab_completion branch.

I think importlib can fix this, just not entirely sure if it's worth it (not following the convention to achieve this). Maybe there isn't really a convention thing in Python anyway. Will update with importlib soon.

jwhhh commented

Using importlib to manually import the contribution classes doesn't quite work. Am I missing something here? @valentineap

The change for using importlib is here: 0c76f75
The previous change with del <contrib_path> is here: f8f652b

I'll take another look next week.

jwhhh commented

This SO answer looks promising.

But this only helps

import cofi_espresso
cofi_espresso.<TAB>

not

from cofi_espresso import <TAB>

An experimental implementation can be found in this tab_completion branch.

I think importlib can fix this, just not entirely sure if it's worth it (not following the convention to achieve this). Maybe there isn't really a convention thing in Python anyway. Will update with importlib soon.

It seems impossible to hide the files and folders when you do from cofi_espresso import <TAB>. Because when you do from <module> import <something>, it checks files/folders under the module, instead of checking the namespaces (names available after you import the module).

Alternatively, adding underscores to the contrib folder names might make sense (so that even though they are still displayed, they are not at the front):

In [1]: from cofi_espresso import <TAB>
                                   EspressoProblem      GravityDensity       SimpleRegression     _espresso_problem    _simple_regression   __all__              __name__            
                                   exceptions           list_problem_names() utils                _fmm_tomography      _version             __doc__              __package__         
                                   FmmTomography        list_problems        XrayTomography       _gravity_density     _xray_tomography     __file__             __version__