Path: csiph.com!usenet.pasdenom.info!news.redatomik.org!newsfeed.xs4all.nl!newsfeed8.news.xs4all.nl!newsgate.cistron.nl!newsgate.news.xs4all.nl!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'modify': 0.04; 'main()': 0.07; 'wrapper': 0.07; "%s'": 0.09; 'app,': 0.09; 'imported': 0.09; 'mess': 0.09; 'name)': 0.09; 'name):': 0.09; 'python': 0.11; 'def': 0.14; 'above?': 0.16; 'annotations.': 0.16; 'cleaner': 0.16; 'from:addr:mrabarnett.plus.com': 0.16; 'from:addr:python': 0.16; 'from:name:mrab': 0.16; 'maintainable': 0.16; 'message- id:@mrabarnett.plus.com': 0.16; 'received:192.168.1.4': 0.16; 'wrote:': 0.16; 'looked': 0.16; 'merge': 0.18; 'skip:v 30': 0.20; 'decorator': 0.22; 'this:': 0.23; 'file.': 0.24; 'import': 0.24; 'header:In-Reply-To:1': 0.24; 'header:User-Agent:1': 0.26; 'this.': 0.28; '**kwargs)': 0.29; '**kwargs):': 0.29; 'app.': 0.29; 'ret': 0.29; 'subject:some': 0.29; 'function': 0.30; 'classes': 0.30; 'print': 0.31; "i'd": 0.31; 'third': 0.33; 'could': 0.35; 'to:addr:python-list': 0.35; 'clear': 0.35; 'functions.': 0.35; 'skip:> 10': 0.35; 'skip:d 30': 0.35; 'tasks': 0.35; 'something': 0.35; 'problem.': 0.35; 'skip:o 20': 0.35; 'but': 0.36; 'possible': 0.36; 'subject:: ': 0.37; "skip:' 20": 0.37; 'brief': 0.38; 'skip:s 40': 0.38; 'stuff': 0.38; 'does': 0.39; 'to:addr:python.org': 0.39; 'received:192': 0.39; 'subject:with': 0.40; 'some': 0.40; 'more': 0.62; 'skip:n 10': 0.63; 'email addr:gmail.com': 0.64 X-CM-Score: 0.00 X-CNFS-Analysis: v=2.1 cv=JOrGyJ+b c=1 sm=1 tr=0 a=0nF1XD0wxitMEM03M9B4ZQ==:117 a=0nF1XD0wxitMEM03M9B4ZQ==:17 a=0Bzu9jTXAAAA:8 a=EBOSESyhAAAA:8 a=AGkejYDSTmIA:10 a=IkcTkHD0fZMA:10 a=pGLkceISAAAA:8 a=VqFBMDixD09B9qHVqlIA:9 a=QEXdDO2ut3YA:10 X-AUTH: mrabarnett@:2500 Date: Fri, 26 Jun 2015 18:44:42 +0100 From: MRAB User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 MIME-Version: 1.0 To: python-list@python.org Subject: Re: how to replace some methods with instrumented ones References: <1bd45a06-6141-429d-89bc-79b5aa7de0ff@googlegroups.com> In-Reply-To: <1bd45a06-6141-429d-89bc-79b5aa7de0ff@googlegroups.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.20+ Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 73 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1435340694 news.xs4all.nl 2958 [2001:888:2000:d::a6]:42768 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:93201 On 2015-06-26 18:12, georgeryoung@gmail.com wrote: > [python 2.7, linux] > I have a python app. I cannot modify the file. But I can import it and mess with it. I need to perform brief tasks before and after some of the member functions. > I'd like to do this in as clear and maintainable way as possible (no third party imports). Here's what I have now(which works): > > from newvbr import * #get all the stuff from the newvbr app. > > def perf_time(tag): # I do a little more than this, but you get the idea. > print >>sys.stderr, datetime.datetime.now().isoformat() + tag > > def perf(tag): > def decorator(fn): > a def wrapper(*args): > perf_time('start %s' % tag) > ret = fn(*args) > perf_time('end %s' % tag) > return ret > return wrapper > return decorator > > > I use this on various members of various classes in the newvbr app: > > old_database_snapshot = VerticaSession.database_snapshot > @perf('db_snap') > def new_database_snapshot(self, name): > old_database_snapshot(self, name) > VerticaSession.database_snapshot = new_database_snapshot > > old_object_snapshot = VerticaSession.object_snapshot > @perf('obj_snap') > def new_object_snapshot(self, name): > old_object_snapshot(self, name) > VerticaSession.object_snapshot = new_object_snapshot > > main() #do the usual stuff of the imported app, but with annotations. > > > This is still pretty laborious. How can I make something roughly like: > > super_tagger(VerticaSession.database_snapshot) > > that does all the above? I need to tag a bunch of function members like this. I don't insist on using decorators, it just looked like that kind of problem. > You could do something like this: def super_tagger(module, function_name, tag): original_function = getattr(module, function_name) @perf(tag) def wrapper(*args, **kwargs): return original_function(*args, **kwargs) setattr(module, function_name, wrapper) and then: super_tagger(VerticaSession, 'database_snapshot', 'db'snap') It might be cleaner to merge the functionality of 'perf' into it: def super_tagger(module, function_name, tag): original_function = getattr(module, function_name) def wrapper(*args, **kwargs): perf_time('start %s' % tag) result = original_function(*args, **kwargs) perf_time('end %s' % tag) return result setattr(module, function_name, wrapper)