##// END OF EJS Templates
New wildcard support. Lightly tested, so proceed with caution. We need to...
fperez -
Show More
@@ -0,0 +1,157 b''
1 # -*- coding: utf-8 -*-
2 """Support for wildcard pattern matching in object inspection.
3
4 $Id: OInspect.py 608 2005-07-06 17:52:32Z fperez $
5 """
6
7 #*****************************************************************************
8 # Copyright (C) 2005 Jörgen Stenarson <jorgen.stenarson@bostream.nu>
9 #
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
12 #*****************************************************************************
13
14 from IPython import Release
15 __author__ = "Jörgen Stenarson <jorgen.stenarson@bostream.nu>"
16 __license__ = Release.license
17
18 import __builtin__
19 import types
20 import re
21 import pprint
22 import exceptions
23 import pdb
24 import IPython.genutils as genutils
25
26 def create_typestr2type_dicts(dont_include_in_type2type2str=["lambda"]):
27 """Return dictionaries mapping lower case typename to type objects, from
28 the types package, and vice versa."""
29 typenamelist=[]
30 for tname in dir(types):
31 if tname[-4:]=="Type":
32 typenamelist.append(tname)
33 typestr2type={}
34 type2typestr={}
35 for tname in typenamelist:
36 name=tname[:-4].lower()
37 obj=getattr(types,tname)
38 typestr2type[name]=getattr(types,tname)
39 if name in dont_include_in_type2type2str:
40 type2typestr[obj]=name
41 return typestr2type,type2typestr
42
43 typestr2type,type2typestr=create_typestr2type_dicts()
44
45 def is_type(obj,typestr_or_type):
46 """is_type(obj,typestr_or_type) verifies if obj is of a certain type or
47 group of types takes strings as parameters of the for 'tuple'<->TupleType
48 'all' matches all types. TODO: Should be extended for choosing more than
49 one type
50 """
51 if typestr_or_type=="all":
52 return True
53 if type(typestr_or_type)==types.TypeType:
54 test_type=typestr_or_type
55 else:
56 test_type=typestr2type.get(typestr_or_type,False)
57 if test_type:
58 return isinstance(obj,test_type)
59 else:
60 return False
61
62 def show_hidden(str,showhidden=False):
63 """Return true for strings starting with single _ if showhidden is true."""
64 return showhidden or str.startswith("__") or not str.startswith("_")
65
66
67 class NameSpace(object):
68 """NameSpace holds the dictionary for a namespace and implements filtering
69 on name and types"""
70 def __init__(self,obj,namepattern="*",typepattern="all",ignorecase=True,
71 showhidden=True):
72 self.showhidden=showhidden #Hide names beginning with single _
73 self.object=obj
74 self.namepattern=namepattern
75 self.typepattern=typepattern
76 self.ignorecase=ignorecase
77 if type(obj)==type(dict()):
78 self._ns=obj
79 else:
80 try:
81 self._ns=self.object.__dict__
82 except exceptions.AttributeError:
83 self._ns=dict([(key,getattr(self.object,key))
84 for key in dir(self.object)])
85
86 def get_ns(self):
87 """Return name space dictionary with objects matching type and name patterns."""
88 return self.filter(self.namepattern,self.typepattern)
89 ns=property(get_ns)
90
91 def get_ns_names(self):
92 """Return list of object names in namespace that match the patterns."""
93 return self.ns.keys()
94 ns_names=property(get_ns_names,doc="List of objects in name space that "
95 "match the type and name patterns.")
96
97 def filter(self,namepattern,typepattern):
98 """Return dictionary of filtered namespace."""
99 def glob_filter(lista,namepattern,hidehidden,ignorecase):
100 """Return list of elements in lista that match pattern."""
101 pattern=namepattern.replace("*",".*")
102 if ignorecase:
103 reg=re.compile(pattern+"$",re.I)
104 else:
105 reg=re.compile(pattern+"$")
106 result=[x for x in lista if reg.match(x) and show_hidden(x,hidehidden)]
107 return result
108 ns=self._ns
109 #Filter namespace by the namepattern
110 all=[(x,ns[x]) for x in glob_filter(ns.keys(),namepattern,
111 self.showhidden,self.ignorecase)]
112 #Filter namespace by typepattern
113 all=[(key,obj) for key,obj in all if is_type(obj,typepattern)]
114 all=dict(all)
115 return all
116
117 #TODO: Implement dictionary like access to filtered name space?
118
119 def list_namespace(namespace,typepattern,filter,ignorecase=False,showhidden=False):
120 """Return dictionary of all objects in namespace that matches typepattern
121 and filter."""
122 patternlist=filter.split(".")
123 if len(patternlist)==1:
124 ns=NameSpace(namespace,namepattern=patternlist[0],typepattern=typepattern,
125 ignorecase=ignorecase,showhidden=showhidden)
126 return ns.ns
127 if len(patternlist)>1:
128 #This is where we can change if all objects should be searched or only moduleas
129 #Just change the typepattern to module to search only modules
130 ns=NameSpace(namespace,
131 namepattern=patternlist[0],
132 typepattern="all",ignorecase=ignorecase,showhidden=showhidden)
133 res={}
134 nsdict=ns.ns
135 for name,obj in nsdict.iteritems():
136 ns=list_namespace(obj,typepattern,".".join(patternlist[1:]),
137 ignorecase=ignorecase,showhidden=showhidden)
138 for inner_name,inner_obj in ns.iteritems():
139 res["%s.%s"%(name,inner_name)]=inner_obj
140 return res
141
142 def choose_namespaces(shell,cmds):
143 """Returns a list of namespaces modified by arguments."""
144 nslist=genutils.mkdict(user=shell.user_ns,internal=shell.internal_ns,
145 builtin=__builtin__.__dict__,alias=shell.alias_table)
146 default_list=["user","builtin"] # Should this list be a user option??
147 for cmd in cmds:
148 if cmd[0]=="-": #remove from defaultlist
149 if cmd[1:] in default_list:
150 default_list.remove(cmd[1:])
151 elif cmd[0]=="+":
152 if cmd[1:] not in default_list and cmd[1:]in nslist:
153 default_list.append(cmd[1:])
154 else:
155 if cmd in nslist:
156 default_list.append(cmd[1:])
157 return [nslist[x] for x in default_list]
@@ -1,7 +1,7 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Magic functions for InteractiveShell.
2 """Magic functions for InteractiveShell.
3
3
4 $Id: Magic.py 908 2005-09-26 16:05:48Z fperez $"""
4 $Id: Magic.py 919 2005-10-15 07:57:05Z fperez $"""
5
5
6 #*****************************************************************************
6 #*****************************************************************************
7 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
@@ -34,8 +34,9 b' from cStringIO import StringIO'
34 from IPython.Struct import Struct
34 from IPython.Struct import Struct
35 from IPython.Itpl import Itpl, itpl, printpl,itplns
35 from IPython.Itpl import Itpl, itpl, printpl,itplns
36 from IPython.FakeModule import FakeModule
36 from IPython.FakeModule import FakeModule
37 from IPython import OInspect
38 from IPython.PyColorize import Parser
37 from IPython.PyColorize import Parser
38 from IPython import OInspect
39 from IPython import wildcard
39 from IPython.genutils import *
40 from IPython.genutils import *
40
41
41 # Globals to be set later by Magic constructor
42 # Globals to be set later by Magic constructor
@@ -656,7 +657,63 b' Currently the magic system has the following functions:\\n"""'
656 re.match('(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups()
657 re.match('(pinfo )?(\?*)(.*?)(\??$)',parameter_s).groups()
657 if pinfo or qmark1 or qmark2:
658 if pinfo or qmark1 or qmark2:
658 detail_level = 1
659 detail_level = 1
659 self._inspect('pinfo',oname,detail_level=detail_level)
660 if "*" in oname:
661 self.magic_psearch(oname)
662 else:
663 self._inspect('pinfo',oname,detail_level=detail_level)
664
665 def magic_psearch(self, parameter_s=''):
666 """Search for object in namespaces by wildcard.
667
668 %psearch PATTERN [OBJECT TYPE] [-NAMESPACE]* [+NAMESPACE]* [-a] [-c]
669
670 Note: ? can be used as a synonym for %psearch, at the beginning or at
671 the end: both a*? and ?a* are equivalent to '%psearch a*'.
672
673 PATTERN
674
675 where PATTERN is a string containing * as a wildcard similar to its
676 use in a shell. The pattern is matched in all namespaces on the
677 search path. By default objects starting with a single _ are not
678 matched, many IPython generated objects have a single underscore. The
679 default is case insensitive matching. Matching is also done on the
680 attributes of objects and not only on the objects in a module.
681
682 [OBJECT TYPE]
683 Is the name of a python type from the types module. The name is given
684 in lowercase without the ending type, ex. StringType is written
685 string. By adding a type here only objects matching the given type are
686 matched. Using all here makes the pattern match all types (this is the
687 default).
688
689 [-NAMESPACE]* [+NAMESPACE]*
690 The possible namespaces are builtin, user, internal, alias. Where
691 builtin and user are default. Builtin contains the python module
692 builtin, user contains all imported namespaces, alias only contain the
693 shell aliases and no python objects, internal contains objects used by
694 IPython. The namespaces on the search path are removed by -namespace
695 and added by +namespace.
696
697 [-a] makes the pattern match even objects with a single underscore.
698 [-c] makes the pattern case sensitive.
699
700 Examples:
701
702 %psearch a* list objects beginning with an a
703 %psearch a* function list all functions beginning with an a
704 %psearch re.e* list objects beginning with an e in module re
705 %psearch r*.e* list objects that starts with e in modules starting in r
706 %psearch r*.* string list all strings in modules beginning with r
707
708 Case sensitve search:
709
710 %psearch a* -c list all object beginning with lower case a
711
712 Show objects beginning with a single _:
713
714 %psearch _* -a list objects beginning with underscore"""
715
716 self.shell.inspector.psearch(parameter_s,shell=self.shell)
660
717
661 def magic_who_ls(self, parameter_s=''):
718 def magic_who_ls(self, parameter_s=''):
662 """Return a sorted list of all interactive variables.
719 """Return a sorted list of all interactive variables.
@@ -6,7 +6,7 b' Uses syntax highlighting for presenting the various information elements.'
6 Similar in spirit to the inspect module, but all calls take a name argument to
6 Similar in spirit to the inspect module, but all calls take a name argument to
7 reference the name under which an object is being read.
7 reference the name under which an object is being read.
8
8
9 $Id: OInspect.py 575 2005-04-08 14:16:44Z fperez $
9 $Id: OInspect.py 919 2005-10-15 07:57:05Z fperez $
10 """
10 """
11
11
12 #*****************************************************************************
12 #*****************************************************************************
@@ -26,9 +26,10 b" __all__ = ['Inspector','InspectColors']"
26 import inspect,linecache,types,StringIO,string
26 import inspect,linecache,types,StringIO,string
27
27
28 # IPython's own
28 # IPython's own
29 from IPython import PyColorize
29 from IPython.Itpl import itpl
30 from IPython.Itpl import itpl
31 from IPython.wildcard import choose_namespaces,list_namespace
30 from IPython.genutils import page,indent,Term
32 from IPython.genutils import page,indent,Term
31 from IPython import PyColorize
32 from IPython.ColorANSI import *
33 from IPython.ColorANSI import *
33
34
34 #****************************************************************************
35 #****************************************************************************
@@ -396,3 +397,46 b' class Inspector:'
396 if output:
397 if output:
397 page(output)
398 page(output)
398 # end pinfo
399 # end pinfo
400
401 def psearch(self,oname='',formatter = None,shell=None):
402 """Search namespaces with wildcards for objects.
403
404 Optional arguments:
405
406 - oname: rest of the commandline containging pattern and options
407
408 - formatter: Not used
409
410 - shell: The shell object from the Magic class. Needed to
411 access the namespaces
412
413 """
414 option_list=["-c","-a"]
415 import pdb
416 # pdb.set_trace()
417 cmds=oname.split()
418 filter=""
419 type_pattern="all"
420 ns_cmds=[]
421 options=[x for x in cmds if x in option_list]
422 ignorecase="-c" not in options
423 showhidden="-a" in options
424 ns_cmds=[x for x in cmds if x[0] in "-+" and x not in option_list]
425 cmds=[x for x in cmds if x[0] not in "-+"]
426 if len(cmds)>2: #assume we want to choose name spaces.
427 #Rather poor design forces the use of a typepattern in order to choose name spaces
428 cmds=cmds[:2]
429 if len(cmds)==2:
430 filter,type_pattern=cmds
431 elif len(cmds)==1:
432 filter=cmds[0].strip()
433
434 do_list=choose_namespaces(shell,ns_cmds)
435
436 search_result=[]
437 for ns in do_list:
438 tmp_res=list(list_namespace(ns,type_pattern,filter,ignorecase=ignorecase,showhidden=showhidden))
439 search_result.extend(tmp_res)
440 search_result.sort()
441
442 page("\n".join(search_result))
@@ -1,10 +1,19 b''
1 2005-10-15 Fernando Perez <Fernando.Perez@colorado.edu>
2
3 * IPython/Magic.py (magic_psearch): new support for wildcard
4 patterns. Now, typing ?a*b will list all names which begin with a
5 and end in b, for example. The %psearch magic has full
6 docstrings. Many thanks to Jörgen Stenarson
7 <jorgen.stenarson-AT-bostream.nu>, author of the patches
8 implementing this functionality.
9
1 2005-09-27 Fernando Perez <Fernando.Perez@colorado.edu>
10 2005-09-27 Fernando Perez <Fernando.Perez@colorado.edu>
2
11
3 * Manual: fixed long-standing annoyance of double-dashes (as in
12 * Manual: fixed long-standing annoyance of double-dashes (as in
4 --prefix=~, for example) being stripped in the HTML version. This
13 --prefix=~, for example) being stripped in the HTML version. This
5 is a latex2html bug, but a workaround was provided. Many thanks
14 is a latex2html bug, but a workaround was provided. Many thanks
6 to George K. Thiruvathukal <gthiruv AT luc.edu> for the detailed
15 to George K. Thiruvathukal <gthiruv-AT-luc.edu> for the detailed
7 help, and Michael Tobis <mtobis AT gmail.com> for getting the ball
16 help, and Michael Tobis <mtobis-AT-gmail.com> for getting the ball
8 rolling. This seemingly small issue had tripped a number of users
17 rolling. This seemingly small issue had tripped a number of users
9 when first installing, so I'm glad to see it gone.
18 when first installing, so I'm glad to see it gone.
10
19
@@ -76,7 +85,7 b''
76
85
77 * IPython/iplib.py (InteractiveShell.__init__): Trap exception if
86 * IPython/iplib.py (InteractiveShell.__init__): Trap exception if
78 os.getcwd() fails at init time. Thanks to patch from David Remahl
87 os.getcwd() fails at init time. Thanks to patch from David Remahl
79 <chmod007 AT mac.com>.
88 <chmod007-AT-mac.com>.
80 (InteractiveShell.__init__): prevent certain special magics from
89 (InteractiveShell.__init__): prevent certain special magics from
81 being shadowed by aliases. Closes
90 being shadowed by aliases. Closes
82 http://www.scipy.net/roundup/ipython/issue41.
91 http://www.scipy.net/roundup/ipython/issue41.
@@ -174,7 +183,7 b''
174 slightly modified version of the patch in
183 slightly modified version of the patch in
175 http://www.scipy.net/roundup/ipython/issue34, which also allows me
184 http://www.scipy.net/roundup/ipython/issue34, which also allows me
176 to remove the previous try/except solution (which was costlier).
185 to remove the previous try/except solution (which was costlier).
177 Thanks to Gaetan Lehmann <gaetan.lehmann AT jouy.inra.fr> for the fix.
186 Thanks to Gaetan Lehmann <gaetan.lehmann-AT-jouy.inra.fr> for the fix.
178
187
179 2005-06-08 Fernando Perez <fperez@colorado.edu>
188 2005-06-08 Fernando Perez <fperez@colorado.edu>
180
189
@@ -9053,4 +9053,13 b' Sakkis <'
9053 gsakkis-AT-eden.rutgers.edu>
9053 gsakkis-AT-eden.rutgers.edu>
9054 \family default
9054 \family default
9055 New matcher for tab-completing named arguments of user-defined functions.
9055 New matcher for tab-completing named arguments of user-defined functions.
9056 \layout List
9057 \labelwidthstring 00.00.0000
9058
9059 J�rgen\SpecialChar ~
9060 Stenarson
9061 \family typewriter
9062 <jorgen.stenarson-AT-bostream.nu>
9063 \family default
9064 Wildcard support implementation for searching namespaces.
9056 \the_end
9065 \the_end
General Comments 0
You need to be logged in to leave comments. Login now