Skip to content
This repository was archived by the owner on Jun 9, 2020. It is now read-only.

Commit d3cef04

Browse files
authored
Merge pull request #65 from caethan/master
Add compatibility with IPython 5.0+, remove support for IPython <0.13
2 parents 1960340 + 516a214 commit d3cef04

File tree

6 files changed

+129
-125
lines changed

6 files changed

+129
-125
lines changed

.travis.yml

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ language: python
22
python:
33
- "3.4"
44
- "3.3"
5-
- "3.2"
65
- "2.7"
76
install:
8-
- pip install --install-option='--no-cython-compile' -r dev_requirements.txt
7+
- pip install --install-option='--no-cython-compile' Cython
8+
- pip install -r dev_requirements.txt
99
- python setup.py develop
1010
script:
1111
- python -m unittest discover -v tests
1212
notifications:
1313
email:
14+
- brett.olsen+travis-ci@gmail.com
1415
- robert.kern+travis-ci@gmail.com

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
all:
22
@echo 'Just some tools to help me make releases. Nothing for users.'
33

4-
index.html: README.txt
5-
rst2html.py README.txt index.html
4+
index.html: README.rst
5+
rst2html.py README.rst index.html
66

77
pypi-site-docs.zip: index.html kernprof.py LICENSE.txt
88
zip -r $@ $?

README.rst

+5-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ They are available under a `BSD license`_.
1515
Installation
1616
============
1717

18-
Releases of `line_profiler` can be installed using pip_::
18+
Releases of `line_profiler` can be installed using pip::
1919

2020
$ pip install line_profiler
2121

@@ -355,6 +355,10 @@ Bugs and pull requested can be submitted on GitHub_.
355355
Changes
356356
=======
357357

358+
2.0
359+
~~~
360+
* BUG: Added support for IPython 5.0+, removed support for IPython <=0.12
361+
358362
1.1
359363
~~~
360364
* BUG: Read source files as bytes.

dev_requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
Cython
2+
IPython>=0.13

line_profiler.py

+112-119
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@
1717
import os
1818
import sys
1919

20+
from IPython.core.magic import (Magics, magics_class, line_magic)
21+
from IPython.core.page import page
22+
from IPython.utils.ipstruct import Struct
23+
from IPython.core.error import UsageError
24+
2025
from _line_profiler import LineProfiler as CLineProfiler
2126

2227
# Python 2/3 compatibility utils
@@ -226,150 +231,138 @@ def show_text(stats, unit, stream=None, stripzeros=False):
226231
for (fn, lineno, name), timings in sorted(stats.items()):
227232
show_func(fn, lineno, name, stats[fn, lineno, name], unit, stream=stream, stripzeros=stripzeros)
228233

