pax_global_header00006660000000000000000000000064132160446370014520gustar00rootroot0000000000000052 comment=81ebb735337825abab05bbe7141f1b1dc9263a34 line_profiler-2.1/000077500000000000000000000000001321604463700142135ustar00rootroot00000000000000line_profiler-2.1/.gitignore000066400000000000000000000002271321604463700162040ustar00rootroot00000000000000# Swap files. .*.swp .*.swo *~ *.pyc *.pyo *.so *.o *.a build/ dist/ _line_profiler.c line_profiler.egg-info/ MANIFEST pypi-site-docs.zip index.html line_profiler-2.1/.travis.yml000066400000000000000000000010171321604463700163230ustar00rootroot00000000000000language: python python: - "nightly" - "3.7-dev" - "3.6-dev" - "3.6" - "3.5" - "3.4" - "3.3" - "2.7" matrix: fast_finish: true allow_failures: - python: "nightly" - python: "3.7-dev" - python: "3.6-dev" install: - pip install --install-option='--no-cython-compile' Cython - pip install -r dev_requirements.txt - python setup.py develop script: - python -m unittest discover -v tests notifications: email: - brett.olsen+travis-ci@gmail.com - robert.kern+travis-ci@gmail.com line_profiler-2.1/LICENSE.txt000066400000000000000000000031201321604463700160320ustar00rootroot00000000000000This software is OSI Certified Open Source Software. OSI Certified is a certification mark of the Open Source Initiative. Copyright (c) 2008, Enthought, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Enthought, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. line_profiler-2.1/LICENSE_Python.txt000066400000000000000000000330571321604463700174070ustar00rootroot00000000000000The file timers.c was derived from the timer code in Python 2.5.2's _lsprof.c file and falls under the PSF license given below. A. HISTORY OF THE SOFTWARE ========================== Python was created in the early 1990s by Guido van Rossum at Stichting Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands as a successor of a language called ABC. Guido remains Python's principal author, although it includes many contributions from others. In 1995, Guido continued his work on Python at the Corporation for National Research Initiatives (CNRI, see http://www.cnri.reston.va.us) in Reston, Virginia where he released several versions of the software. In May 2000, Guido and the Python core development team moved to BeOpen.com to form the BeOpen PythonLabs team. In October of the same year, the PythonLabs team moved to Digital Creations (now Zope Corporation, see http://www.zope.com). In 2001, the Python Software Foundation (PSF, see http://www.python.org/psf/) was formed, a non-profit organization created specifically to own Python-related Intellectual Property. Zope Corporation is a sponsoring member of the PSF. All Python releases are Open Source (see http://www.opensource.org for the Open Source Definition). Historically, most, but not all, Python releases have also been GPL-compatible; the table below summarizes the various releases. Release Derived Year Owner GPL- from compatible? (1) 0.9.0 thru 1.2 1991-1995 CWI yes 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes 1.6 1.5.2 2000 CNRI no 2.0 1.6 2000 BeOpen.com no 1.6.1 1.6 2001 CNRI yes (2) 2.1 2.0+1.6.1 2001 PSF no 2.0.1 2.0+1.6.1 2001 PSF yes 2.1.1 2.1+2.0.1 2001 PSF yes 2.2 2.1.1 2001 PSF yes 2.1.2 2.1.1 2002 PSF yes 2.1.3 2.1.2 2002 PSF yes 2.2.1 2.2 2002 PSF yes 2.2.2 2.2.1 2002 PSF yes 2.2.3 2.2.2 2003 PSF yes 2.3 2.2.2 2002-2003 PSF yes 2.3.1 2.3 2002-2003 PSF yes 2.3.2 2.3.1 2002-2003 PSF yes 2.3.3 2.3.2 2002-2003 PSF yes 2.3.4 2.3.3 2004 PSF yes 2.3.5 2.3.4 2005 PSF yes 2.4 2.3 2004 PSF yes 2.4.1 2.4 2005 PSF yes 2.4.2 2.4.1 2005 PSF yes 2.4.3 2.4.2 2006 PSF yes 2.4.4 2.4.3 2006 PSF yes 2.5 2.4 2006 PSF yes 2.5.1 2.5 2007 PSF yes 2.5.2 2.5.2 2008 PSF yes Footnotes: (1) GPL-compatible doesn't mean that we're distributing Python under the GPL. All Python licenses, unlike the GPL, let you distribute a modified version without making your changes open source. The GPL-compatible licenses make it possible to combine Python with other software that is released under the GPL; the others don't. (2) According to Richard Stallman, 1.6.1 is not GPL-compatible, because its license has a choice of law clause. According to CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1 is "not incompatible" with the GPL. Thanks to the many outside volunteers who have worked under Guido's direction to make these releases possible. B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON =============================================================== PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 -------------------------------------------- 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization ("Licensee") accessing and otherwise using this software ("Python") in source or binary form and its associated documentation. 2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Python Software Foundation; All Rights Reserved" are retained in Python alone or in any derivative version prepared by Licensee. 3. In the event Licensee prepares a derivative work that is based on or incorporates Python or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python. 4. PSF is making Python available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. 8. By copying, installing or otherwise using Python, Licensee agrees to be bound by the terms and conditions of this License Agreement. BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0 ------------------------------------------- BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1 1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the Individual or Organization ("Licensee") accessing and otherwise using this software in source or binary form and its associated documentation ("the Software"). 2. Subject to the terms and conditions of this BeOpen Python License Agreement, BeOpen hereby grants Licensee a non-exclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use the Software alone or in any derivative version, provided, however, that the BeOpen Python License is retained in the Software, alone or in any derivative version prepared by Licensee. 3. BeOpen is making the Software available to Licensee on an "AS IS" basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 5. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 6. This License Agreement shall be governed by and interpreted in all respects by the law of the State of California, excluding conflict of law provisions. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between BeOpen and Licensee. This License Agreement does not grant permission to use BeOpen trademarks or trade names in a trademark sense to endorse or promote products or services of Licensee, or any third party. As an exception, the "BeOpen Python" logos available at http://www.pythonlabs.com/logos.html may be used according to the permissions granted on that web page. 7. By copying, installing or otherwise using the software, Licensee agrees to be bound by the terms and conditions of this License Agreement. CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1 --------------------------------------- 1. This LICENSE AGREEMENT is between the Corporation for National Research Initiatives, having an office at 1895 Preston White Drive, Reston, VA 20191 ("CNRI"), and the Individual or Organization ("Licensee") accessing and otherwise using Python 1.6.1 software in source or binary form and its associated documentation. 2. Subject to the terms and conditions of this License Agreement, CNRI hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python 1.6.1 alone or in any derivative version, provided, however, that CNRI's License Agreement and CNRI's notice of copyright, i.e., "Copyright (c) 1995-2001 Corporation for National Research Initiatives; All Rights Reserved" are retained in Python 1.6.1 alone or in any derivative version prepared by Licensee. Alternately, in lieu of CNRI's License Agreement, Licensee may substitute the following text (omitting the quotes): "Python 1.6.1 is made available subject to the terms and conditions in CNRI's License Agreement. This Agreement together with Python 1.6.1 may be located on the Internet using the following unique, persistent identifier (known as a handle): 1895.22/1013. This Agreement may also be obtained from a proxy server on the Internet using the following URL: http://hdl.handle.net/1895.22/1013". 3. In the event Licensee prepares a derivative work that is based on or incorporates Python 1.6.1 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python 1.6.1. 4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS" basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 7. This License Agreement shall be governed by the federal intellectual property law of the United States, including without limitation the federal copyright law, and, to the extent such U.S. federal law does not apply, by the law of the Commonwealth of Virginia, excluding Virginia's conflict of law provisions. Notwithstanding the foregoing, with regard to derivative works based on Python 1.6.1 that incorporate non-separable material that was previously distributed under the GNU General Public License (GPL), the law of the Commonwealth of Virginia shall govern this License Agreement only as to issues arising under or with respect to Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between CNRI and Licensee. This License Agreement does not grant permission to use CNRI trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. 8. By clicking on the "ACCEPT" button where indicated, or by copying, installing or otherwise using Python 1.6.1, Licensee agrees to be bound by the terms and conditions of this License Agreement. ACCEPT CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2 -------------------------------------------------- Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam, The Netherlands. All rights reserved. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Stichting Mathematisch Centrum or CWI not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. line_profiler-2.1/MANIFEST.in000066400000000000000000000002641321604463700157530ustar00rootroot00000000000000include LICENSE.txt include LICENSE_Python.txt include README.rst include python25.pxd include timers.h include _line_profiler.c include unset_trace.h recursive-include tests *.py line_profiler-2.1/Makefile000066400000000000000000000006631321604463700156600ustar00rootroot00000000000000all: @echo 'Just some tools to help me make releases. Nothing for users.' index.html: README.rst rst2html.py README.rst index.html pypi-site-docs.zip: index.html kernprof.py LICENSE.txt zip -r $@ $? site: pypi-site-docs.zip # We need to run build_ext first to make sure we have _line_profiler.c. # However, we can't run both commands in the same run. sdist: python setup.py build_ext python setup.py sdist .PHONY: site sdist line_profiler-2.1/README.rst000066400000000000000000000417521321604463700157130ustar00rootroot00000000000000line_profiler and kernprof -------------------------- `line_profiler` is a module for doing line-by-line profiling of functions. kernprof is a convenient script for running either `line_profiler` or the Python standard library's cProfile or profile modules, depending on what is available. They are available under a `BSD license`_. .. _BSD license: https://raw.githubusercontent.com/rkern/line_profiler/master/LICENSE.txt .. contents:: Installation ============ Releases of `line_profiler` can be installed using pip:: $ pip install line_profiler Source releases and any binaries can be downloaded from the PyPI link. http://pypi.python.org/pypi/line_profiler To check out the development sources, you can use Git_:: $ git clone https://github.com/rkern/line_profiler.git You may also download source tarballs of any snapshot from that URL. Source releases will require a C compiler in order to build `line_profiler`. In addition, git checkouts will also require Cython_ >= 0.10. Source releases on PyPI should contain the pregenerated C sources, so Cython should not be required in that case. `kernprof` is a single-file pure Python script and does not require a compiler. If you wish to use it to run cProfile and not line-by-line profiling, you may copy it to a directory on your `PATH` manually and avoid trying to build any C extensions. .. _git: http://git-scm.com/ .. _Cython: http://www.cython.org .. _build and install: http://docs.python.org/install/index.html line_profiler ============= The current profiling tools supported in Python 2.7 and later only time function calls. This is a good first step for locating hotspots in one's program and is frequently all one needs to do to optimize the program. However, sometimes the cause of the hotspot is actually a single line in the function, and that line may not be obvious from just reading the source code. These cases are particularly frequent in scientific computing. Functions tend to be larger (sometimes because of legitimate algorithmic complexity, sometimes because the programmer is still trying to write FORTRAN code), and a single statement without function calls can trigger lots of computation when using libraries like numpy. cProfile only times explicit function calls, not special methods called because of syntax. Consequently, a relatively slow numpy operation on large arrays like this, :: a[large_index_array] = some_other_large_array is a hotspot that never gets broken out by cProfile because there is no explicit function call in that statement. LineProfiler can be given functions to profile, and it will time the execution of each individual line inside those functions. In a typical workflow, one only cares about line timings of a few functions because wading through the results of timing every single line of code would be overwhelming. However, LineProfiler does need to be explicitly told what functions to profile. The easiest way to get started is to use the `kernprof` script. :: $ kernprof -l script_to_profile.py `kernprof` will create an instance of LineProfiler and insert it into the `__builtins__` namespace with the name `profile`. It has been written to be used as a decorator, so in your script, you decorate the functions you want to profile with @profile. :: @profile def slow_function(a, b, c): ... The default behavior of `kernprof` is to put the results into a binary file script_to_profile.py.lprof . You can tell `kernprof` to immediately view the formatted results at the terminal with the [-v/--view] option. Otherwise, you can view the results later like so:: $ python -m line_profiler script_to_profile.py.lprof For example, here are the results of profiling a single function from a decorated version of the pystone.py benchmark (the first two lines are output from `pystone.py`, not `kernprof`):: Pystone(1.1) time for 50000 passes = 2.48 This machine benchmarks at 20161.3 pystones/second Wrote profile results to pystone.py.lprof Timer unit: 1e-06 s File: pystone.py Function: Proc2 at line 149 Total time: 0.606656 s Line # Hits Time Per Hit % Time Line Contents ============================================================== 149 @profile 150 def Proc2(IntParIO): 151 50000 82003 1.6 13.5 IntLoc = IntParIO + 10 152 50000 63162 1.3 10.4 while 1: 153 50000 69065 1.4 11.4 if Char1Glob == 'A': 154 50000 66354 1.3 10.9 IntLoc = IntLoc - 1 155 50000 67263 1.3 11.1 IntParIO = IntLoc - IntGlob 156 50000 65494 1.3 10.8 EnumLoc = Ident1 157 50000 68001 1.4 11.2 if EnumLoc == Ident1: 158 50000 63739 1.3 10.5 break 159 50000 61575 1.2 10.1 return IntParIO The source code of the function is printed with the timing information for each line. There are six columns of information. * Line #: The line number in the file. * Hits: The number of times that line was executed. * Time: The total amount of time spent executing the line in the timer's units. In the header information before the tables, you will see a line "Timer unit:" giving the conversion factor to seconds. It may be different on different systems. * Per Hit: The average amount of time spent executing the line once in the timer's units. * % Time: The percentage of time spent on that line relative to the total amount of recorded time spent in the function. * Line Contents: The actual source code. Note that this is always read from disk when the formatted results are viewed, *not* when the code was executed. If you have edited the file in the meantime, the lines will not match up, and the formatter may not even be able to locate the function for display. If you are using IPython, there is an implementation of an %lprun magic command which will let you specify functions to profile and a statement to execute. It will also add its LineProfiler instance into the __builtins__, but typically, you would not use it like that. For IPython 0.11+, you can install it by editing the IPython configuration file `~/.ipython/profile_default/ipython_config.py` to add the `'line_profiler'` item to the extensions list:: c.TerminalIPythonApp.extensions = [ 'line_profiler', ] To get usage help for %lprun, use the standard IPython help mechanism:: In [1]: %lprun? These two methods are expected to be the most frequent user-level ways of using LineProfiler and will usually be the easiest. However, if you are building other tools with LineProfiler, you will need to use the API. There are two ways to inform LineProfiler of functions to profile: you can pass them as arguments to the constructor or use the `add_function(f)` method after instantiation. :: profile = LineProfiler(f, g) profile.add_function(h) LineProfiler has the same `run()`, `runctx()`, and `runcall()` methods as cProfile.Profile as well as `enable()` and `disable()`. It should be noted, though, that `enable()` and `disable()` are not entirely safe when nested. Nesting is common when using LineProfiler as a decorator. In order to support nesting, use `enable_by_count()` and `disable_by_count()`. These functions will increment and decrement a counter and only actually enable or disable the profiler when the count transitions from or to 0. After profiling, the `dump_stats(filename)` method will pickle the results out to the given file. `print_stats([stream])` will print the formatted results to sys.stdout or whatever stream you specify. `get_stats()` will return LineStats object, which just holds two attributes: a dictionary containing the results and the timer unit. kernprof ======== `kernprof` also works with cProfile, its third-party incarnation lsprof, or the pure-Python profile module depending on what is available. It has a few main features: * Encapsulation of profiling concerns. You do not have to modify your script in order to initiate profiling and save the results. Unless if you want to use the advanced __builtins__ features, of course. * Robust script execution. Many scripts require things like __name__, __file__, and sys.path to be set relative to it. A naive approach at encapsulation would just use execfile(), but many scripts which rely on that information will fail. kernprof will set those variables correctly before executing the script. * Easy executable location. If you are profiling an application installed on your PATH, you can just give the name of the executable. If kernprof does not find the given script in the current directory, it will search your PATH for it. * Inserting the profiler into __builtins__. Sometimes, you just want to profile a small part of your code. With the [-b/--builtin] argument, the Profiler will be instantiated and inserted into your __builtins__ with the name "profile". Like LineProfiler, it may be used as a decorator, or enabled/disabled with `enable_by_count()` and `disable_by_count()`, or even as a context manager with the "with profile:" statement. * Pre-profiling setup. With the [-s/--setup] option, you can provide a script which will be executed without profiling before executing the main script. This is typically useful for cases where imports of large libraries like wxPython or VTK are interfering with your results. If you can modify your source code, the __builtins__ approach may be easier. The results of profile script_to_profile.py will be written to script_to_profile.py.prof by default. It will be a typical marshalled file that can be read with pstats.Stats(). They may be interactively viewed with the command:: $ python -m pstats script_to_profile.py.prof Such files may also be viewed with graphical tools like kcachegrind_ through the converter program pyprof2calltree_ or RunSnakeRun_. .. _kcachegrind: http://kcachegrind.sourceforge.net/html/Home.html .. _pyprof2calltree: http://pypi.python.org/pypi/pyprof2calltree/ .. _RunSnakeRun: http://www.vrplumber.com/programming/runsnakerun/ Frequently Asked Questions ========================== * Why the name "kernprof"? I didn't manage to come up with a meaningful name, so I named it after myself. * Why not use hotshot instead of line_profile? hotshot can do line-by-line timings, too. However, it is deprecated and may disappear from the standard library. Also, it can take a long time to process the results while I want quick turnaround in my workflows. hotshot pays this processing time in order to make itself minimally intrusive to the code it is profiling. Code that does network operations, for example, may even go down different code paths if profiling slows down execution too much. For my use cases, and I think those of many other people, their line-by-line profiling is not affected much by this concern. * Why not allow using hotshot from kernprof.py? I don't use hotshot, myself. I will accept contributions in this vein, though. * The line-by-line timings don't add up when one profiled function calls another. What's up with that? Let's say you have function F() calling function G(), and you are using LineProfiler on both. The total time reported for G() is less than the time reported on the line in F() that calls G(). The reason is that I'm being reasonably clever (and possibly too clever) in recording the times. Basically, I try to prevent recording the time spent inside LineProfiler doing all of the bookkeeping for each line. Each time Python's tracing facility issues a line event (which happens just before a line actually gets executed), LineProfiler will find two timestamps, one at the beginning before it does anything (t_begin) and one as close to the end as possible (t_end). Almost all of the overhead of LineProfiler's data structures happens in between these two times. When a line event comes in, LineProfiler finds the function it belongs to. If it's the first line in the function, we record the line number and *t_end* associated with the function. The next time we see a line event belonging to that function, we take t_begin of the new event and subtract the old t_end from it to find the amount of time spent in the old line. Then we record the new t_end as the active line for this function. This way, we are removing most of LineProfiler's overhead from the results. Well almost. When one profiled function F calls another profiled function G, the line in F that calls G basically records the total time spent executing the line, which includes the time spent inside the profiler while inside G. The first time this question was asked, the questioner had the G() function call as part of a larger expression, and he wanted to try to estimate how much time was being spent in the function as opposed to the rest of the expression. My response was that, even if I could remove the effect, it might still be misleading. G() might be called elsewhere, not just from the relevant line in F(). The workaround would be to modify the code to split it up into two lines, one which just assigns the result of G() to a temporary variable and the other with the rest of the expression. I am open to suggestions on how to make this more robust. Or simple admonitions against trying to be clever. * Why do my list comprehensions have so many hits when I use the LineProfiler? LineProfiler records the line with the list comprehension once for each iteration of the list comprehension. * Why is kernprof distributed with line_profiler? It works with just cProfile, right? Partly because kernprof.py is essential to using line_profiler effectively, but mostly because I'm lazy and don't want to maintain the overhead of two projects for modules as small as these. However, kernprof.py is a standalone, pure Python script that can be used to do function profiling with just the Python standard library. You may grab it and install it by itself without `line_profiler`. * Do I need a C compiler to build `line_profiler`? kernprof.py? You do need a C compiler for line_profiler. kernprof.py is a pure Python script and can be installed separately, though. * Do I need Cython to build `line_profiler`? You should not have to if you are building from a released source tarball. It should contain the generated C sources already. If you are running into problems, that may be a bug; let me know. If you are building from a git checkout or snapshot, you will need Cython to generate the C sources. You will probably need version 0.10 or higher. There is a bug in some earlier versions in how it handles NULL PyObject* pointers. * What version of Python do I need? Both `line_profiler` and `kernprof` have been tested with Python 2.7, and 3.2-3.4. To Do ===== cProfile uses a neat "rotating trees" data structure to minimize the overhead of looking up and recording entries. LineProfiler uses Python dictionaries and extension objects thanks to Cython. This mostly started out as a prototype that I wanted to play with as quickly as possible, so I passed on stealing the rotating trees for now. As usual, I got it working, and it seems to have acceptable performance, so I am much less motivated to use a different strategy now. Maybe later. Contributions accepted! Bugs and Such ============= Bugs and pull requested can be submitted on GitHub_. .. _GitHub: https://github.com/rkern/line_profiler Changes ======= 2.1 ~~~ * ENH: Add support for Python 3.5 coroutines * ENH: Documentation updates * ENH: CI for most recent Python versions (3.5, 3.6, 3.6-dev, 3.7-dev, nightly) * ENH: Add timer unit argument for output time granularity spec 2.0 ~~~ * BUG: Added support for IPython 5.0+, removed support for IPython <=0.12 1.1 ~~~ * BUG: Read source files as bytes. 1.0 ~~~ * ENH: `kernprof.py` is now installed as `kernprof`. * ENH: Python 3 support. Thanks to the long-suffering Mikhail Korobov for being patient. * Dropped 2.6 as it was too annoying. * ENH: The `stripzeros` and `add_module` options. Thanks to Erik Tollerud for contributing it. * ENH: Support for IPython cell blocks. Thanks to Michael Forbes for adding this feature. * ENH: Better warnings when building without Cython. Thanks to David Cournapeau for spotting this. 1.0b3 ~~~~~ * ENH: Profile generators. * BUG: Update for compatibility with newer versions of Cython. Thanks to Ondrej Certik for spotting the bug. * BUG: Update IPython compatibility for 0.11+. Thanks to Yaroslav Halchenko and others for providing the updated imports. 1.0b2 ~~~~~ * BUG: fixed line timing overflow on Windows. * DOC: improved the README. 1.0b1 ~~~~~ * Initial release. line_profiler-2.1/_line_profiler.pyx000066400000000000000000000152451321604463700177540ustar00rootroot00000000000000from python25 cimport PyFrameObject, PyObject, PyStringObject cdef extern from "frameobject.h": ctypedef int (*Py_tracefunc)(object self, PyFrameObject *py_frame, int what, PyObject *arg) cdef extern from "Python.h": ctypedef long long PY_LONG_LONG cdef bint PyCFunction_Check(object obj) cdef void PyEval_SetProfile(Py_tracefunc func, object arg) cdef void PyEval_SetTrace(Py_tracefunc func, object arg) ctypedef object (*PyCFunction)(object self, object args) ctypedef struct PyMethodDef: char *ml_name PyCFunction ml_meth int ml_flags char *ml_doc ctypedef struct PyCFunctionObject: PyMethodDef *m_ml PyObject *m_self PyObject *m_module # They're actually #defines, but whatever. cdef int PyTrace_CALL cdef int PyTrace_EXCEPTION cdef int PyTrace_LINE cdef int PyTrace_RETURN cdef int PyTrace_C_CALL cdef int PyTrace_C_EXCEPTION cdef int PyTrace_C_RETURN cdef extern from "timers.h": PY_LONG_LONG hpTimer() double hpTimerUnit() cdef extern from "unset_trace.h": void unset_trace() def label(code): """ Return a (filename, first_lineno, func_name) tuple for a given code object. This is the same labelling as used by the cProfile module in Python 2.5. """ if isinstance(code, str): return ('~', 0, code) # built-in functions ('~' sorts at the end) else: return (code.co_filename, code.co_firstlineno, code.co_name) cdef class LineTiming: """ The timing for a single line. """ cdef public object code cdef public int lineno cdef public PY_LONG_LONG total_time cdef public long nhits def __init__(self, object code, int lineno): self.code = code self.lineno = lineno self.total_time = 0 self.nhits = 0 cdef hit(self, PY_LONG_LONG dt): """ Record a line timing. """ self.nhits += 1 self.total_time += dt def astuple(self): """ Convert to a tuple of (lineno, nhits, total_time). """ return (self.lineno, self.nhits, self.total_time) def __repr__(self): return '' % (self.code, self.lineno, self.nhits, self.total_time) # Note: this is a regular Python class to allow easy pickling. class LineStats(object): """ Object to encapsulate line-profile statistics. Attributes ---------- timings : dict Mapping from (filename, first_lineno, function_name) of the profiled function to a list of (lineno, nhits, total_time) tuples for each profiled line. total_time is an integer in the native units of the timer. unit : float The number of seconds per timer unit. """ def __init__(self, timings, unit): self.timings = timings self.unit = unit cdef class LineProfiler: """ Time the execution of lines of Python code. """ cdef public list functions cdef public dict code_map cdef public dict last_time cdef public double timer_unit cdef public long enable_count def __init__(self, *functions): self.functions = [] self.code_map = {} self.last_time = {} self.timer_unit = hpTimerUnit() self.enable_count = 0 for func in functions: self.add_function(func) def add_function(self, func): """ Record line profiling information for the given Python function. """ try: code = func.__code__ except AttributeError: import warnings warnings.warn("Could not extract a code object for the object %r" % (func,)) return if code not in self.code_map: self.code_map[code] = {} self.functions.append(func) def enable_by_count(self): """ Enable the profiler if it hasn't been enabled before. """ if self.enable_count == 0: self.enable() self.enable_count += 1 def disable_by_count(self): """ Disable the profiler if the number of disable requests matches the number of enable requests. """ if self.enable_count > 0: self.enable_count -= 1 if self.enable_count == 0: self.disable() def __enter__(self): self.enable_by_count() def __exit__(self, exc_type, exc_val, exc_tb): self.disable_by_count() def enable(self): PyEval_SetTrace(python_trace_callback, self) def disable(self): self.last_time = {} unset_trace() def get_stats(self): """ Return a LineStats object containing the timings. """ stats = {} for code in self.code_map: entries = self.code_map[code].values() key = label(code) stats[key] = [e.astuple() for e in entries] stats[key].sort() return LineStats(stats, self.timer_unit) cdef class LastTime: """ Record the last callback call for a given line. """ cdef int f_lineno cdef PY_LONG_LONG time def __cinit__(self, int f_lineno, PY_LONG_LONG time): self.f_lineno = f_lineno self.time = time cdef int python_trace_callback(object self_, PyFrameObject *py_frame, int what, PyObject *arg): """ The PyEval_SetTrace() callback. """ cdef LineProfiler self cdef object code, key cdef dict line_entries, last_time cdef LineTiming entry cdef LastTime old cdef PY_LONG_LONG time self = self_ last_time = self.last_time if what == PyTrace_LINE or what == PyTrace_RETURN: code = py_frame.f_code if code in self.code_map: time = hpTimer() if code in last_time: old = last_time[code] line_entries = self.code_map[code] key = old.f_lineno if key not in line_entries: entry = LineTiming(code, old.f_lineno) line_entries[key] = entry else: entry = line_entries[key] entry.hit(time - old.time) if what == PyTrace_LINE: # Get the time again. This way, we don't record much time wasted # in this function. last_time[code] = LastTime(py_frame.f_lineno, hpTimer()) else: # We are returning from a function, not executing a line. Delete # the last_time record. It may have already been deleted if we # are profiling a generator that is being pumped past its end. if code in last_time: del last_time[code] return 0 line_profiler-2.1/dev_requirements.txt000066400000000000000000000000241321604463700203310ustar00rootroot00000000000000Cython IPython>=0.13line_profiler-2.1/kernprof.py000077500000000000000000000162121321604463700164200ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: UTF-8 -*- """ Script to conveniently run profilers on code in a variety of circumstances. """ import functools import optparse import os import sys PY3 = sys.version_info[0] == 3 # Guard the import of cProfile such that 3.x people # without lsprof can still use this script. try: from cProfile import Profile except ImportError: try: from lsprof import Profile except ImportError: from profile import Profile # Python 3.x compatibility utils: execfile # ======================================== try: execfile except NameError: # Python 3.x doesn't have 'execfile' builtin import builtins exec_ = getattr(builtins, "exec") def execfile(filename, globals=None, locals=None): with open(filename, 'rb') as f: exec_(compile(f.read(), filename, 'exec'), globals, locals) # ===================================== CO_GENERATOR = 0x0020 def is_generator(f): """ Return True if a function is a generator. """ isgen = (f.__code__.co_flags & CO_GENERATOR) != 0 return isgen class ContextualProfile(Profile): """ A subclass of Profile that adds a context manager for Python 2.5 with: statements and a decorator. """ def __init__(self, *args, **kwds): super(ContextualProfile, self).__init__(*args, **kwds) self.enable_count = 0 def enable_by_count(self, subcalls=True, builtins=True): """ Enable the profiler if it hasn't been enabled before. """ if self.enable_count == 0: self.enable(subcalls=subcalls, builtins=builtins) self.enable_count += 1 def disable_by_count(self): """ Disable the profiler if the number of disable requests matches the number of enable requests. """ if self.enable_count > 0: self.enable_count -= 1 if self.enable_count == 0: self.disable() def __call__(self, func): """ Decorate a function to start the profiler on function entry and stop it on function exit. """ # FIXME: refactor this into a utility function so that both it and # line_profiler can use it. if is_generator(func): wrapper = self.wrap_generator(func) else: wrapper = self.wrap_function(func) return wrapper # FIXME: refactor this stuff so that both LineProfiler and # ContextualProfile can use the same implementation. def wrap_generator(self, func): """ Wrap a generator to profile it. """ @functools.wraps(func) def wrapper(*args, **kwds): g = func(*args, **kwds) # The first iterate will not be a .send() self.enable_by_count() try: item = next(g) finally: self.disable_by_count() input = (yield item) # But any following one might be. while True: self.enable_by_count() try: item = g.send(input) finally: self.disable_by_count() input = (yield item) return wrapper def wrap_function(self, func): """ Wrap a function to profile it. """ @functools.wraps(func) def wrapper(*args, **kwds): self.enable_by_count() try: result = func(*args, **kwds) finally: self.disable_by_count() return result return wrapper def __enter__(self): self.enable_by_count() def __exit__(self, exc_type, exc_val, exc_tb): self.disable_by_count() def find_script(script_name): """ Find the script. If the input is not a file, then $PATH will be searched. """ if os.path.isfile(script_name): return script_name path = os.getenv('PATH', os.defpath).split(os.pathsep) for dir in path: if dir == '': continue fn = os.path.join(dir, script_name) if os.path.isfile(fn): return fn sys.stderr.write('Could not find script %s\n' % script_name) raise SystemExit(1) def main(args=None): if args is None: args = sys.argv usage = "%prog [-s setupfile] [-o output_file_path] scriptfile [arg] ..." parser = optparse.OptionParser(usage=usage, version="%prog 1.0b2") parser.allow_interspersed_args = False parser.add_option('-l', '--line-by-line', action='store_true', help="Use the line-by-line profiler from the line_profiler module " "instead of Profile. Implies --builtin.") parser.add_option('-b', '--builtin', action='store_true', help="Put 'profile' in the builtins. Use 'profile.enable()' and " "'profile.disable()' in your code to turn it on and off, or " "'@profile' to decorate a single function, or 'with profile:' " "to profile a single section of code.") parser.add_option('-o', '--outfile', default=None, help="Save stats to ") parser.add_option('-s', '--setup', default=None, help="Code to execute before the code to profile") parser.add_option('-v', '--view', action='store_true', help="View the results of the profile in addition to saving it.") if not sys.argv[1:]: parser.print_usage() sys.exit(2) options, args = parser.parse_args() if not options.outfile: if options.line_by_line: extension = 'lprof' else: extension = 'prof' options.outfile = '%s.%s' % (os.path.basename(args[0]), extension) sys.argv[:] = args if options.setup is not None: # Run some setup code outside of the profiler. This is good for large # imports. setup_file = find_script(options.setup) __file__ = setup_file __name__ = '__main__' # Make sure the script's directory is on sys.path instead of just # kernprof.py's. sys.path.insert(0, os.path.dirname(setup_file)) ns = locals() execfile(setup_file, ns, ns) if options.line_by_line: import line_profiler prof = line_profiler.LineProfiler() options.builtin = True else: prof = ContextualProfile() if options.builtin: if PY3: import builtins else: import __builtin__ as builtins builtins.__dict__['profile'] = prof script_file = find_script(sys.argv[0]) __file__ = script_file __name__ = '__main__' # Make sure the script's directory is on sys.path instead of just # kernprof.py's. sys.path.insert(0, os.path.dirname(script_file)) try: try: execfile_ = execfile ns = locals() if options.builtin: execfile(script_file, ns, ns) else: prof.runctx('execfile_(%r, globals())' % (script_file,), ns, ns) except (KeyboardInterrupt, SystemExit): pass finally: prof.dump_stats(options.outfile) print('Wrote profile results to %s' % options.outfile) if options.view: prof.print_stats() if __name__ == '__main__': sys.exit(main(sys.argv)) line_profiler-2.1/line_profiler.py000077500000000000000000000325631321604463700174320ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import print_function try: import cPickle as pickle except ImportError: import pickle try: from cStringIO import StringIO except ImportError: from io import StringIO import functools import inspect import linecache import optparse import os import sys from IPython.core.magic import (Magics, magics_class, line_magic) from IPython.core.page import page from IPython.utils.ipstruct import Struct from IPython.core.error import UsageError from _line_profiler import LineProfiler as CLineProfiler # Python 2/3 compatibility utils # =========================================================== PY3 = sys.version_info[0] == 3 PY35 = PY3 and sys.version_info[1] >= 5 # exec (from https://bitbucket.org/gutworth/six/): if PY3: import builtins exec_ = getattr(builtins, "exec") del builtins else: def exec_(_code_, _globs_=None, _locs_=None): """Execute code in a namespace.""" if _globs_ is None: frame = sys._getframe(1) _globs_ = frame.f_globals if _locs_ is None: _locs_ = frame.f_locals del frame elif _locs_ is None: _locs_ = _globs_ exec("""exec _code_ in _globs_, _locs_""") if PY35: import inspect def is_coroutine(f): return inspect.iscoroutinefunction(f) else: def is_coroutine(f): return False # ============================================================ CO_GENERATOR = 0x0020 def is_generator(f): """ Return True if a function is a generator. """ isgen = (f.__code__.co_flags & CO_GENERATOR) != 0 return isgen class LineProfiler(CLineProfiler): """ A profiler that records the execution times of individual lines. """ def __call__(self, func): """ Decorate a function to start the profiler on function entry and stop it on function exit. """ self.add_function(func) if is_coroutine(func): wrapper = self.wrap_coroutine(func) elif is_generator(func): wrapper = self.wrap_generator(func) else: wrapper = self.wrap_function(func) return wrapper def wrap_generator(self, func): """ Wrap a generator to profile it. """ @functools.wraps(func) def wrapper(*args, **kwds): g = func(*args, **kwds) # The first iterate will not be a .send() self.enable_by_count() try: item = next(g) finally: self.disable_by_count() input = (yield item) # But any following one might be. while True: self.enable_by_count() try: item = g.send(input) finally: self.disable_by_count() input = (yield item) return wrapper def wrap_function(self, func): """ Wrap a function to profile it. """ @functools.wraps(func) def wrapper(*args, **kwds): self.enable_by_count() try: result = func(*args, **kwds) finally: self.disable_by_count() return result return wrapper if PY35: import line_profiler_py35 wrap_coroutine = line_profiler_py35.wrap_coroutine def dump_stats(self, filename): """ Dump a representation of the data to a file as a pickled LineStats object from `get_stats()`. """ lstats = self.get_stats() with open(filename, 'wb') as f: pickle.dump(lstats, f, pickle.HIGHEST_PROTOCOL) def print_stats(self, stream=None, output_unit=None, stripzeros=False): """ Show the gathered statistics. """ lstats = self.get_stats() show_text(lstats.timings, lstats.unit, output_unit=output_unit, stream=stream, stripzeros=stripzeros) def run(self, cmd): """ Profile a single executable statment in the main namespace. """ import __main__ main_dict = __main__.__dict__ return self.runctx(cmd, main_dict, main_dict) def runctx(self, cmd, globals, locals): """ Profile a single executable statement in the given namespaces. """ self.enable_by_count() try: exec_(cmd, globals, locals) finally: self.disable_by_count() return self def runcall(self, func, *args, **kw): """ Profile a single function call. """ self.enable_by_count() try: return func(*args, **kw) finally: self.disable_by_count() def add_module(self, mod): """ Add all the functions in a module and its classes. """ from inspect import isclass, isfunction nfuncsadded = 0 for item in mod.__dict__.values(): if isclass(item): for k, v in item.__dict__.items(): if isfunction(v): self.add_function(v) nfuncsadded += 1 elif isfunction(item): self.add_function(item) nfuncsadded += 1 return nfuncsadded def show_func(filename, start_lineno, func_name, timings, unit, output_unit=None, stream=None, stripzeros=False): """ Show results for a single function. """ if stream is None: stream = sys.stdout template = '%6s %9s %12s %8s %8s %-s' d = {} total_time = 0.0 linenos = [] for lineno, nhits, time in timings: total_time += time linenos.append(lineno) if stripzeros and total_time == 0: return if output_unit is None: output_unit = unit scalar = unit / output_unit stream.write("Total time: %g s\n" % (total_time * unit)) if os.path.exists(filename) or filename.startswith(" The given statement (which doesn't require quote marks) is run via the LineProfiler. Profiling is enabled for the functions specified by the -f options. The statistics will be shown side-by-side with the code through the pager once the statement has completed. Options: -f : LineProfiler only profiles functions and methods it is told to profile. This option tells the profiler about these functions. Multiple -f options may be used. The argument may be any expression that gives a Python function or method object. However, one must be careful to avoid spaces that may confuse the option parser. -m : Get all the functions/methods in a module One or more -f or -m options are required to get any useful results. -D : dump the raw statistics out to a pickle file on disk. The usual extension for this is ".lprof". These statistics may be viewed later by running line_profiler.py as a script. -T : dump the text-formatted statistics with the code side-by-side out to a text file. -r: return the LineProfiler object after it has completed profiling. -s: strip out all entries from the print-out that have zeros. -u: specify time unit for the print-out in seconds. """ # Escape quote markers. opts_def = Struct(D=[''], T=[''], f=[], m=[], u=None) parameter_s = parameter_s.replace('"', r'\"').replace("'", r"\'") opts, arg_str = self.parse_options(parameter_s, 'rsf:m:D:T:u:', list_all=True) opts.merge(opts_def) global_ns = self.shell.user_global_ns local_ns = self.shell.user_ns # Get the requested functions. funcs = [] for name in opts.f: try: funcs.append(eval(name, global_ns, local_ns)) except Exception as e: raise UsageError('Could not find function %r.\n%s: %s' % (name, e.__class__.__name__, e)) profile = LineProfiler(*funcs) # Get the modules, too for modname in opts.m: try: mod = __import__(modname, fromlist=['']) profile.add_module(mod) except Exception as e: raise UsageError('Could not find module %r.\n%s: %s' % (modname, e.__class__.__name__, e)) if opts.u is not None: try: output_unit = float(opts.u[0]) except Exception as e: raise TypeError("Timer unit setting must be a float.") else: output_unit = None # Add the profiler to the builtins for @profile. if PY3: import builtins else: import __builtin__ as builtins if 'profile' in builtins.__dict__: had_profile = True old_profile = builtins.__dict__['profile'] else: had_profile = False old_profile = None builtins.__dict__['profile'] = profile try: try: profile.runctx(arg_str, global_ns, local_ns) message = '' except SystemExit: message = """*** SystemExit exception caught in code being profiled.""" except KeyboardInterrupt: message = ("*** KeyboardInterrupt exception caught in code being " "profiled.") finally: if had_profile: builtins.__dict__['profile'] = old_profile # Trap text output. stdout_trap = StringIO() profile.print_stats(stdout_trap, output_unit=output_unit, stripzeros='s' in opts) output = stdout_trap.getvalue() output = output.rstrip() page(output) print(message, end="") dump_file = opts.D[0] if dump_file: profile.dump_stats(dump_file) print('\n*** Profile stats pickled to file %r. %s' % ( dump_file, message)) text_file = opts.T[0] if text_file: pfile = open(text_file, 'w') pfile.write(output) pfile.close() print('\n*** Profile printout saved to text file %r. %s' % ( text_file, message)) return_value = None if 'r' in opts: return_value = profile return return_value def load_ipython_extension(ip): """ API for IPython to recognize this module as an IPython extension. """ ip.register_magics(LineProfilerMagics) def load_stats(filename): """ Utility function to load a pickled LineStats object from a given filename. """ with open(filename, 'rb') as f: return pickle.load(f) def main(): usage = "usage: %prog profile.lprof" parser = optparse.OptionParser(usage=usage, version='%prog 1.0b2') options, args = parser.parse_args() if len(args) != 1: parser.error("Must provide a filename.") lstats = load_stats(args[0]) show_text(lstats.timings, lstats.unit) if __name__ == '__main__': main() line_profiler-2.1/line_profiler_py35.py000066400000000000000000000006511321604463700203000ustar00rootroot00000000000000""" This file is only imported in python 3.5 environments """ import functools def wrap_coroutine(self, func): """ Wrap a Python 3.5 coroutine to profile it. """ @functools.wraps(func) async def wrapper(*args, **kwds): self.enable_by_count() try: result = await func(*args, **kwds) finally: self.disable_by_count() return result return wrapper line_profiler-2.1/python25.pxd000066400000000000000000001172331321604463700164270ustar00rootroot00000000000000# From: Eric Huss # # Here is my latest copy. It does not cover 100% of the API. It should be # current up to 2.5. # # -Eric # XXX: # - Need to support "long long" definitions that are different for different platforms. # - Support unicode platform dependencies. # - Add unicode calls. # - Add setobject calls. cdef extern from "sys/types.h": ctypedef unsigned int size_t cdef extern from "stdio.h": ctypedef struct FILE: pass cdef extern from "Python.h": # XXX: This is platform dependent. ctypedef unsigned short Py_UNICODE ctypedef struct PyTypeObject: pass ctypedef struct PyObject: Py_ssize_t ob_refcnt PyTypeObject * ob_type ############################################################################################### # bool ############################################################################################### PyObject * Py_False PyObject * Py_True PyTypeObject PyBool_Type int PyBool_Check (object) # Always succeeds. object PyBool_FromLong (long) ############################################################################################### # buffer ############################################################################################### PyTypeObject PyBuffer_Type int Py_END_OF_BUFFER int PyBuffer_Check (object) # Always succeeds. object PyBuffer_FromMemory (void *, Py_ssize_t) object PyBuffer_FromObject (object, Py_ssize_t, Py_ssize_t) object PyBuffer_FromReadWriteMemory (void *, Py_ssize_t) object PyBuffer_FromReadWriteObject (object, Py_ssize_t, Py_ssize_t) object PyBuffer_New (Py_ssize_t) int PyObject_AsCharBuffer (object, char **, Py_ssize_t *) except -1 int PyObject_AsReadBuffer (object, void **, Py_ssize_t *) except -1 int PyObject_AsWriteBuffer (object, void **, Py_ssize_t *) except -1 int PyObject_CheckReadBuffer (object) # Always succeeds. ############################################################################################### # cobject ############################################################################################### PyTypeObject PyCObject_Type int PyCObject_Check(object) # Always succeeds. object PyCObject_FromVoidPtr(void *, void (*)(void*)) object PyCObject_FromVoidPtrAndDesc(void *, void *, void (*)(void*,void*)) void * PyCObject_AsVoidPtr(object) except NULL void * PyCObject_GetDesc(object) except NULL void * PyCObject_Import(char *, char *) except NULL ############################################################################################### # compile ############################################################################################### ctypedef struct PyCodeObject: int co_argcount int co_nlocals int co_stacksize int co_flags PyObject *co_code PyObject *co_consts PyObject *co_names PyObject *co_varnames PyObject *co_freevars PyObject *co_cellvars PyObject *co_filename PyObject *co_name int co_firstlineno PyObject *co_lnotab int PyCode_Addr2Line(PyCodeObject *, int) ############################################################################################### # complex ############################################################################################### ctypedef struct Py_complex: double real double imag PyTypeObject PyComplex_Type Py_complex PyComplex_AsCComplex (object) # Always succeeds. int PyComplex_Check (object) # Always succeeds. int PyComplex_CheckExact (object) # Always succeeds. object PyComplex_FromCComplex (Py_complex) object PyComplex_FromDoubles (double, double) double PyComplex_ImagAsDouble (object) except? -1 double PyComplex_RealAsDouble (object) except? -1 Py_complex _Py_c_diff (Py_complex, Py_complex) Py_complex _Py_c_neg (Py_complex) Py_complex _Py_c_pow (Py_complex, Py_complex) Py_complex _Py_c_prod (Py_complex, Py_complex) Py_complex _Py_c_quot (Py_complex, Py_complex) Py_complex _Py_c_sum (Py_complex, Py_complex) ############################################################################################### # dict ############################################################################################### PyTypeObject PyDict_Type int PyDict_Check (object) # Always succeeds. int PyDict_CheckExact (object) # Always succeeds. void PyDict_Clear (object) int PyDict_Contains (object, object) except -1 object PyDict_Copy (object) int PyDict_DelItem (object, object) except -1 int PyDict_DelItemString (object, char *) except -1 object PyDict_Items (object) object PyDict_Keys (object) int PyDict_Merge (object, object, int) except -1 int PyDict_MergeFromSeq2 (object, object, int) except -1 object PyDict_New () # XXX: Pyrex doesn't support pointer to a python object? #int PyDict_Next (object, Py_ssize_t *, object *, object *) # Always succeeds. int PyDict_SetItem (object, object, object) except -1 int PyDict_SetItemString (object, char *, object) except -1 Py_ssize_t PyDict_Size (object) except -1 int PyDict_Update (object, object) except -1 object PyDict_Values (object) # XXX: Borrowed reference. No exception on NULL. #object PyDict_GetItem (object, object) # XXX: Borrowed reference. No exception on NULL #object PyDict_GetItemString (object, char *) ############################################################################################### # float ############################################################################################### PyTypeObject PyFloat_Type int _PyFloat_Pack4 (double, unsigned char *, int) except -1 int _PyFloat_Pack8 (double, unsigned char *, int) except -1 double _PyFloat_Unpack4 (unsigned char *, int) except? -1 double _PyFloat_Unpack8 (unsigned char *, int) except? -1 double PyFloat_AS_DOUBLE (object) double PyFloat_AsDouble (object) except? -1 void PyFloat_AsReprString (char*, object) void PyFloat_AsString (char*, object) int PyFloat_Check (object) # Always succeeds. int PyFloat_CheckExact (object) # Always succeeds. object PyFloat_FromDouble (double) object PyFloat_FromString (object, char**) ############################################################################################### # frame ############################################################################################### ctypedef struct PyFrameObject: PyFrameObject *f_back PyCodeObject *f_code PyObject *f_builtins PyObject *f_globals PyObject *f_locals PyObject *f_trace PyObject *f_exc_type PyObject *f_exc_value PyObject *f_exc_traceback int f_lasti int f_lineno int f_restricted int f_iblock int f_nlocals int f_ncells int f_nfreevars int f_stacksize ############################################################################################### # int ############################################################################################### PyTypeObject PyInt_Type long PyInt_AS_LONG (object) # Always succeeds. long PyInt_AsLong (object) except? -1 Py_ssize_t PyInt_AsSsize_t (object) except? -1 unsigned long long PyInt_AsUnsignedLongLongMask (object) except? -1 unsigned long PyInt_AsUnsignedLongMask (object) except? -1 int PyInt_Check (object) # Always succeeds. int PyInt_CheckExact (object) # Always succeeds. object PyInt_FromLong (long) object PyInt_FromSsize_t (Py_ssize_t) object PyInt_FromString (char*, char**, int) object PyInt_FromUnicode (Py_UNICODE*, Py_ssize_t, int) long PyInt_GetMax () # Always succeeds. ############################################################################################### # iterator ############################################################################################### int PyIter_Check (object) # Always succeeds. object PyIter_Next (object) ############################################################################################### # list ############################################################################################### PyTypeObject PyList_Type int PyList_Append (object, object) except -1 object PyList_AsTuple (object) int PyList_Check (object) # Always succeeds. int PyList_CheckExact (object) # Always succeeds. int PyList_GET_SIZE (object) # Always suceeds. object PyList_GetSlice (object, Py_ssize_t, Py_ssize_t) int PyList_Insert (object, Py_ssize_t, object) except -1 object PyList_New (Py_ssize_t) int PyList_Reverse (object) except -1 int PyList_SetSlice (object, Py_ssize_t, Py_ssize_t, object) except -1 Py_ssize_t PyList_Size (object) except -1 int PyList_Sort (object) except -1 ############################################################################################### # long ############################################################################################### PyTypeObject PyLong_Type int _PyLong_AsByteArray (object, unsigned char *, size_t, int, int) except -1 object _PyLong_FromByteArray (unsigned char *, size_t, int, int) size_t _PyLong_NumBits (object) except -1 int _PyLong_Sign (object) # No error. long PyLong_AsLong (object) except? -1 long long PyLong_AsLongLong (object) except? -1 unsigned long PyLong_AsUnsignedLong (object) except? -1 unsigned long PyLong_AsUnsignedLongMask (object) except? -1 unsigned long long PyLong_AsUnsignedLongLong (object) except? -1 unsigned long long PyLong_AsUnsignedLongLongMask (object) except? -1 int PyLong_Check (object) # Always succeeds. int PyLong_CheckExact (object) # Always succeeds. object PyLong_FromDouble (double) object PyLong_FromLong (long) object PyLong_FromLongLong (long long) object PyLong_FromUnsignedLong (unsigned long) object PyLong_FromUnsignedLongLong (unsigned long long) double PyLong_AsDouble (object) except? -1 object PyLong_FromVoidPtr (void *) void * PyLong_AsVoidPtr (object) except NULL object PyLong_FromString (char *, char **, int) object PyLong_FromUnicode (Py_UNICODE*, Py_ssize_t, int) ############################################################################################### # mapping ############################################################################################### int PyMapping_Check (object) # Always succeeds. int PyMapping_DelItem (object, object) except -1 int PyMapping_DelItemString (object, char *) except -1 object PyMapping_GetItemString (object, char *) int PyMapping_HasKey (object, object) # Always succeeds. int PyMapping_HasKeyString (object, char *) # Always succeeds. object PyMapping_Items (object) object PyMapping_Keys (object) Py_ssize_t PyMapping_Length (object) except -1 int PyMapping_SetItemString (object, char *, object) except -1 Py_ssize_t PyMapping_Size (object) except -1 object PyMapping_Values (object) ############################################################################################### # mem ############################################################################################### void PyMem_Free (void * p) void * PyMem_Malloc (size_t n) void * PyMem_Realloc (void *, size_t) ############################################################################################### # modsupport ############################################################################################### object Py_BuildValue (char *, ...) object Py_VaBuildValue (char *, va_list) ############################################################################################### # number ############################################################################################### object PyNumber_Absolute (object) object PyNumber_Add (object, object) object PyNumber_And (object, object) Py_ssize_t PyNumber_AsSsize_t (object, object) except? -1 int PyNumber_Check (object) # Always succeeds. # XXX: Pyrex doesn't support pointer to python object? #int PyNumber_Coerce (object*, object*) except -1 object PyNumber_Divide (object, object) object PyNumber_Divmod (object, object) object PyNumber_Float (object) object PyNumber_FloorDivide (object, object) object PyNumber_InPlaceAdd (object, object) object PyNumber_InPlaceAnd (object, object) object PyNumber_InPlaceDivide (object, object) object PyNumber_InPlaceFloorDivide (object, object) object PyNumber_InPlaceLshift (object, object) object PyNumber_InPlaceMultiply (object, object) object PyNumber_InPlaceOr (object, object) object PyNumber_InPlacePower (object, object, object) object PyNumber_InPlaceRemainder (object, object) object PyNumber_InPlaceRshift (object, object) object PyNumber_InPlaceSubtract (object, object) object PyNumber_InPlaceTrueDivide (object, object) object PyNumber_InPlaceXor (object, object) object PyNumber_Int (object) object PyNumber_Invert (object) object PyNumber_Long (object) object PyNumber_Lshift (object, object) object PyNumber_Multiply (object, object) object PyNumber_Negative (object) object PyNumber_Or (object, object) object PyNumber_Positive (object) object PyNumber_Power (object, object, object) object PyNumber_Remainder (object, object) object PyNumber_Rshift (object, object) object PyNumber_Subtract (object, object) object PyNumber_TrueDivide (object, object) object PyNumber_Xor (object, object) ############################################################################################### # object ############################################################################################### int PyCallable_Check (object) # Always succeeds. int PyObject_AsFileDescriptor (object) except -1 object PyObject_Call (object, object, object) object PyObject_CallFunction (object, char *, ...) object PyObject_CallFunctionObjArgs (object, ...) object PyObject_CallMethod (object, char *, char *, ...) object PyObject_CallMethodObjArgs (object, object, ...) object PyObject_CallObject (object, object) int PyObject_Cmp (object, object, int *result) except -1 # Use PyObject_Cmp instead. #int PyObject_Compare (object, object) int PyObject_DelAttr (object, object) except -1 int PyObject_DelAttrString (object, char *) except -1 int PyObject_DelItem (object, object) except -1 int PyObject_DelItemString (object, char *) except -1 object PyObject_Dir (object) object PyObject_GetAttr (object, object) object PyObject_GetAttrString (object, char *) object PyObject_GetItem (object, object) object PyObject_GetIter (object) int PyObject_HasAttr (object, object) # Always succeeds. int PyObject_HasAttrString (object, char *) # Always succeeds. long PyObject_Hash (object) except -1 int PyObject_IsInstance (object, object) except -1 int PyObject_IsSubclass (object, object) except -1 int PyObject_IsTrue (object) except -1 Py_ssize_t PyObject_Length (object) except -1 int PyObject_Not (object) except -1 int PyObject_Print (object, FILE *, int) except -1 object PyObject_Repr (object) object PyObject_RichCompare (object, object, int) int PyObject_RichCompareBool (object, object, int) except -1 int PyObject_SetAttr (object, object, object) except -1 int PyObject_SetAttrString (object, char *, object) except -1 int PyObject_SetItem (object, object, object) except -1 Py_ssize_t PyObject_Size (object) except -1 object PyObject_Str (object) object PyObject_Type (object) int PyObject_TypeCheck (object, object) # Always succeeds. object PyObject_Unicode (object) ############################################################################################### # pyerrors ############################################################################################### int PyErr_BadArgument () void PyErr_BadInternalCall () int PyErr_CheckSignals () void PyErr_Clear () int PyErr_ExceptionMatches (object) object PyErr_Format (object, char *, ...) int PyErr_GivenExceptionMatches (object, object) object PyErr_NoMemory () object PyErr_Occurred () void PyErr_Restore (object, object, object) object PyErr_SetFromErrno (object) object PyErr_SetFromErrnoWithFilename (object, char *) object PyErr_SetFromErrnoWithFilenameObject (object, object) void PyErr_SetInterrupt () void PyErr_SetNone (object) void PyErr_SetObject (object, object) void PyErr_SetString (object, char *) int PyErr_Warn (object, char *) int PyErr_WarnExplicit (object, char *, char *, int, char *, object) void PyErr_WriteUnraisable (object) ############################################################################################### # pyeval # Be extremely careful with these functions. ############################################################################################### ctypedef struct PyThreadState: PyFrameObject * frame int recursion_depth void * curexc_type void * curexc_value void * curexc_traceback void * exc_type void * exc_value void * exc_traceback void PyEval_AcquireLock () void PyEval_ReleaseLock () void PyEval_AcquireThread (PyThreadState *) void PyEval_ReleaseThread (PyThreadState *) PyThreadState* PyEval_SaveThread () void PyEval_RestoreThread (PyThreadState *) ############################################################################################### # pystate # Be extremely careful with these functions. Read PEP 311 for more detail. ############################################################################################### ctypedef int PyGILState_STATE PyGILState_STATE PyGILState_Ensure () void PyGILState_Release (PyGILState_STATE) ctypedef struct PyInterpreterState: pass PyThreadState* PyThreadState_New (PyInterpreterState *) void PyThreadState_Clear (PyThreadState *) void PyThreadState_Delete (PyThreadState *) PyThreadState* PyThreadState_Get () PyThreadState* PyThreadState_Swap (PyThreadState *tstate) # XXX: Borrowed reference. #object PyThreadState_GetDict () ############################################################################################### # run # Functions for embedded interpreters are not included. ############################################################################################### ctypedef struct PyCompilerFlags: int cf_flags ctypedef struct _node: pass ctypedef void (*PyOS_sighandler_t)(int) void PyErr_Display (object, object, object) void PyErr_Print () void PyErr_PrintEx (int) char * PyOS_Readline (FILE *, FILE *, char *) PyOS_sighandler_t PyOS_getsig (int) PyOS_sighandler_t PyOS_setsig (int, PyOS_sighandler_t) _node * PyParser_SimpleParseFile (FILE *, char *, int) except NULL _node * PyParser_SimpleParseFileFlags (FILE *, char *, int, int) except NULL _node * PyParser_SimpleParseString (char *, int) except NULL _node * PyParser_SimpleParseStringFlagsFilename(char *, char *, int, int) except NULL _node * PyParser_SimpleParseStringFlags (char *, int, int) except NULL int PyRun_AnyFile (FILE *, char *) except -1 int PyRun_AnyFileEx (FILE *, char *, int) except -1 int PyRun_AnyFileExFlags (FILE *, char *, int, PyCompilerFlags *) except -1 int PyRun_AnyFileFlags (FILE *, char *, PyCompilerFlags *) except -1 object PyRun_File (FILE *, char *, int, object, object) object PyRun_FileEx (FILE *, char *, int, object, object, int) object PyRun_FileExFlags (FILE *, char *, int, object, object, int, PyCompilerFlags *) object PyRun_FileFlags (FILE *, char *, int, object, object, PyCompilerFlags *) int PyRun_InteractiveLoop (FILE *, char *) except -1 int PyRun_InteractiveLoopFlags (FILE *, char *, PyCompilerFlags *) except -1 int PyRun_InteractiveOne (FILE *, char *) except -1 int PyRun_InteractiveOneFlags (FILE *, char *, PyCompilerFlags *) except -1 int PyRun_SimpleFile (FILE *, char *) except -1 int PyRun_SimpleFileEx (FILE *, char *, int) except -1 int PyRun_SimpleFileExFlags (FILE *, char *, int, PyCompilerFlags *) except -1 int PyRun_SimpleString (char *) except -1 int PyRun_SimpleStringFlags (char *, PyCompilerFlags *) except -1 object PyRun_String (char *, int, object, object) object PyRun_StringFlags (char *, int, object, object, PyCompilerFlags *) int Py_AtExit (void (*func)()) object Py_CompileString (char *, char *, int) object Py_CompileStringFlags (char *, char *, int, PyCompilerFlags *) void Py_Exit (int) int Py_FdIsInteractive (FILE *, char *) # Always succeeds. char * Py_GetBuildInfo () char * Py_GetCompiler () char * Py_GetCopyright () char * Py_GetExecPrefix () char * Py_GetPath () char * Py_GetPlatform () char * Py_GetPrefix () char * Py_GetProgramFullPath () char * Py_GetProgramName () char * Py_GetPythonHome () char * Py_GetVersion () ############################################################################################### # sequence ############################################################################################### int PySequence_Check (object) # Always succeeds. object PySequence_Concat (object, object) int PySequence_Contains (object, object) except -1 Py_ssize_t PySequence_Count (object, object) except -1 int PySequence_DelItem (object, Py_ssize_t) except -1 int PySequence_DelSlice (object, Py_ssize_t, Py_ssize_t) except -1 object PySequence_Fast (object, char *) int PySequence_Fast_GET_SIZE (object) object PySequence_GetItem (object, Py_ssize_t) object PySequence_GetSlice (object, Py_ssize_t, Py_ssize_t) object PySequence_ITEM (object, int) int PySequence_In (object, object) except -1 object PySequence_InPlaceConcat (object, object) object PySequence_InPlaceRepeat (object, Py_ssize_t) Py_ssize_t PySequence_Index (object, object) except -1 Py_ssize_t PySequence_Length (object) except -1 object PySequence_List (object) object PySequence_Repeat (object, Py_ssize_t) int PySequence_SetItem (object, Py_ssize_t, object) except -1 int PySequence_SetSlice (object, Py_ssize_t, Py_ssize_t, object) except -1 Py_ssize_t PySequence_Size (object) except -1 object PySequence_Tuple (object) ############################################################################################### # string ############################################################################################### PyTypeObject PyString_Type # Pyrex cannot support resizing because you have no choice but to use # realloc which may call free() on the object, and there's no way to tell # Pyrex to "forget" reference counting for the object. #int _PyString_Resize (object *, Py_ssize_t) except -1 char * PyString_AS_STRING (object) # Always succeeds. object PyString_AsDecodedObject (object, char *, char *) object PyString_AsEncodedObject (object, char *, char *) object PyString_AsEncodedString (object, char *, char *) char * PyString_AsString (object) except NULL int PyString_AsStringAndSize (object, char **, Py_ssize_t *) except -1 int PyString_Check (object) # Always succeeds. int PyString_CHECK_INTERNED (object) # Always succeeds. int PyString_CheckExact (object) # Always succeeds. # XXX: Pyrex doesn't support pointer to a python object? #void PyString_Concat (object *, object) # XXX: Pyrex doesn't support pointer to a python object? #void PyString_ConcatAndDel (object *, object) object PyString_Decode (char *, int, char *, char *) object PyString_DecodeEscape (char *, int, char *, int, char *) object PyString_Encode (char *, int, char *, char *) object PyString_Format (object, object) object PyString_FromFormat (char*, ...) object PyString_FromFormatV (char*, va_list) object PyString_FromString (char *) object PyString_FromStringAndSize (char *, Py_ssize_t) Py_ssize_t PyString_GET_SIZE (object) # Always succeeds. object PyString_InternFromString (char *) # XXX: Pyrex doesn't support pointer to a python object? #void PyString_InternImmortal (object*) # XXX: Pyrex doesn't support pointer to a python object? #void PyString_InternInPlace (object*) object PyString_Repr (object, int) Py_ssize_t PyString_Size (object) except -1 # Disgusting hack to access internal object values. ctypedef struct PyStringObject: int ob_refcnt PyTypeObject * ob_type int ob_size long ob_shash int ob_sstate char * ob_sval ############################################################################################### # tuple ############################################################################################### PyTypeObject PyTuple_Type # See PyString_Resize note about resizing. #int _PyTuple_Resize (object*, Py_ssize_t) except -1 int PyTuple_Check (object) # Always succeeds. int PyTuple_CheckExact (object) # Always succeeds. Py_ssize_t PyTuple_GET_SIZE (object) # Always succeeds. object PyTuple_GetSlice (object, Py_ssize_t, Py_ssize_t) object PyTuple_New (Py_ssize_t) object PyTuple_Pack (Py_ssize_t, ...) Py_ssize_t PyTuple_Size (object) except -1 ############################################################################################### # Dangerous things! # Do not use these unless you really, really know what you are doing. ############################################################################################### void Py_INCREF (object) void Py_XINCREF (object) void Py_DECREF (object) void Py_XDECREF (object) void Py_CLEAR (object) # XXX: Stolen reference. void PyTuple_SET_ITEM (object, Py_ssize_t, value) # XXX: Borrowed reference. object PyTuple_GET_ITEM (object, Py_ssize_t) # XXX: Borrowed reference. object PyTuple_GetItem (object, Py_ssize_t) # XXX: Stolen reference. int PyTuple_SetItem (object, Py_ssize_t, object) except -1 # XXX: Steals reference. int PyList_SetItem (object, Py_ssize_t, object) except -1 # XXX: Borrowed reference object PyList_GetItem (object, Py_ssize_t) # XXX: Borrowed reference, no NULL on error. object PyList_GET_ITEM (object, Py_ssize_t) # XXX: Stolen reference. void PyList_SET_ITEM (object, Py_ssize_t, object) # XXX: Borrowed reference. object PySequence_Fast_GET_ITEM (object, Py_ssize_t) # First parameter _must_ be a PyStringObject. object _PyString_Join (object, object) line_profiler-2.1/setup.py000077500000000000000000000054551321604463700157410ustar00rootroot00000000000000import os import sys # Monkeypatch distutils. import setuptools import distutils.errors from distutils.core import setup from distutils.extension import Extension from distutils.log import warn try: from Cython.Distutils import build_ext cmdclass = dict(build_ext=build_ext) line_profiler_source = '_line_profiler.pyx' except ImportError: cmdclass = {} line_profiler_source = '_line_profiler.c' if not os.path.exists(line_profiler_source): raise distutils.errors.DistutilsError("""\ You need Cython to build the line_profiler from a git checkout, or alternatively use a release tarball from PyPI to build it without Cython.""") else: warn("Could not import Cython. " "Using the available pre-generated C file.") long_description = """\ line_profiler will profile the time individual lines of code take to execute. The profiler is implemented in C via Cython in order to reduce the overhead of profiling. Also included is the script kernprof.py which can be used to conveniently profile Python applications and scripts either with line_profiler or with the function-level profiling tools in the Python standard library. """ py_modules = ['line_profiler', 'kernprof'] if sys.version_info > (3, 4): py_modules += ['line_profiler_py35'] setup( name = 'line_profiler', version = '2.1', author = 'Robert Kern', author_email = 'robert.kern@enthought.com', description = 'Line-by-line profiler.', long_description = long_description, url = 'https://github.com/rkern/line_profiler', download_url = 'https://github.com/rkern/line_profiler/tarball/2.1', ext_modules = [ Extension('_line_profiler', sources=[line_profiler_source, 'timers.c', 'unset_trace.c'], depends=['python25.pxd'], ), ], license = "BSD", keywords = ['timing', 'timer', 'profiling', 'profiler', 'line_profiler'], classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: C", "Programming Language :: Python", 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: Implementation :: CPython', "Topic :: Software Development", ], py_modules = py_modules, entry_points = { 'console_scripts': [ 'kernprof=kernprof:main', ], }, install_requires = [ 'IPython>=0.13', ], cmdclass = cmdclass, ) line_profiler-2.1/tests/000077500000000000000000000000001321604463700153555ustar00rootroot00000000000000line_profiler-2.1/tests/_test_kernprof_py35.py000066400000000000000000000012321321604463700216310ustar00rootroot00000000000000from kernprof import ContextualProfile def test_coroutine_decorator(self): async def _(): async def c(x): """ A coroutine. """ y = x + 10 return y profile = ContextualProfile() c_wrapped = profile(c) self.assertEqual(c_wrapped.__name__, c.__name__) self.assertEqual(c_wrapped.__doc__, c.__doc__) self.assertEqual(profile.enable_count, 0) value = await c_wrapped(10) self.assertEqual(profile.enable_count, 0) self.assertEqual(value, await c(10)) import asyncio loop = asyncio.get_event_loop() loop.run_until_complete(_()) loop.close() line_profiler-2.1/tests/test_kernprof.py000066400000000000000000000050621321604463700206170ustar00rootroot00000000000000import unittest import sys from kernprof import ContextualProfile PY3 = sys.version_info[0] == 3 PY35 = PY3 and sys.version_info[1] >= 5 def f(x): """ A function. """ y = x + 10 return y def g(x): """ A generator. """ y = yield x + 10 yield y + 20 class TestKernprof(unittest.TestCase): def test_enable_disable(self): profile = ContextualProfile() self.assertEqual(profile.enable_count, 0) profile.enable_by_count() self.assertEqual(profile.enable_count, 1) profile.enable_by_count() self.assertEqual(profile.enable_count, 2) profile.disable_by_count() self.assertEqual(profile.enable_count, 1) profile.disable_by_count() self.assertEqual(profile.enable_count, 0) profile.disable_by_count() self.assertEqual(profile.enable_count, 0) with profile: self.assertEqual(profile.enable_count, 1) with profile: self.assertEqual(profile.enable_count, 2) self.assertEqual(profile.enable_count, 1) self.assertEqual(profile.enable_count, 0) with self.assertRaises(RuntimeError): self.assertEqual(profile.enable_count, 0) with profile: self.assertEqual(profile.enable_count, 1) raise RuntimeError() self.assertEqual(profile.enable_count, 0) def test_function_decorator(self): profile = ContextualProfile() f_wrapped = profile(f) self.assertEqual(f_wrapped.__name__, f.__name__) self.assertEqual(f_wrapped.__doc__, f.__doc__) self.assertEqual(profile.enable_count, 0) value = f_wrapped(10) self.assertEqual(profile.enable_count, 0) self.assertEqual(value, f(10)) def test_gen_decorator(self): profile = ContextualProfile() g_wrapped = profile(g) self.assertEqual(g_wrapped.__name__, g.__name__) self.assertEqual(g_wrapped.__doc__, g.__doc__) self.assertEqual(profile.enable_count, 0) i = g_wrapped(10) self.assertEqual(profile.enable_count, 0) self.assertEqual(next(i), 20) self.assertEqual(profile.enable_count, 0) self.assertEqual(i.send(30), 50) self.assertEqual(profile.enable_count, 0) with self.assertRaises(StopIteration): next(i) self.assertEqual(profile.enable_count, 0) if PY35: import _test_kernprof_py35 test_coroutine_decorator = _test_kernprof_py35.test_coroutine_decorator if __name__ == '__main__': unittest.main() line_profiler-2.1/tests/test_line_profiler.py000066400000000000000000000060031321604463700216160ustar00rootroot00000000000000import unittest from line_profiler import LineProfiler def f(x): y = x + 10 return y def g(x): y = yield x + 10 yield y + 20 class TestLineProfiler(unittest.TestCase): def test_init(self): lp = LineProfiler() self.assertEqual(lp.functions, []) self.assertEqual(lp.code_map, {}) lp = LineProfiler(f) self.assertEqual(lp.functions, [f]) self.assertEqual(lp.code_map, {f.__code__: {}}) lp = LineProfiler(f, g) self.assertEqual(lp.functions, [f, g]) self.assertEqual(lp.code_map, { f.__code__: {}, g.__code__: {}, }) def test_enable_disable(self): lp = LineProfiler() self.assertEqual(lp.enable_count, 0) lp.enable_by_count() self.assertEqual(lp.enable_count, 1) lp.enable_by_count() self.assertEqual(lp.enable_count, 2) lp.disable_by_count() self.assertEqual(lp.enable_count, 1) lp.disable_by_count() self.assertEqual(lp.enable_count, 0) self.assertEqual(lp.last_time, {}) lp.disable_by_count() self.assertEqual(lp.enable_count, 0) with lp: self.assertEqual(lp.enable_count, 1) with lp: self.assertEqual(lp.enable_count, 2) self.assertEqual(lp.enable_count, 1) self.assertEqual(lp.enable_count, 0) self.assertEqual(lp.last_time, {}) with self.assertRaises(RuntimeError): self.assertEqual(lp.enable_count, 0) with lp: self.assertEqual(lp.enable_count, 1) raise RuntimeError() self.assertEqual(lp.enable_count, 0) self.assertEqual(lp.last_time, {}) def test_function_decorator(self): profile = LineProfiler() f_wrapped = profile(f) self.assertEqual(f_wrapped.__name__, 'f') self.assertEqual(profile.enable_count, 0) value = f_wrapped(10) self.assertEqual(profile.enable_count, 0) self.assertEqual(value, f(10)) timings = profile.code_map[f.__code__] self.assertEqual(len(timings), 2) for timing in timings.values(): self.assertEqual(timing.nhits, 1) def test_gen_decorator(self): profile = LineProfiler() g_wrapped = profile(g) self.assertEqual(g_wrapped.__name__, 'g') timings = profile.code_map[g.__code__] self.assertEqual(profile.enable_count, 0) i = g_wrapped(10) self.assertEqual(profile.enable_count, 0) self.assertEqual(next(i), 20) self.assertEqual(profile.enable_count, 0) self.assertEqual(len(timings), 1) self.assertEqual(i.send(30), 50) self.assertEqual(profile.enable_count, 0) self.assertEqual(len(timings), 2) with self.assertRaises(StopIteration): next(i) self.assertEqual(profile.enable_count, 0) self.assertEqual(len(timings), 2) for timing in timings.values(): self.assertEqual(timing.nhits, 1) line_profiler-2.1/timers.c000066400000000000000000000023001321604463700156550ustar00rootroot00000000000000#include "Python.h" /* The following timer code comes from Python 2.5.2's _lsprof.c */ #if !defined(HAVE_LONG_LONG) #error "This module requires long longs!" #endif /*** Selection of a high-precision timer ***/ #ifdef MS_WINDOWS #include PY_LONG_LONG hpTimer(void) { LARGE_INTEGER li; QueryPerformanceCounter(&li); return li.QuadPart; } double hpTimerUnit(void) { LARGE_INTEGER li; if (QueryPerformanceFrequency(&li)) return 1.0 / li.QuadPart; else return 0.000001; /* unlikely */ } #else /* !MS_WINDOWS */ #ifndef HAVE_GETTIMEOFDAY #error "This module requires gettimeofday() on non-Windows platforms!" #endif #if (defined(PYOS_OS2) && defined(PYCC_GCC)) #include #else #include #include #endif PY_LONG_LONG hpTimer(void) { struct timeval tv; PY_LONG_LONG ret; #ifdef GETTIMEOFDAY_NO_TZ gettimeofday(&tv); #else gettimeofday(&tv, (struct timezone *)NULL); #endif ret = tv.tv_sec; ret = ret * 1000000 + tv.tv_usec; return ret; } double hpTimerUnit(void) { return 0.000001; } #endif /* MS_WINDOWS */ line_profiler-2.1/timers.h000066400000000000000000000001131321604463700156620ustar00rootroot00000000000000#include "Python.h" PY_LONG_LONG hpTimer(void); double hpTimerUnit(void); line_profiler-2.1/unset_trace.c000066400000000000000000000001761321604463700166770ustar00rootroot00000000000000/* Hack to hide an NULL from Cython. */ #include "Python.h" void unset_trace() { PyEval_SetTrace(NULL, NULL); } line_profiler-2.1/unset_trace.h000066400000000000000000000000241321604463700166740ustar00rootroot00000000000000void unset_trace();