Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(11564)

Side by Side Diff: Lib/inspect.py

Issue 20334: make inspect Signature hashable
Patch Set: Created 5 years, 1 month ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | Lib/test/test_inspect.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 """Get useful information from live Python objects. 1 """Get useful information from live Python objects.
2 2
3 This module encapsulates the interface provided by the internal special 3 This module encapsulates the interface provided by the internal special
4 attributes (co_*, im_*, tb_*, etc.) in a friendlier fashion. 4 attributes (co_*, im_*, tb_*, etc.) in a friendlier fashion.
5 It also provides some help for examining source code and class layout. 5 It also provides some help for examining source code and class layout.
6 6
7 Here are some of the useful functions provided by this module: 7 Here are some of the useful functions provided by this module:
8 8
9 ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(), 9 ismodule(), isclass(), ismethod(), isfunction(), isgeneratorfunction(),
10 isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(), 10 isgenerator(), istraceback(), isframe(), iscode(), isbuiltin(),
(...skipping 2221 matching lines...) Expand 10 before | Expand all | Expand 10 after
2232 elif kind == _VAR_KEYWORD: 2232 elif kind == _VAR_KEYWORD:
2233 formatted = '**' + formatted 2233 formatted = '**' + formatted
2234 2234
2235 return formatted 2235 return formatted
2236 2236
2237 def __repr__(self): 2237 def __repr__(self):
2238 return '<{} at {:#x} "{}">'.format(self.__class__.__name__, 2238 return '<{} at {:#x} "{}">'.format(self.__class__.__name__,
2239 id(self), self) 2239 id(self), self)
2240 2240
2241 def __hash__(self): 2241 def __hash__(self):
2242 hash_tuple = (self.name, int(self.kind)) 2242 return hash((self.name, self.kind, self._annotation, self._default))
2243
2244 if self._annotation is not _empty:
2245 hash_tuple += (self._annotation,)
2246 if self._default is not _empty:
2247 hash_tuple += (self._default,)
2248
2249 return hash(hash_tuple)
2250 2243
2251 def __eq__(self, other): 2244 def __eq__(self, other):
2252 return (issubclass(other.__class__, Parameter) and 2245 return (issubclass(other.__class__, Parameter) and
2253 self._name == other._name and 2246 self._name == other._name and
2254 self._kind == other._kind and 2247 self._kind == other._kind and
2255 self._default == other._default and 2248 self._default == other._default and
2256 self._annotation == other._annotation) 2249 self._annotation == other._annotation)
2257 2250
2258 def __ne__(self, other): 2251 def __ne__(self, other):
2259 return not self.__eq__(other) 2252 return not self.__eq__(other)
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
2534 2527
2535 if parameters is _void: 2528 if parameters is _void:
2536 parameters = self.parameters.values() 2529 parameters = self.parameters.values()
2537 2530
2538 if return_annotation is _void: 2531 if return_annotation is _void:
2539 return_annotation = self._return_annotation 2532 return_annotation = self._return_annotation
2540 2533
2541 return type(self)(parameters, 2534 return type(self)(parameters,
2542 return_annotation=return_annotation) 2535 return_annotation=return_annotation)
2543 2536
2537 def _hash_helper(self):
2538 return (tuple(param for param in self.parameters.values()
2539 if param.kind != _KEYWORD_ONLY),
2540 {param.name: param for param in self.parameters.values()
2541 if param.kind == _KEYWORD_ONLY},
2542 self._return_annotation)
2543
2544 def __hash__(self): 2544 def __hash__(self):
2545 hash_tuple = tuple(self.parameters.values()) 2545 params, kwo_params, return_annotation = self._hash_helper()
2546 if self._return_annotation is not _empty: 2546 return hash((params, frozenset(kwo_params.items()), return_annotation))
2547 hash_tuple += (self._return_annotation,)
2548 return hash(hash_tuple)
2549 2547
2550 def __eq__(self, other): 2548 def __eq__(self, other):
2551 if (not issubclass(type(other), Signature) or 2549 return (isinstance(other, Signature) and
2552 self.return_annotation != other.return_annotation or 2550 self._hash_helper() == other._hash_helper())
2553 len(self.parameters) != len(other.parameters)):
2554 return False
2555
2556 other_positions = {param: idx
2557 for idx, param in enumerate(other.parameters.keys())}
2558
2559 for idx, (param_name, param) in enumerate(self.parameters.items()):
2560 if param.kind == _KEYWORD_ONLY:
2561 try:
2562 other_param = other.parameters[param_name]
2563 except KeyError:
2564 return False
2565 else:
2566 if param != other_param:
2567 return False
2568 else:
2569 try:
2570 other_idx = other_positions[param_name]
2571 except KeyError:
2572 return False
2573 else:
2574 if (idx != other_idx or
2575 param != other.parameters[param_name]):
2576 return False
2577
2578 return True
2579 2551
2580 def __ne__(self, other): 2552 def __ne__(self, other):
2581 return not self.__eq__(other) 2553 return not self.__eq__(other)
2582 2554
2583 def _bind(self, args, kwargs, *, partial=False): 2555 def _bind(self, args, kwargs, *, partial=False):
2584 """Private method. Don't use directly.""" 2556 """Private method. Don't use directly."""
2585 2557
2586 arguments = OrderedDict() 2558 arguments = OrderedDict()
2587 2559
2588 parameters = iter(self.parameters.values()) 2560 parameters = iter(self.parameters.values())
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
2837 else: 2809 else:
2838 print('Line: {}'.format(lineno)) 2810 print('Line: {}'.format(lineno))
2839 2811
2840 print('\n') 2812 print('\n')
2841 else: 2813 else:
2842 print(getsource(obj)) 2814 print(getsource(obj))
2843 2815
2844 2816
2845 if __name__ == "__main__": 2817 if __name__ == "__main__":
2846 _main() 2818 _main()
OLDNEW
« no previous file with comments | « no previous file | Lib/test/test_inspect.py » ('j') | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+