##// END OF EJS Templates
Further tidying up of IPython.utils.wildcard.
Thomas Kluyver -
Show More
@@ -1,134 +1,125 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Support for wildcard pattern matching in object inspection.
3 3
4 4 Authors
5 5 -------
6 6 - Jörgen Stenarson <jorgen.stenarson@bostream.nu>
7 7 """
8 8
9 9 #*****************************************************************************
10 10 # Copyright (C) 2005 Jörgen Stenarson <jorgen.stenarson@bostream.nu>
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #*****************************************************************************
15 15
16 16 import re
17 17 import types
18 18
19 19 from IPython.utils.dir2 import dir2
20 20
21 21 def create_typestr2type_dicts(dont_include_in_type2typestr=["lambda"]):
22 22 """Return dictionaries mapping lower case typename (e.g. 'tuple) to type
23 23 objects from the types package, and vice versa."""
24 24 typenamelist = [tname for tname in dir(types) if tname.endswith("Type")]
25 25 typestr2type, type2typestr = {}, {}
26 26
27 27 for tname in typenamelist:
28 28 name = tname[:-4].lower() # Cut 'Type' off the end of the name
29 29 obj = getattr(types, tname)
30 30 typestr2type[name] = obj
31 31 if name not in dont_include_in_type2typestr:
32 32 type2typestr[obj] = name
33 33 return typestr2type, type2typestr
34 34
35 35 typestr2type, type2typestr = create_typestr2type_dicts()
36 36
37 37 def is_type(obj, typestr_or_type):
38 38 """is_type(obj, typestr_or_type) verifies if obj is of a certain type. It
39 39 can take strings or actual python types for the second argument, i.e.
40 40 'tuple'<->TupleType. 'all' matches all types.
41 41
42 42 TODO: Should be extended for choosing more than one type."""
43 43 if typestr_or_type=="all":
44 44 return True
45 45 if type(typestr_or_type) == types.TypeType:
46 46 test_type = typestr_or_type
47 47 else:
48 48 test_type = typestr2type.get(typestr_or_type, False)
49 49 if test_type:
50 50 return isinstance(obj, test_type)
51 51 return False
52 52
53 53 def show_hidden(str,show_all=False):
54 54 """Return true for strings starting with single _ if show_all is true."""
55 55 return show_all or str.startswith("__") or not str.startswith("_")
56 56
57 57 class NameSpace(dict):
58 58 """NameSpace holds the dictionary for a namespace and implements filtering
59 59 on name and types"""
60 60
61 61 @classmethod
62 62 def from_object(cls, obj, *args, **kwargs):
63 63 """Instantiate a namespace by constructing a dictionary of an object's
64 64 attributes. A class method, returns a new NameSpace instance."""
65 65 ns = cls()
66 66 for key in dir2(obj):
67 67 if isinstance(key, basestring):
68 68 # This seemingly unnecessary try/except is actually needed
69 69 # because there is code out there with metaclasses that
70 70 # create 'write only' attributes, where a getattr() call
71 71 # will fail even if the attribute appears listed in the
72 72 # object's dictionary. Properties can actually do the same
73 73 # thing. In particular, Traits use this pattern
74 74 try:
75 75 ns[key] = getattr(obj,key)
76 76 except AttributeError:
77 77 pass
78 78 return ns
79 79
80 80 def filter(self, name_pattern="*", type_pattern="all", ignore_case=True,
81 81 show_all=True):
82 82 """Return a dictionary of the namespace filtered by regex pattern and
83 83 item type."""
84 84 pattern=name_pattern.replace("*",".*").replace("?",".")
85 85 if ignore_case:
86 86 reg=re.compile(pattern+"$",re.I)
87 87 else:
88 88 reg=re.compile(pattern+"$")
89
90 return dict((key,obj) for key,obj in self.iteritems() if all((\
91 reg.match(key), # Matches pattern
92 show_hidden(key, show_all), # Not _hidden
93 is_type(obj, type_pattern) )) ) # Correct type
89
90 # Check each one matches regex; shouldn't be hidden; of correct type.
91 return dict((key,obj) for key,obj in self.iteritems() if reg.match(key)\
92 and show_hidden(key, show_all)\
93 and is_type(obj, type_pattern))
94 94
95 def list_namespace(namespace,type_pattern,filter,ignore_case=False,show_all=False):
95 def list_namespace(namespace, type_pattern, filter, ignore_case=False, show_all=False):
96 96 """Return dictionary of all objects in a namespace dictionary that match
97 97 type_pattern and filter."""
98 98 pattern_list=filter.split(".")
99 99 ns = NameSpace(namespace)
100 return _list_namespace(ns, type_pattern, pattern_list, ignore_case,show_all)
101 # This function is a more convenient wrapper around the recursive one below.
102
103 def _list_namespace(ns, type_pattern, pattern_list, ignore_case=False, show_all=False):
104 """Return dictionary of objects in a namespace which match type_pattern
105 and filter (pattern_list).
106
107 This is a recursive function behind list_namespace, which is intended to be
108 the public interface. Unlike that function, this expects a NameSpace
109 instance as the first argument, and the name pattern split by '.'s."""
100 110 if len(pattern_list) == 1:
101 return ns.filter(name_pattern=pattern_list[0], type_pattern=type_pattern,
102 ignore_case=ignore_case, show_all=show_all)
111 return ns.filter(name_pattern=pattern_list[0], type_pattern=type_pattern,
112 ignore_case=ignore_case, show_all=show_all)
103 113 else:
104 114 # This is where we can change if all objects should be searched or
105 115 # only modules. Just change the type_pattern to module to search only
106 116 # modules
107 117 filtered = ns.filter(name_pattern=pattern_list[0], type_pattern="all",
108 118 ignore_case=ignore_case, show_all=show_all)
109 119 results = {}
110 120 for name, obj in filtered.iteritems():
111 ns = list_object_namespace(obj, type_pattern, pattern_list[1:],
112 ignore_case=ignore_case, show_all=show_all)
113 for inner_name, inner_obj in ns.iteritems():
114 results["%s.%s"%(name,inner_name)] = inner_obj
115 return results
116
117 def list_object_namespace(ns_obj, type_pattern, pattern_list, ignore_case=False,
118 show_all=False):
119 """Return dictionary of all attributes of an object which match type_pattern
120 and filter (pattern_list)."""
121 ns = NameSpace.from_object(ns_obj)
122 if len(pattern_list) == 1:
123 return ns.filter(name_pattern=pattern_list[0], type_pattern=type_pattern,
124 ignore_case=ignore_case, show_all=show_all)
125 else:
126 filtered = ns.filter(name_pattern=pattern_list[0], type_pattern="all",
127 ignore_case=ignore_case, show_all=show_all)
128 results = {}
129 for name, obj in filtered.iteritems():
130 ns = list_object_namespace(obj, type_pattern, pattern_list[1:],
131 ignore_case=ignore_case, show_all=show_all)
121 ns = _list_namespace(NameSpace.from_object(obj), type_pattern,
122 pattern_list[1:], ignore_case=ignore_case, show_all=show_all)
132 123 for inner_name,inner_obj in ns.iteritems():
133 124 results["%s.%s"%(name,inner_name)] = inner_obj
134 125 return results
General Comments 0
You need to be logged in to leave comments. Login now