229-
# A %lprun magic for IPython.
230-
def magic_lprun(self, parameter_s=''):
231-
""" Execute a statement under the line-by-line profiler from the
232-
line_profiler module.
234+
@magics_class
235+
class LineProfilerMagics(Magics):
233236

234-
Usage:
235-
%lprun -f func1 -f func2 <statement>
237+
@line_magic
238+
def lprun(self, parameter_s=''):
239+
""" Execute a statement under the line-by-line profiler from the
240+
line_profiler module.
236241
237-
The given statement (which doesn't require quote marks) is run via the
238-
LineProfiler. Profiling is enabled for the functions specified by the -f
239-
options. The statistics will be shown side-by-side with the code through the
240-
pager once the statement has completed.
242+
Usage:
243+
%lprun -f func1 -f func2 <statement>
241244
242-
Options:
245+
The given statement (which doesn't require quote marks) is run via the
246+
LineProfiler. Profiling is enabled for the functions specified by the -f
247+
options. The statistics will be shown side-by-side with the code through the
248+
pager once the statement has completed.
243249
244-
-f <function>: LineProfiler only profiles functions and methods it is told
245-
to profile. This option tells the profiler about these functions. Multiple
246-
-f options may be used. The argument may be any expression that gives
247-
a Python function or method object. However, one must be careful to avoid
248-
spaces that may confuse the option parser. Additionally, functions defined
249-
in the interpreter at the In[] prompt or via %run currently cannot be
250-
displayed. Write these functions out to a separate file and import them.
250+
Options:
251251
252-
-m <module>: Get all the functions/methods in a module
252+
-f <function>: LineProfiler only profiles functions and methods it is told
253+
to profile. This option tells the profiler about these functions. Multiple
254+
-f options may be used. The argument may be any expression that gives
255+
a Python function or method object. However, one must be careful to avoid
256+
spaces that may confuse the option parser. Additionally, functions defined
257+
in the interpreter at the In[] prompt or via %run currently cannot be
258+
displayed. Write these functions out to a separate file and import them.
253259
254-
One or more -f or -m options are required to get any useful results.
260+
-m <module>: Get all the functions/methods in a module
255261
256-
-D <filename>: dump the raw statistics out to a pickle file on disk. The
257-
usual extension for this is ".lprof". These statistics may be viewed later
258-
by running line_profiler.py as a script.
262+
One or more -f or -m options are required to get any useful results.
259263
260-
-T <filename>: dump the text-formatted statistics with the code side-by-side
261-
out to a text file.
264+
-D <filename>: dump the raw statistics out to a pickle file on disk. The
265+
usual extension for this is ".lprof". These statistics may be viewed later
266+
by running line_profiler.py as a script.
262267
263-
-r: return the LineProfiler object after it has completed profiling.
268+
-T <filename>: dump the text-formatted statistics with the code side-by-side
269+
out to a text file.
264270
265-
-s: strip out all entries from the print-out that have zeros.
266-
"""
267-
# Local imports to avoid hard dependency.
268-
from distutils.version import LooseVersion
269-
import IPython
270-
ipython_version = LooseVersion(IPython.__version__)
271-
if ipython_version < '0.11':
272-
from IPython.genutils import page
273-
from IPython.ipstruct import Struct
274-
from IPython.ipapi import UsageError
275-
else:
276-
from IPython.core.page import page
277-
from IPython.utils.ipstruct import Struct
278-
from IPython.core.error import UsageError
279-
280-
# Escape quote markers.
281-
opts_def = Struct(D=[''], T=[''], f=[], m=[])
282-
parameter_s = parameter_s.replace('"', r'\"').replace("'", r"\'")
283-
opts, arg_str = self.parse_options(parameter_s, 'rsf:m:D:T:', list_all=True)
284-
opts.merge(opts_def)
285-
286-
global_ns = self.shell.user_global_ns
287-
local_ns = self.shell.user_ns
288-
289-
# Get the requested functions.
290-
funcs = []
291-
for name in opts.f:
292-
try:
293-
funcs.append(eval(name, global_ns, local_ns))
294-
except Exception as e:
295-
raise UsageError('Could not find function %r.\n%s: %s' % (name,
296-
e.__class__.__name__, e))
271+
-r: return the LineProfiler object after it has completed profiling.
297272
298-
profile = LineProfiler(*funcs)
273+
-s: strip out all entries from the print-out that have zeros.
274+
"""
299275

300-
# Get the modules, too
301-
for modname in opts.m:
302-
try:
303-
mod = __import__(modname, fromlist=[''])
304-
profile.add_module(mod)
305-
except Exception as e:
306-
raise UsageError('Could not find module %r.\n%s: %s' % (modname,
307-
e.__class__.__name__, e))
308-
309-
# Add the profiler to the builtins for @profile.
310-
if PY3:
311-
import builtins
312-
else:
313-
import __builtin__ as builtins
276+
# Escape quote markers.
277+
opts_def = Struct(D=[''], T=[''], f=[], m=[])
278+
parameter_s = parameter_s.replace('"', r'\"').replace("'", r"\'")
279+
opts, arg_str = self.parse_options(parameter_s, 'rsf:m:D:T:', list_all=True)
280+
opts.merge(opts_def)
314281

315-
if 'profile' in builtins.__dict__:
316-
had_profile = True
317-
old_profile = builtins.__dict__['profile']
318-
else:
319-
had_profile = False
320-
old_profile = None
321-
builtins.__dict__['profile'] = profile
282+
global_ns = self.shell.user_global_ns
283+
local_ns = self.shell.user_ns
284+
285+
# Get the requested functions.
286+
funcs = []
287+
for name in opts.f:
288+
try:
289+
funcs.append(eval(name, global_ns, local_ns))
290+
except Exception as e:
291+
raise UsageError('Could not find function %r.\n%s: %s' % (name,
292+
e.__class__.__name__, e))
293+
294+
profile = LineProfiler(*funcs)
295+
296+
# Get the modules, too
297+
for modname in opts.m:
298+
try:
299+
mod = __import__(modname, fromlist=[''])
300+
profile.add_module(mod)
301+
except Exception as e:
302+
raise UsageError('Could not find module %r.\n%s: %s' % (modname,
303+
e.__class__.__name__, e))
304+
305+
# Add the profiler to the builtins for @profile.
306+
if PY3:
307+
import builtins
308+
else:
309+
import __builtin__ as builtins
310+
311+
if 'profile' in builtins.__dict__:
312+
had_profile = True
313+
old_profile = builtins.__dict__['profile']
314+
else:
315+
had_profile = False
316+
old_profile = None
317+
builtins.__dict__['profile'] = profile
322318

323-
try:
324319
try:
325-
profile.runctx(arg_str, global_ns, local_ns)
326-
message = ''
327-
except SystemExit:
328-
message = """*** SystemExit exception caught in code being profiled."""
329-
except KeyboardInterrupt:
330-
message = ("*** KeyboardInterrupt exception caught in code being "
331-
"profiled.")
332-
finally:
333-
if had_profile:
334-
builtins.__dict__['profile'] = old_profile
335-
336-
# Trap text output.
337-
stdout_trap = StringIO()
338-
profile.print_stats(stdout_trap, stripzeros='s' in opts)
339-
output = stdout_trap.getvalue()
340-
output = output.rstrip()
341-
342-
if ipython_version < '0.11':
343-
page(output, screen_lines=self.shell.rc.screen_length)
344-
else:
320+
try:
321+
profile.runctx(arg_str, global_ns, local_ns)
322+
message = ''
323+
except SystemExit:
324+
message = """*** SystemExit exception caught in code being profiled."""
325+
except KeyboardInterrupt:
326+
message = ("*** KeyboardInterrupt exception caught in code being "
327+
"profiled.")
328+
finally:
329+
if had_profile:
330+
builtins.__dict__['profile'] = old_profile
331+
332+
# Trap text output.
333+
stdout_trap = StringIO()
334+
profile.print_stats(stdout_trap, stripzeros='s' in opts)
335+
output = stdout_trap.getvalue()
336+
output = output.rstrip()
337+
345338
page(output)
346-
print(message, end="")
339+
print(message, end="")
347340

348-
dump_file = opts.D[0]
349-
if dump_file:
350-
profile.dump_stats(dump_file)
351-
print('\n*** Profile stats pickled to file %r. %s' % (
352-
dump_file, message))
341+
dump_file = opts.D[0]
342+
if dump_file:
343+
profile.dump_stats(dump_file)
344+
print('\n*** Profile stats pickled to file %r. %s' % (
345+
dump_file, message))
353346

354-
text_file = opts.T[0]
355-
if text_file:
356-
pfile = open(text_file, 'w')
357-
pfile.write(output)
358-
pfile.close()
359-
print('\n*** Profile printout saved to text file %r. %s' % (
360-
text_file, message))
347+
text_file = opts.T[0]
348+
if text_file:
349+
pfile = open(text_file, 'w')
350+
pfile.write(output)
351+
pfile.close()
352+
print('\n*** Profile printout saved to text file %r. %s' % (
353+
text_file, message))
361354

362-
return_value = None
363-
if 'r' in opts:
364-
return_value = profile
355+
return_value = None
356+
if 'r' in opts:
357+
return_value = profile
365358

366-
return return_value
359+
return return_value
367360

368361

369362
def load_ipython_extension(ip):
370363
""" API for IPython to recognize this module as an IPython extension.
371364
"""
372-
ip.define_magic('lprun', magic_lprun)
365+
ip.register_magics(LineProfilerMagics)
373366

374367

375368
def load_stats(filename):

setup.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,21 @@
3535

3636
setup(
3737
name = 'line_profiler',
38-
version = '1.0',
38+
version = '2.0',
3939
author = 'Robert Kern',
4040
author_email = 'robert.kern@enthought.com',
4141
description = 'Line-by-line profiler.',
4242
long_description = long_description,
4343
url = 'https://github.com/rkern/line_profiler',
44+
download_url = 'https://github.com/rkern/line_profiler/tarball/2.0',
4445
ext_modules = [
4546
Extension('_line_profiler',
4647
sources=[line_profiler_source, 'timers.c', 'unset_trace.c'],
4748
depends=['python25.pxd'],
4849
),
4950
],
5051
license = "BSD",
52+
keywords = ['timing', 'timer', 'profiling', 'profiler', 'line_profiler'],
5153
classifiers = [
5254
"Development Status :: 5 - Production/Stable",
5355
"Intended Audience :: Developers",
@@ -70,5 +72,8 @@
7072
'kernprof=kernprof:main',
7173
],
7274
},
75+
install_requires = [
76+
'IPython>=0.13',
77+
],
7378
cmdclass = cmdclass,
7479
)

0 commit comments

Comments
 (0)