https://dev-eole.ac-dijon.fr/
https://dev-eole.ac-dijon.fr/favicon.ico
2012-10-23T12:01:54Z
Ensemble Ouvert Libre Évolutif
python-pyeole - Evolution #4324: Fournir un décorateur de traçage d’appel de fonction
https://dev-eole.ac-dijon.fr/issues/4324?journal_id=14660
2012-10-23T12:01:54Z
Daniel Dehennin
<ul><li><strong>Description</strong> mis à jour (<a title="Voir les différences" href="/journals/14660/diff?detail_id=17975">diff</a>)</li></ul>
python-pyeole - Evolution #4324: Fournir un décorateur de traçage d’appel de fonction
https://dev-eole.ac-dijon.fr/issues/4324?journal_id=14661
2012-10-23T12:02:27Z
Daniel Dehennin
<ul><li><strong>Description</strong> mis à jour (<a title="Voir les différences" href="/journals/14661/diff?detail_id=17976">diff</a>)</li></ul>
python-pyeole - Evolution #4324: Fournir un décorateur de traçage d’appel de fonction
https://dev-eole.ac-dijon.fr/issues/4324?journal_id=14662
2012-10-23T12:33:10Z
Daniel Dehennin
<ul><li><strong>Description</strong> mis à jour (<a title="Voir les différences" href="/journals/14662/diff?detail_id=17977">diff</a>)</li></ul><p>Il ne faut pas supprimer les arguments sinon on modifie l’appel de fonction -> copy</p>
python-pyeole - Evolution #4324: Fournir un décorateur de traçage d’appel de fonction
https://dev-eole.ac-dijon.fr/issues/4324?journal_id=14671
2012-10-23T14:27:11Z
Daniel Dehennin
<ul></ul><p>Voici une classe <code>trace</code> permettant un appel sans les parenthèses si on ne passe aucun argument au décorateur :</p>
<pre><code class="python syntaxhl"><span class="CodeRay"><span class="comment">#!/usr/bin/python</span>
<span class="keyword">import</span> <span class="include">logging</span>
logger = logging.getLogger()
logger.addHandler(logging.StreamHandler())
logger.setLevel(logging.DEBUG)
<span class="keyword">class</span> <span class="class">trace</span>(<span class="predefined">object</span>):
<span class="docstring"><span class="delimiter">"""</span><span class="content">This is a decorator which can be used to trace functions calls</span><span class="content">
</span><span class="content">
</span><span class="content"> It can replace some positional and/or keyword arguments with some</span><span class="content">
</span><span class="content"> 'X' if they are present.</span><span class="content">
</span><span class="content"> </span><span class="delimiter">"""</span></span>
<span class="keyword">def</span> <span class="function">__init__</span>(<span class="predefined-constant">self</span>, f=<span class="predefined-constant">None</span>, hide_args=[], hide_kwargs=[]):
<span class="docstring"><span class="delimiter">"""</span><span class="content">Initialize the trace decorator</span><span class="content">
</span><span class="content">
</span><span class="content"> When no argument are passed to the decorator, it can be called without the braces.</span><span class="content">
</span><span class="content">
</span><span class="content"> @param f: Function to decorate when there are no decorator arguments</span><span class="content">
</span><span class="content"> @type f: C{function}</span><span class="content">
</span><span class="content"> @param hide_args: List of positional argument indexes to replace if present</span><span class="content">
</span><span class="content"> @type hide_args: C{list}</span><span class="content">
</span><span class="content"> @param hide_kwargs: List of keyword argument names to replace if present</span><span class="content">
</span><span class="content"> @type hide_kwargs: C{list}</span><span class="content">
</span><span class="content"> </span><span class="delimiter">"""</span></span>
<span class="comment"># func is used when using @trace decorator without braces</span>
<span class="keyword">if</span> f <span class="keyword">is</span> <span class="keyword">not</span> <span class="predefined-constant">None</span> <span class="keyword">and</span> <span class="keyword">not</span> <span class="predefined">callable</span>(f):
<span class="keyword">raise</span> <span class="exception">TypeError</span>(<span class="string"><span class="delimiter">'</span><span class="content">You must call trace decorator with keyword arguments</span><span class="delimiter">'</span></span>)
<span class="predefined-constant">self</span>.function = f
<span class="predefined-constant">self</span>.hide_args = hide_args
<span class="predefined-constant">self</span>.hide_kwargs = hide_kwargs
<span class="keyword">def</span> <span class="function">__log_call</span>(<span class="predefined-constant">self</span>, f, *args, **kwargs):
<span class="docstring"><span class="delimiter">"""</span><span class="content">Log function calls</span><span class="content">
</span><span class="content"> </span><span class="delimiter">"""</span></span>
<span class="comment"># Do nothing if debug is not enabled</span>
<span class="keyword">if</span> logger.isEnabledFor(logging.DEBUG):
<span class="comment"># Copy arguments</span>
args_list = <span class="predefined">list</span>(args)
args_dict = kwargs.copy()
<span class="keyword">for</span> index <span class="keyword">in</span> <span class="predefined-constant">self</span>.hide_args:
<span class="keyword">if</span> index < <span class="predefined">len</span>(args_list):
args_list[index] = <span class="string"><span class="delimiter">'</span><span class="content">X</span><span class="delimiter">'</span></span> * <span class="predefined">len</span>( args_list[index] )
<span class="keyword">for</span> keyname <span class="keyword">in</span> <span class="predefined-constant">self</span>.hide_kwargs:
<span class="keyword">if</span> keyname <span class="keyword">in</span> args_dict:
args_dict[keyname] = <span class="string"><span class="delimiter">'</span><span class="content">X</span><span class="delimiter">'</span></span> * <span class="predefined">len</span>( args_dict[keyname] )
logger.debug( <span class="string"><span class="delimiter">"</span><span class="content">-> entering %s(%s, %s)</span><span class="delimiter">"</span></span> % (f.__name__, <span class="predefined">str</span>(args_list), <span class="predefined">str</span>(args_dict)) )
<span class="keyword">def</span> <span class="function">__call_with_args</span>(<span class="predefined-constant">self</span>, f):
<span class="docstring"><span class="delimiter">"""</span><span class="content">Call decorator with parameters</span><span class="content">
</span><span class="content">
</span><span class="content"> Return a wrapper since the call is done</span><span class="content">
</span><span class="content"> </span><span class="delimiter">"""</span></span>
<span class="keyword">def</span> <span class="function">wrapped_f</span>(*args, **kwargs):
<span class="predefined-constant">self</span>.__log_call(f, *args, **kwargs)
f(*args, **kwargs)
<span class="keyword">return</span> wrapped_f
<span class="keyword">def</span> <span class="function">__call_without_args</span>(<span class="predefined-constant">self</span>, *args, **kwargs):
<span class="docstring"><span class="delimiter">"""</span><span class="content">Call decorator without parameter</span><span class="content">
</span><span class="content">
</span><span class="content"> The __call__ method of this object is not called until the decorated function is called itself.</span><span class="content">
</span><span class="content"> </span><span class="delimiter">"""</span></span>
<span class="predefined-constant">self</span>.__log_call(<span class="predefined-constant">self</span>.function, *args, **kwargs)
<span class="predefined-constant">self</span>.function(*args, **kwargs)
<span class="keyword">def</span> <span class="function">__call__</span>(<span class="predefined-constant">self</span>, f, *args, **kwargs):
<span class="docstring"><span class="delimiter">"""</span><span class="content">Log function calls</span><span class="content">
</span><span class="content"> </span><span class="delimiter">"""</span></span>
<span class="keyword">if</span> <span class="predefined">callable</span>(f):
<span class="keyword">return</span> <span class="predefined-constant">self</span>.__call_with_args(f)
<span class="keyword">else</span>:
argslist = [f]
argslist.extend(args)
<span class="keyword">return</span> <span class="predefined-constant">self</span>.__call_without_args(*argslist, **kwargs)
<span class="decorator">@trace</span>(hide_args=[<span class="integer">2</span>], hide_kwargs=[<span class="string"><span class="delimiter">'</span><span class="content">passwd</span><span class="delimiter">'</span></span>])
<span class="keyword">def</span> <span class="function">machin</span>(msg, name=<span class="predefined-constant">None</span>, passwd=<span class="predefined-constant">None</span>):
<span class="keyword">print</span> <span class="string"><span class="delimiter">"</span><span class="content">Machin: %s</span><span class="delimiter">"</span></span> % msg
<span class="comment"># Now braces are useless when no argument are passed to the decorator</span>
<span class="decorator">@trace</span>
<span class="keyword">def</span> <span class="function">bidule</span>(msg, name=<span class="predefined-constant">None</span>, passwd=<span class="predefined-constant">None</span>):
<span class="keyword">print</span> <span class="string"><span class="delimiter">"</span><span class="content">Bidule: %s</span><span class="delimiter">"</span></span> % msg
machin(<span class="string"><span class="delimiter">"</span><span class="content">MSG: args</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">user</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">secret</span><span class="delimiter">"</span></span>)
<span class="comment"># -> entering machin(['MSG: args', 'user', 'XXXXXX'], {})</span>
bidule(<span class="string"><span class="delimiter">"</span><span class="content">MSG: args</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">user</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">secret</span><span class="delimiter">"</span></span>)
<span class="comment"># -> entering bidule(['MSG: args', 'user', 'secret'], {})</span>
machin(<span class="string"><span class="delimiter">"</span><span class="content">MSG: kwargs</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">user</span><span class="delimiter">"</span></span>, passwd=<span class="string"><span class="delimiter">"</span><span class="content">secret</span><span class="delimiter">"</span></span>)
<span class="comment"># -> entering machin(['MSG: kwargs', 'user'], {'passwd': 'XXXXXX'})</span>
bidule(<span class="string"><span class="delimiter">"</span><span class="content">MSG: kwargs</span><span class="delimiter">"</span></span>, <span class="string"><span class="delimiter">"</span><span class="content">user</span><span class="delimiter">"</span></span>, passwd=<span class="string"><span class="delimiter">"</span><span class="content">secret</span><span class="delimiter">"</span></span>)
<span class="comment"># -> entering bidule(['MSG: kwargs', 'user'], {'passwd': 'secret'})</span>
</span></code></code></pre>
python-pyeole - Evolution #4324: Fournir un décorateur de traçage d’appel de fonction
https://dev-eole.ac-dijon.fr/issues/4324?journal_id=14672
2012-10-23T14:33:08Z
Daniel Dehennin
<ul></ul><p>Une <a href="http://python.dzone.com/articles/understanding-python" class="external">petite documentation en 12 points</a> pour comprender les décorateurs.</p>
<p>Un peu d’<a href="http://www.artima.com/weblogs/viewpost.jsp?thread=240845" class="external">explication</a> sur la différence entre les décorateurs avec et sans arguments.</p>
python-pyeole - Evolution #4324: Fournir un décorateur de traçage d’appel de fonction
https://dev-eole.ac-dijon.fr/issues/4324?journal_id=15805
2012-12-11T13:30:29Z
Emmanuel GARETTE
<ul></ul><p>Il serait pratique d'avoir également le "return" dans les logs.</p>
python-pyeole - Evolution #4324: Fournir un décorateur de traçage d’appel de fonction
https://dev-eole.ac-dijon.fr/issues/4324?journal_id=15958
2012-12-19T17:00:28Z
Daniel Dehennin
<ul><li><strong>Statut</strong> changé de <i>Nouveau</i> à <i>Résolu</i></li><li><strong>% réalisé</strong> changé de <i>0</i> à <i>100</i></li></ul><p>Appliqué par commit <a class="changeset" title="Ajout d’un décorateur traceur de fonction Le traceur prend des arguments optionels afin de cache..." href="https://dev-eole.ac-dijon.fr/projects/python-pyeole/repository/revisions/8659782892ebcde565fe604536a5bc8d0b0136a7">8659782892ebcde565fe604536a5bc8d0b0136a7</a>.</p>
python-pyeole - Evolution #4324: Fournir un décorateur de traçage d’appel de fonction
https://dev-eole.ac-dijon.fr/issues/4324?journal_id=16070
2013-01-07T16:20:47Z
Joël Cuissinat
joel.cuissinat@ac-dijon.fr
<ul><li><strong>Statut</strong> changé de <i>Résolu</i> à <i>Fermé</i></li></ul><p>à ressortir quand on en aura besoin :)</p>