On 5/8/20 4:12 PM, Nils Bruin wrote:
> On Thursday, April 30, 2020 at 9:20:00 AM UTC-7, Michael Orlitzky wrote:
> 
>     I feel the same way about functions like search_src() that badly
>     reimplement grep (even if they still work).
> 
> 
> I'm definitely in favour of keeping search_src and search_def. I find it
> *super* convenient to not have to think how to formulate the right grep
> query nor what the target of my grep should be. Grep is great, but
> writing regexp's comes with significant cognitive load, 

As another recent message just showed, the pattern used by search_def()
is wrong, and the definition of "regular" means that it can never be
right. If you want to know exactly *how* it's going to get your query
wrong, the implementation details are unavoidable. The fact that python
is an interpreted language and that things can be defined on-the-fly
only makes this attempt more embarrassing.

The following is a lot closer to correct, but you still need some way to
tell sage that the whitespace/underscore is optional; in other words,
unless we build in a search engine, you have to know a bit of regex to
tell it what you mean.

sage: load('searchdefs.py')
sage: search_submodules("fundamental.?group", sage)
sage.all.fundamental_group
sage.all_cmdline.fundamental_group
sage.categories.simplicial_sets.fundamental_group
sage.combinat.cluster_complex.fundamental_group
sage.combinat.root_system.extended_affine_weyl_group.FundamentalGroupOfExtendedAffineWeylGroup
sage.combinat.root_system.extended_affine_weyl_group.fundamental_group
sage.combinat.root_system.extended_affine_weyl_group.to_fundamental_group
sage.combinat.root_system.fundamental_group.FundamentalGroupElement
sage.combinat.root_system.fundamental_group.FundamentalGroupGL
sage.combinat.root_system.fundamental_group.FundamentalGroupGLElement
sage.combinat.root_system.fundamental_group.FundamentalGroupOfExtendedAffineWeylGroup
sage.combinat.root_system.fundamental_group.FundamentalGroupOfExtendedAffineWeylGroup_Class
sage.combinat.subword_complex.fundamental_group
sage.homology.all.fundamental_group
sage.homology.delta_complex.fundamental_group
sage.homology.examples.fundamental_group
sage.homology.homology_morphism.fundamental_group
sage.homology.homology_vector_space_with_basis.fundamental_group
sage.homology.simplicial_complex.fundamental_group
sage.homology.simplicial_complex_morphism.fundamental_group
sage.homology.simplicial_set.fundamental_group
sage.knots.knot.fundamental_group
sage.knots.link.fundamental_group
sage.misc.benchmark.fundamental_group
sage.repl.ipython_kernel.all_jupyter.fundamental_group
sage.sandpiles.sandpile.fundamental_group
sage.schemes.curves.affine_curve.fundamental_group
sage.schemes.curves.constructor.fundamental_group
sage.schemes.curves.projective_curve.fundamental_group
sage.schemes.curves.zariski_vankampen.fundamental_group
sage.schemes.elliptic_curves.ell_field.fundamental_group
sage.schemes.elliptic_curves.ell_finite_field.fundamental_group
sage.schemes.elliptic_curves.ell_number_field.fundamental_group
sage.schemes.elliptic_curves.ell_padic_field.fundamental_group
sage.schemes.elliptic_curves.ell_rational_field.fundamental_group
sage.schemes.elliptic_curves.isogeny_class.fundamental_group
sage.schemes.hyperelliptic_curves.constructor.fundamental_group
sage.schemes.hyperelliptic_curves.hyperelliptic_finite_field.fundamental_group
sage.schemes.hyperelliptic_curves.hyperelliptic_padic_field.fundamental_group
sage.schemes.hyperelliptic_curves.hyperelliptic_rational_field.fundamental_group
sage.schemes.plane_conics.con_finite_field.fundamental_group
sage.schemes.plane_conics.constructor.fundamental_group
sage.schemes.toric.divisor.fundamental_group
sage.tests.benchmark.fundamental_group

There are some duplicates in there (I've wasted enough time on it), but
it matches things that a regex never will. That function is implemented
by the following code, which belongs in a third-party library and not
sage itself because it has nothing to do with mathematics:

$ cat searchdefs.py
import inspect
import pkgutil
import re
import sys

def has_name(obj):
    if inspect.isclass(obj): return True
    if inspect.ismethod(obj): return True
    if inspect.isfunction(obj): return True
    if inspect.isgenerator(obj): return True
    if inspect.iscoroutine(obj): return True
    return False

def search_submodules(s, module, exclude=[]):
    found = []
    for modinfo in pkgutil.walk_packages(module.__path__,
                                         module.__name__ + '.'):

        if isinstance(s,str):
            s = re.compile(s, re.IGNORECASE)

        importer, module_name, ispkg = modinfo

        if ispkg or any(module_name.startswith(e) for e in exclude):
            # Don't load packages, or things explicitly excluded.
            continue

        if module_name not in sys.modules:
            loader = importer.find_module(module_name)
            with warnings.catch_warnings():
                warnings.simplefilter("ignore")
                try:
                    loader.load_module(module_name)
                except:
                    # A lot of things fail to load.
                    continue

        members = [ (k,v) for (k,v)
                    in inspect.getmembers(sys.modules[module_name],
                                          has_name)
                    if not k.startswith('_') ]

        # Covers Element = FooElement and things like that.
        maxdepth = 2
        depth = 0
        while len(members) > 0 and depth < maxdepth:
            submembers = []
            for (mname, member) in members:
                if s.search(mname) is not None:
                    result = module_name + "." + mname
                    if not result in found:
                        found.append(result)
                        print(result)
                try:
                    submembers += [ (k,v) for (k,v)
                                    in inspect.getmembers(member,
                                                          has_name)
                                    if not k.startswith('_') ]
                except:
                    pass
            members = submembers
            depth += 1

-- 
You received this message because you are subscribed to the Google Groups 
"sage-devel" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sage-devel+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sage-devel/eab7b8c2-ca94-d17f-4a0c-54bd210b4b2f%40orlitzky.com.

Reply via email to