ó
æb]c           @   s  d  Z  d d l Z d d l Z d d l Z d d l Z d d l Z d d l m Z d d l m	 Z	 d d l m
 Z
 d d l m Z d d	 l m Z d d
 l m Z y d d l Z Wn e k
 rĖ d Z n Xd Z d Z d e f d     YZ d d  Z e j d d   Z d S(   s§   Profiling support for unit and performance tests.

These are special purpose profiling methods which operate
in a more fine-grained way than nose's profiling plugin.

i’’’’Ni   (   t   config(   t
   gc_collecti   (   t   jython(   t   pypy(   t   update_wrapper(   t   win32t   ProfileStatsFilec           B   s\   e  Z d  Z d   Z e d    Z d   Z d   Z d   Z d   Z	 d   Z
 d   Z RS(	   s°   "Store per-platform/fn profiling results in a file.

    We're still targeting Py2.5, 2.4 on 0.7 with no dependencies,
    so no json lib :(  need to roll something silly

    c         C   sÆ   t  j d  k	 o t  j j |  _ |  j p? t  j d  k	 o? t  j j |  _ t j j	 |  |  _
 t j j |  j
  d |  _ t j d    |  _ |  j   |  j r« |  j   n  d  S(   Ni’’’’c           S   s   t  j t  S(   N(   t   collectionst   defaultdictt   dict(    (    (    s;   lib/python2.7/site-packages/sqlalchemy/testing/profiling.pyt   <lambda>:   t    (   R    t   optionst   Nonet   force_write_profilest   force_writet   write_profilest   writet   ost   patht   abspatht   fnamet   splitt   short_fnameR   R   t   datat   _readt   _write(   t   selft   filename(    (    s;   lib/python2.7/site-packages/sqlalchemy/testing/profiling.pyt   __init__0   s    	
	c         C   sū   t  j j d t  j j } d j g  t j d d !D] } t |  ^ q1  } | g } | j |  t	 rx | j d  n  t
 r | j d  n  t r¤ | j d  n  | j t  j j j ræ d n d	  t  j j   } | j | rē d
 pź d  d j |  S(   Nt   _t   .i    i   R   R   t   wint   nativeunicodet   dbapiunicodet   cextensionst   nocextensions(   R    t   dbt   namet   drivert   joint   syst   version_infot   strt   appendR   R   R   t   dialectt   convert_unicodet   requirementst   _has_cextensions(   R   t	   dbapi_keyt   vt
   py_versiont   platform_tokenst	   _has_cext(    (    s;   lib/python2.7/site-packages/sqlalchemy/testing/profiling.pyt   platform_keyB   s     2	c         C   s)   t  } | |  j k o( |  j |  j | k S(   N(   t   _current_testR   R6   (   R   t   test_key(    (    s;   lib/python2.7/site-packages/sqlalchemy/testing/profiling.pyt	   has_stats[   s    c   	      C   sŚ   t  } |  j | } | |  j } d | k r= g  | d <} n
 | d } d | k rd d | d <} n
 | d } t |  | k } | s² | j |  |  j r© |  j   n  d  } n | d | | f } | d c d 7<| S(   Nt   countst   current_counti    t   linenoi   (   R7   R   R6   t   lenR,   R   R   R   (	   R   t	   callcountR8   t   per_fnt   per_platformR:   R;   t	   has_countt   result(    (    s;   lib/python2.7/site-packages/sqlalchemy/testing/profiling.pyRB   a   s$    

		c         C   s{   t  } |  j | } | |  j } | d } | d } | t |  k  rW | | | d <n
 | | d <|  j rw |  j   n  d  S(   NR:   R;   i   i’’’’(   R7   R   R6   R=   R   R   (   R   R>   R8   R?   R@   R:   R;   (    (    s;   lib/python2.7/site-packages/sqlalchemy/testing/profiling.pyt   replace|   s    


	c         C   s   d |  j  S(   Ns  # %s
# This file is written out on a per-environment basis.
# For each test in aaa_profiling, the corresponding function and 
# environment is located within this file.  If it doesn't exist,
# the test is skipped.
# If a callcount does exist, it is compared to what we received. 
# assertions are raised if the counts do not match.
# 
# To add a new callcount test, apply the function_call_count 
# decorator and re-run the tests using the --write-profiles 
# option - this file will be rewritten including the new count.
# 
(   R   (   R   (    (    s;   lib/python2.7/site-packages/sqlalchemy/testing/profiling.pyt   _header   s    c         C   sń   y t  |  j  } Wn t k
 r' d  SXxø t |  D]Ŗ \ } } | j   } | s5 | j d  ri q5 n  | j   \ } } } |  j | } | | } g  | j d  D] }	 t |	  ^ q„ }
 |
 | d <| d | d <d | d <q5 W| j	   d  S(   Nt   #t   ,R:   i   R<   i    R;   (
   t   openR   t   IOErrort	   enumeratet   stript
   startswithR   R   t   intt   close(   R   t	   profile_fR<   t   lineR8   R6   R:   R?   R@   t   countt   c(    (    s;   lib/python2.7/site-packages/sqlalchemy/testing/profiling.pyR      s     
(
c         C   sĻ   d |  j  GHt |  j  d  } | j |  j    x t |  j  D]| } |  j | } | j d |  xU t |  D]G } | | } d j d   | d D  } | j d | | | f  qr WqA W| j   d  S(   Ns   Writing profile file %st   ws   
# TEST: %s

RF   c         s   s   |  ] } t  |  Vq d  S(   N(   R+   (   t   .0RP   (    (    s;   lib/python2.7/site-packages/sqlalchemy/testing/profiling.pys	   <genexpr>¹   s    R:   s	   %s %s %s
(   R   RG   R   RD   t   sortedR   R(   RM   (   R   RN   R8   R?   R6   R@   RQ   (    (    s;   lib/python2.7/site-packages/sqlalchemy/testing/profiling.pyR   Æ   s    
"(   t   __name__t
   __module__t   __doc__R   t   propertyR6   R9   RB   RC   RD   R   R   (    (    (    s;   lib/python2.7/site-packages/sqlalchemy/testing/profiling.pyR   (   s   						g©?c            s     f d   } | S(   s©  Assert a target for a test case's function call count.

    The main purpose of this assertion is to detect changes in
    callcounts for various functions - the actual number is not as important.
    Callcounts are stored in a file keyed to Python version and OS platform
    information.  This file is generated automatically for new tests,
    and versioned so that unexpected changes in callcounts will be detected.

    c            s      f d   } t  |    S(   Nc             s'   t  d      |  |   SWd  QXd  S(   Nt   variance(   t   count_functions(   t   argst   kw(   t   fnRY   (    s;   lib/python2.7/site-packages/sqlalchemy/testing/profiling.pyt   wrapŹ   s    (   R   (   R]   R^   (   RY   (   R]   s;   lib/python2.7/site-packages/sqlalchemy/testing/profiling.pyt   decorateÉ   s    (    (   RY   R_   (    (   RY   s;   lib/python2.7/site-packages/sqlalchemy/testing/profiling.pyt   function_call_count¾   s    c   	      c   sp  t  d  k r t j d   n  t j   rL t j rL t j d t j  n  t	   t  j
   } | j   d  V| j   t j | d t j } | j } t j |  } | d  k r½ d  } n | \ } } d | | f GH| j d  | j   | rlt | |   } t | |  | k } | s*t j rlt j rCt j |  qit d | |  d | t j f   qln  d  S(   Ns   cProfile is not installeds   No profiling stats available on this platform for this function.  Run tests with --write-profiles to add statistics to %s for this platform.t   streams   Pstats calls: %d Expected %st
   cumulatives   Adjusted function call count %s not within %s%% of expected %s, platform %s. Rerun with --write-profiles to regenerate this callcount.id   (   t   cProfileR   R    t   _skip_test_exceptiont   _profile_statsR9   R   t	   skip_testR   R   t   Profilet   enablet   disablet   pstatst   StatsR)   t   stdoutt   total_callsRB   t
   sort_statst   print_statsRL   t   absR   RC   t   AssertionErrorR6   (	   RY   t   prt   statsR>   t   expectedt   expected_countt   line_not   deviancet   failed(    (    s;   lib/python2.7/site-packages/sqlalchemy/testing/profiling.pyRZ   Ó   s@    

		
	(   RW   R   t
   contextlibR   Rj   R)   R   R    t   utilR   R   R   R   R   Rc   t   ImportErrorR   R7   Re   t   objectR   R`   t   contextmanagerRZ   (    (    (    s;   lib/python2.7/site-packages/sqlalchemy/testing/profiling.pyt   <module>   s*   
