mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	Patch #1006219: let inspect.getsource show '@' decorators and add tests for
this (which are rather ugly, but it'll have to do until test_inspect gets a major overhaul and a conversion to unittest). Thanks Simon Percivall!
This commit is contained in:
		
							parent
							
								
									318a12eb01
								
							
						
					
					
						commit
						c473c99d16
					
				
					 3 changed files with 47 additions and 2 deletions
				
			
		| 
						 | 
					@ -433,7 +433,7 @@ def findsource(object):
 | 
				
			||||||
        if not hasattr(object, 'co_firstlineno'):
 | 
					        if not hasattr(object, 'co_firstlineno'):
 | 
				
			||||||
            raise IOError('could not find function definition')
 | 
					            raise IOError('could not find function definition')
 | 
				
			||||||
        lnum = object.co_firstlineno - 1
 | 
					        lnum = object.co_firstlineno - 1
 | 
				
			||||||
        pat = re.compile(r'^(\s*def\s)|(.*\slambda(:|\s))')
 | 
					        pat = re.compile(r'^(\s*def\s)|(.*\slambda(:|\s))|^(\s*@)')
 | 
				
			||||||
        while lnum > 0:
 | 
					        while lnum > 0:
 | 
				
			||||||
            if pat.match(lines[lnum]): break
 | 
					            if pat.match(lines[lnum]): break
 | 
				
			||||||
            lnum = lnum - 1
 | 
					            lnum = lnum - 1
 | 
				
			||||||
| 
						 | 
					@ -509,7 +509,8 @@ def __init__(self):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def tokeneater(self, type, token, (srow, scol), (erow, ecol), line):
 | 
					    def tokeneater(self, type, token, (srow, scol), (erow, ecol), line):
 | 
				
			||||||
        if not self.started:
 | 
					        if not self.started:
 | 
				
			||||||
            if type == tokenize.NAME: self.started = 1
 | 
					            if '@' in line: pass
 | 
				
			||||||
 | 
					            elif type == tokenize.NAME: self.started = 1
 | 
				
			||||||
        elif type == tokenize.NEWLINE:
 | 
					        elif type == tokenize.NEWLINE:
 | 
				
			||||||
            self.last = srow
 | 
					            self.last = srow
 | 
				
			||||||
        elif type == tokenize.INDENT:
 | 
					        elif type == tokenize.INDENT:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -202,6 +202,47 @@ def sourcerange(top, bottom):
 | 
				
			||||||
    except:
 | 
					    except:
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Test for decorators as well.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					source = r"""
 | 
				
			||||||
 | 
					def wrap(foo=None):
 | 
				
			||||||
 | 
					  def wrapper(func):
 | 
				
			||||||
 | 
					    return func
 | 
				
			||||||
 | 
					  return wrapper
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def replace(func):
 | 
				
			||||||
 | 
					  def insteadfunc():
 | 
				
			||||||
 | 
					    print 'hello'
 | 
				
			||||||
 | 
					  return insteadfunc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# two decorators, one with argument
 | 
				
			||||||
 | 
					@wrap()
 | 
				
			||||||
 | 
					@wrap(wrap)
 | 
				
			||||||
 | 
					def wrapped():
 | 
				
			||||||
 | 
					  pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@replace
 | 
				
			||||||
 | 
					def gone():
 | 
				
			||||||
 | 
					  pass"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					file = open(TESTFN + "2", "w")
 | 
				
			||||||
 | 
					file.write(source)
 | 
				
			||||||
 | 
					file.close()
 | 
				
			||||||
 | 
					files_to_clean_up = [TESTFN + "2", TESTFN + '2c', TESTFN + '2o']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mod2 = imp.load_source("testmod3", TESTFN + "2")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test(inspect.getsource(mod2.wrapped) == sourcerange(13, 16),
 | 
				
			||||||
 | 
					     "inspect.getsource(mod.wrapped)")
 | 
				
			||||||
 | 
					test(inspect.getsource(mod2.gone) == sourcerange(8, 9),
 | 
				
			||||||
 | 
					     "inspect.getsource(mod.gone)")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for fname in files_to_clean_up:
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        os.unlink(fname)
 | 
				
			||||||
 | 
					    except:
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Test classic-class method resolution order.
 | 
					# Test classic-class method resolution order.
 | 
				
			||||||
class A:    pass
 | 
					class A:    pass
 | 
				
			||||||
class B(A): pass
 | 
					class B(A): pass
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -44,6 +44,9 @@ Extension modules
 | 
				
			||||||
Library
 | 
					Library
 | 
				
			||||||
-------
 | 
					-------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Patch #1006219: let inspect.getsource handle '@' decorators. Thanks Simon
 | 
				
			||||||
 | 
					  Percivall.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- logging.handlers.SMTPHandler.date_time has been removed;
 | 
					- logging.handlers.SMTPHandler.date_time has been removed;
 | 
				
			||||||
  the class now uses email.Utils.formatdate to generate the time stamp.
 | 
					  the class now uses email.Utils.formatdate to generate the time stamp.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue