##// END OF EJS Templates
Move pretty into lib, because it's heavily changed now.
Thomas Spura -
Show More
@@ -1,557 +1,557 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Display formatters.
3 3
4 4
5 5 Authors:
6 6
7 7 * Robert Kern
8 8 * Brian Granger
9 9 """
10 10 #-----------------------------------------------------------------------------
11 11 # Copyright (c) 2010, IPython Development Team.
12 12 #
13 13 # Distributed under the terms of the Modified BSD License.
14 14 #
15 15 # The full license is in the file COPYING.txt, distributed with this software.
16 16 #-----------------------------------------------------------------------------
17 17
18 18 #-----------------------------------------------------------------------------
19 19 # Imports
20 20 #-----------------------------------------------------------------------------
21 21
22 22 # Stdlib imports
23 23 import abc
24 24 import sys
25 25 # We must use StringIO, as cStringIO doesn't handle unicode properly.
26 26 from StringIO import StringIO
27 27
28 28 # Our own imports
29 29 from IPython.config.configurable import Configurable
30 from IPython.external import pretty
30 from IPython.lib import pretty
31 31 from IPython.utils.traitlets import Bool, Dict, Int, Str, CStr
32 32
33 33
34 34 #-----------------------------------------------------------------------------
35 35 # The main DisplayFormatter class
36 36 #-----------------------------------------------------------------------------
37 37
38 38
39 39 class DisplayFormatter(Configurable):
40 40
41 41 # When set to true only the default plain text formatter will be used.
42 42 plain_text_only = Bool(False, config=True)
43 43
44 44 # A dict of formatter whose keys are format types (MIME types) and whose
45 45 # values are subclasses of BaseFormatter.
46 46 formatters = Dict(config=True)
47 47 def _formatters_default(self):
48 48 """Activate the default formatters."""
49 49 formatter_classes = [
50 50 PlainTextFormatter,
51 51 HTMLFormatter,
52 52 SVGFormatter,
53 53 PNGFormatter,
54 54 LatexFormatter,
55 55 JSONFormatter
56 56 ]
57 57 d = {}
58 58 for cls in formatter_classes:
59 59 f = cls(config=self.config)
60 60 d[f.format_type] = f
61 61 return d
62 62
63 63 def format(self, obj, include=None, exclude=None):
64 64 """Return a format data dict for an object.
65 65
66 66 By default all format types will be computed.
67 67
68 68 The following MIME types are currently implemented:
69 69
70 70 * text/plain
71 71 * text/html
72 72 * text/latex
73 73 * application/json
74 74 * image/png
75 75 * immage/svg+xml
76 76
77 77 Parameters
78 78 ----------
79 79 obj : object
80 80 The Python object whose format data will be computed.
81 81 include : list or tuple, optional
82 82 A list of format type strings (MIME types) to include in the
83 83 format data dict. If this is set *only* the format types included
84 84 in this list will be computed.
85 85 exclude : list or tuple, optional
86 86 A list of format type string (MIME types) to exclue in the format
87 87 data dict. If this is set all format types will be computed,
88 88 except for those included in this argument.
89 89
90 90 Returns
91 91 -------
92 92 format_dict : dict
93 93 A dictionary of key/value pairs, one or each format that was
94 94 generated for the object. The keys are the format types, which
95 95 will usually be MIME type strings and the values and JSON'able
96 96 data structure containing the raw data for the representation in
97 97 that format.
98 98 """
99 99 format_dict = {}
100 100
101 101 # If plain text only is active
102 102 if self.plain_text_only:
103 103 formatter = self.formatters['text/plain']
104 104 try:
105 105 data = formatter(obj)
106 106 except:
107 107 # FIXME: log the exception
108 108 raise
109 109 if data is not None:
110 110 format_dict['text/plain'] = data
111 111 return format_dict
112 112
113 113 for format_type, formatter in self.formatters.items():
114 114 if include is not None:
115 115 if format_type not in include:
116 116 continue
117 117 if exclude is not None:
118 118 if format_type in exclude:
119 119 continue
120 120 try:
121 121 data = formatter(obj)
122 122 except:
123 123 # FIXME: log the exception
124 124 raise
125 125 if data is not None:
126 126 format_dict[format_type] = data
127 127 return format_dict
128 128
129 129 @property
130 130 def format_types(self):
131 131 """Return the format types (MIME types) of the active formatters."""
132 132 return self.formatters.keys()
133 133
134 134
135 135 #-----------------------------------------------------------------------------
136 136 # Formatters for specific format types (text, html, svg, etc.)
137 137 #-----------------------------------------------------------------------------
138 138
139 139
140 140 class FormatterABC(object):
141 141 """ Abstract base class for Formatters.
142 142
143 143 A formatter is a callable class that is responsible for computing the
144 144 raw format data for a particular format type (MIME type). For example,
145 145 an HTML formatter would have a format type of `text/html` and would return
146 146 the HTML representation of the object when called.
147 147 """
148 148 __metaclass__ = abc.ABCMeta
149 149
150 150 # The format type of the data returned, usually a MIME type.
151 151 format_type = 'text/plain'
152 152
153 153 # Is the formatter enabled...
154 154 enabled = True
155 155
156 156 @abc.abstractmethod
157 157 def __call__(self, obj):
158 158 """Return a JSON'able representation of the object.
159 159
160 160 If the object cannot be formatted by this formatter, then return None
161 161 """
162 162 try:
163 163 return repr(obj)
164 164 except TypeError:
165 165 return None
166 166
167 167
168 168 class BaseFormatter(Configurable):
169 169 """A base formatter class that is configurable.
170 170
171 171 This formatter should usually be used as the base class of all formatters.
172 172 It is a traited :class:`Configurable` class and includes an extensible
173 173 API for users to determine how their objects are formatted. The following
174 174 logic is used to find a function to format an given object.
175 175
176 176 1. The object is introspected to see if it has a method with the name
177 177 :attr:`print_method`. If is does, that object is passed to that method
178 178 for formatting.
179 179 2. If no print method is found, three internal dictionaries are consulted
180 180 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
181 181 and :attr:`deferred_printers`.
182 182
183 183 Users should use these dictionaries to register functions that will be
184 184 used to compute the format data for their objects (if those objects don't
185 185 have the special print methods). The easiest way of using these
186 186 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
187 187 methods.
188 188
189 189 If no function/callable is found to compute the format data, ``None`` is
190 190 returned and this format type is not used.
191 191 """
192 192
193 193 format_type = Str('text/plain')
194 194
195 195 enabled = Bool(True, config=True)
196 196
197 197 print_method = Str('__repr__')
198 198
199 199 # The singleton printers.
200 200 # Maps the IDs of the builtin singleton objects to the format functions.
201 201 singleton_printers = Dict(config=True)
202 202 def _singleton_printers_default(self):
203 203 return {}
204 204
205 205 # The type-specific printers.
206 206 # Map type objects to the format functions.
207 207 type_printers = Dict(config=True)
208 208 def _type_printers_default(self):
209 209 return {}
210 210
211 211 # The deferred-import type-specific printers.
212 212 # Map (modulename, classname) pairs to the format functions.
213 213 deferred_printers = Dict(config=True)
214 214 def _deferred_printers_default(self):
215 215 return {}
216 216
217 217 def __call__(self, obj):
218 218 """Compute the format for an object."""
219 219 if self.enabled:
220 220 obj_id = id(obj)
221 221 try:
222 222 obj_class = getattr(obj, '__class__', None) or type(obj)
223 223 if hasattr(obj_class, self.print_method):
224 224 printer = getattr(obj_class, self.print_method)
225 225 return printer(obj)
226 226 try:
227 227 printer = self.singleton_printers[obj_id]
228 228 except (TypeError, KeyError):
229 229 pass
230 230 else:
231 231 return printer(obj)
232 232 for cls in pretty._get_mro(obj_class):
233 233 if cls in self.type_printers:
234 234 return self.type_printers[cls](obj)
235 235 else:
236 236 printer = self._in_deferred_types(cls)
237 237 if printer is not None:
238 238 return printer(obj)
239 239 return None
240 240 except Exception:
241 241 pass
242 242 else:
243 243 return None
244 244
245 245 def for_type(self, typ, func):
246 246 """Add a format function for a given type.
247 247
248 248 Parameters
249 249 -----------
250 250 typ : class
251 251 The class of the object that will be formatted using `func`.
252 252 func : callable
253 253 The callable that will be called to compute the format data. The
254 254 call signature of this function is simple, it must take the
255 255 object to be formatted and return the raw data for the given
256 256 format. Subclasses may use a different call signature for the
257 257 `func` argument.
258 258 """
259 259 oldfunc = self.type_printers.get(typ, None)
260 260 if func is not None:
261 261 # To support easy restoration of old printers, we need to ignore
262 262 # Nones.
263 263 self.type_printers[typ] = func
264 264 return oldfunc
265 265
266 266 def for_type_by_name(self, type_module, type_name, func):
267 267 """Add a format function for a type specified by the full dotted
268 268 module and name of the type, rather than the type of the object.
269 269
270 270 Parameters
271 271 ----------
272 272 type_module : str
273 273 The full dotted name of the module the type is defined in, like
274 274 ``numpy``.
275 275 type_name : str
276 276 The name of the type (the class name), like ``dtype``
277 277 func : callable
278 278 The callable that will be called to compute the format data. The
279 279 call signature of this function is simple, it must take the
280 280 object to be formatted and return the raw data for the given
281 281 format. Subclasses may use a different call signature for the
282 282 `func` argument.
283 283 """
284 284 key = (type_module, type_name)
285 285 oldfunc = self.deferred_printers.get(key, None)
286 286 if func is not None:
287 287 # To support easy restoration of old printers, we need to ignore
288 288 # Nones.
289 289 self.deferred_printers[key] = func
290 290 return oldfunc
291 291
292 292 def _in_deferred_types(self, cls):
293 293 """
294 294 Check if the given class is specified in the deferred type registry.
295 295
296 296 Returns the printer from the registry if it exists, and None if the
297 297 class is not in the registry. Successful matches will be moved to the
298 298 regular type registry for future use.
299 299 """
300 300 mod = getattr(cls, '__module__', None)
301 301 name = getattr(cls, '__name__', None)
302 302 key = (mod, name)
303 303 printer = None
304 304 if key in self.deferred_printers:
305 305 # Move the printer over to the regular registry.
306 306 printer = self.deferred_printers.pop(key)
307 307 self.type_printers[cls] = printer
308 308 return printer
309 309
310 310
311 311 class PlainTextFormatter(BaseFormatter):
312 312 """The default pretty-printer.
313 313
314 314 This uses :mod:`IPython.external.pretty` to compute the format data of
315 315 the object. If the object cannot be pretty printed, :func:`repr` is used.
316 316 See the documentation of :mod:`IPython.external.pretty` for details on
317 317 how to write pretty printers. Here is a simple example::
318 318
319 319 def dtype_pprinter(obj, p, cycle):
320 320 if cycle:
321 321 return p.text('dtype(...)')
322 322 if hasattr(obj, 'fields'):
323 323 if obj.fields is None:
324 324 p.text(repr(obj))
325 325 else:
326 326 p.begin_group(7, 'dtype([')
327 327 for i, field in enumerate(obj.descr):
328 328 if i > 0:
329 329 p.text(',')
330 330 p.breakable()
331 331 p.pretty(field)
332 332 p.end_group(7, '])')
333 333 """
334 334
335 335 # The format type of data returned.
336 336 format_type = Str('text/plain')
337 337
338 338 # This subclass ignores this attribute as it always need to return
339 339 # something.
340 340 enabled = Bool(True, config=False)
341 341
342 342 # Look for a __pretty__ methods to use for pretty printing.
343 343 print_method = Str('__pretty__')
344 344
345 345 # Whether to pretty-print or not.
346 346 pprint = Bool(True, config=True)
347 347
348 348 # Whether to be verbose or not.
349 349 verbose = Bool(False, config=True)
350 350
351 351 # The maximum width.
352 352 max_width = Int(79, config=True)
353 353
354 354 # The newline character.
355 355 newline = Str('\n', config=True)
356 356
357 357 # format-string for pprinting floats
358 358 float_format = Str('%r')
359 359 # setter for float precision, either int or direct format-string
360 360 float_precision = CStr('', config=True)
361 361
362 362 def _float_precision_changed(self, name, old, new):
363 363 """float_precision changed, set float_format accordingly.
364 364
365 365 float_precision can be set by int or str.
366 366 This will set float_format, after interpreting input.
367 367 If numpy has been imported, numpy print precision will also be set.
368 368
369 369 integer `n` sets format to '%.nf', otherwise, format set directly.
370 370
371 371 An empty string returns to defaults (repr for float, 8 for numpy).
372 372
373 373 This parameter can be set via the '%precision' magic.
374 374 """
375 375
376 376 if '%' in new:
377 377 # got explicit format string
378 378 fmt = new
379 379 try:
380 380 fmt%3.14159
381 381 except Exception:
382 382 raise ValueError("Precision must be int or format string, not %r"%new)
383 383 elif new:
384 384 # otherwise, should be an int
385 385 try:
386 386 i = int(new)
387 387 assert i >= 0
388 388 except ValueError:
389 389 raise ValueError("Precision must be int or format string, not %r"%new)
390 390 except AssertionError:
391 391 raise ValueError("int precision must be non-negative, not %r"%i)
392 392
393 393 fmt = '%%.%if'%i
394 394 if 'numpy' in sys.modules:
395 395 # set numpy precision if it has been imported
396 396 import numpy
397 397 numpy.set_printoptions(precision=i)
398 398 else:
399 399 # default back to repr
400 400 fmt = '%r'
401 401 if 'numpy' in sys.modules:
402 402 import numpy
403 403 # numpy default is 8
404 404 numpy.set_printoptions(precision=8)
405 405 self.float_format = fmt
406 406
407 407 # Use the default pretty printers from IPython.external.pretty.
408 408 def _singleton_printers_default(self):
409 409 return pretty._singleton_pprinters.copy()
410 410
411 411 def _type_printers_default(self):
412 412 d = pretty._type_pprinters.copy()
413 413 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
414 414 return d
415 415
416 416 def _deferred_printers_default(self):
417 417 return pretty._deferred_type_pprinters.copy()
418 418
419 419 #### FormatterABC interface ####
420 420
421 421 def __call__(self, obj):
422 422 """Compute the pretty representation of the object."""
423 423 if not self.pprint:
424 424 try:
425 425 return repr(obj)
426 426 except TypeError:
427 427 return ''
428 428 else:
429 429 # This uses use StringIO, as cStringIO doesn't handle unicode.
430 430 stream = StringIO()
431 431 printer = pretty.RepresentationPrinter(stream, self.verbose,
432 432 self.max_width, self.newline,
433 433 singleton_pprinters=self.singleton_printers,
434 434 type_pprinters=self.type_printers,
435 435 deferred_pprinters=self.deferred_printers)
436 436 printer.pretty(obj)
437 437 printer.flush()
438 438 return stream.getvalue()
439 439
440 440
441 441 class HTMLFormatter(BaseFormatter):
442 442 """An HTML formatter.
443 443
444 444 To define the callables that compute the HTML representation of your
445 445 objects, define a :meth:`__html__` method or use the :meth:`for_type`
446 446 or :meth:`for_type_by_name` methods to register functions that handle
447 447 this.
448 448 """
449 449 format_type = Str('text/html')
450 450
451 451 print_method = Str('__html__')
452 452
453 453
454 454 class SVGFormatter(BaseFormatter):
455 455 """An SVG formatter.
456 456
457 457 To define the callables that compute the SVG representation of your
458 458 objects, define a :meth:`__svg__` method or use the :meth:`for_type`
459 459 or :meth:`for_type_by_name` methods to register functions that handle
460 460 this.
461 461 """
462 462 format_type = Str('image/svg+xml')
463 463
464 464 print_method = Str('__svg__')
465 465
466 466
467 467 class PNGFormatter(BaseFormatter):
468 468 """A PNG formatter.
469 469
470 470 To define the callables that compute the PNG representation of your
471 471 objects, define a :meth:`__png__` method or use the :meth:`for_type`
472 472 or :meth:`for_type_by_name` methods to register functions that handle
473 473 this. The raw data should be the base64 encoded raw png data.
474 474 """
475 475 format_type = Str('image/png')
476 476
477 477 print_method = Str('__png__')
478 478
479 479
480 480 class LatexFormatter(BaseFormatter):
481 481 """A LaTeX formatter.
482 482
483 483 To define the callables that compute the LaTeX representation of your
484 484 objects, define a :meth:`__latex__` method or use the :meth:`for_type`
485 485 or :meth:`for_type_by_name` methods to register functions that handle
486 486 this.
487 487 """
488 488 format_type = Str('text/latex')
489 489
490 490 print_method = Str('__latex__')
491 491
492 492
493 493 class JSONFormatter(BaseFormatter):
494 494 """A JSON string formatter.
495 495
496 496 To define the callables that compute the JSON string representation of
497 497 your objects, define a :meth:`__json__` method or use the :meth:`for_type`
498 498 or :meth:`for_type_by_name` methods to register functions that handle
499 499 this.
500 500 """
501 501 format_type = Str('application/json')
502 502
503 503 print_method = Str('__json__')
504 504
505 505
506 506 FormatterABC.register(BaseFormatter)
507 507 FormatterABC.register(PlainTextFormatter)
508 508 FormatterABC.register(HTMLFormatter)
509 509 FormatterABC.register(SVGFormatter)
510 510 FormatterABC.register(PNGFormatter)
511 511 FormatterABC.register(LatexFormatter)
512 512 FormatterABC.register(JSONFormatter)
513 513
514 514
515 515 def format_display_data(obj, include=None, exclude=None):
516 516 """Return a format data dict for an object.
517 517
518 518 By default all format types will be computed.
519 519
520 520 The following MIME types are currently implemented:
521 521
522 522 * text/plain
523 523 * text/html
524 524 * text/latex
525 525 * application/json
526 526 * image/png
527 527 * immage/svg+xml
528 528
529 529 Parameters
530 530 ----------
531 531 obj : object
532 532 The Python object whose format data will be computed.
533 533
534 534 Returns
535 535 -------
536 536 format_dict : dict
537 537 A dictionary of key/value pairs, one or each format that was
538 538 generated for the object. The keys are the format types, which
539 539 will usually be MIME type strings and the values and JSON'able
540 540 data structure containing the raw data for the representation in
541 541 that format.
542 542 include : list or tuple, optional
543 543 A list of format type strings (MIME types) to include in the
544 544 format data dict. If this is set *only* the format types included
545 545 in this list will be computed.
546 546 exclude : list or tuple, optional
547 547 A list of format type string (MIME types) to exclue in the format
548 548 data dict. If this is set all format types will be computed,
549 549 except for those included in this argument.
550 550 """
551 551 from IPython.core.interactiveshell import InteractiveShell
552 552
553 553 InteractiveShell.instance().display_formatter.format(
554 554 obj,
555 555 include,
556 556 exclude
557 557 )
1 NO CONTENT: file renamed from IPython/external/pretty/_pretty.py to IPython/lib/pretty.py
@@ -1,381 +1,380 b''
1 1 # encoding: utf-8
2 2 """
3 3 This module defines the things that are used in setup.py for building IPython
4 4
5 5 This includes:
6 6
7 7 * The basic arguments to setup
8 8 * Functions for finding things like packages, package data, etc.
9 9 * A function for checking dependencies.
10 10 """
11 11 from __future__ import print_function
12 12
13 13 #-------------------------------------------------------------------------------
14 14 # Copyright (C) 2008 The IPython Development Team
15 15 #
16 16 # Distributed under the terms of the BSD License. The full license is in
17 17 # the file COPYING, distributed as part of this software.
18 18 #-------------------------------------------------------------------------------
19 19
20 20 #-------------------------------------------------------------------------------
21 21 # Imports
22 22 #-------------------------------------------------------------------------------
23 23 import os
24 24 import sys
25 25
26 26 from ConfigParser import ConfigParser
27 27 from distutils.command.build_py import build_py
28 28 from glob import glob
29 29
30 30 from setupext import install_data_ext
31 31
32 32 #-------------------------------------------------------------------------------
33 33 # Useful globals and utility functions
34 34 #-------------------------------------------------------------------------------
35 35
36 36 # A few handy globals
37 37 isfile = os.path.isfile
38 38 pjoin = os.path.join
39 39
40 40 def oscmd(s):
41 41 print(">", s)
42 42 os.system(s)
43 43
44 44 # A little utility we'll need below, since glob() does NOT allow you to do
45 45 # exclusion on multiple endings!
46 46 def file_doesnt_endwith(test,endings):
47 47 """Return true if test is a file and its name does NOT end with any
48 48 of the strings listed in endings."""
49 49 if not isfile(test):
50 50 return False
51 51 for e in endings:
52 52 if test.endswith(e):
53 53 return False
54 54 return True
55 55
56 56 #---------------------------------------------------------------------------
57 57 # Basic project information
58 58 #---------------------------------------------------------------------------
59 59
60 60 # release.py contains version, authors, license, url, keywords, etc.
61 61 execfile(pjoin('IPython','core','release.py'))
62 62
63 63 # Create a dict with the basic information
64 64 # This dict is eventually passed to setup after additional keys are added.
65 65 setup_args = dict(
66 66 name = name,
67 67 version = version,
68 68 description = description,
69 69 long_description = long_description,
70 70 author = author,
71 71 author_email = author_email,
72 72 url = url,
73 73 download_url = download_url,
74 74 license = license,
75 75 platforms = platforms,
76 76 keywords = keywords,
77 77 cmdclass = {'install_data': install_data_ext},
78 78 )
79 79
80 80
81 81 #---------------------------------------------------------------------------
82 82 # Find packages
83 83 #---------------------------------------------------------------------------
84 84
85 85 def add_package(packages,pname,config=False,tests=False,scripts=False,
86 86 others=None):
87 87 """
88 88 Add a package to the list of packages, including certain subpackages.
89 89 """
90 90 packages.append('.'.join(['IPython',pname]))
91 91 if config:
92 92 packages.append('.'.join(['IPython',pname,'config']))
93 93 if tests:
94 94 packages.append('.'.join(['IPython',pname,'tests']))
95 95 if scripts:
96 96 packages.append('.'.join(['IPython',pname,'scripts']))
97 97 if others is not None:
98 98 for o in others:
99 99 packages.append('.'.join(['IPython',pname,o]))
100 100
101 101 def find_packages():
102 102 """
103 103 Find all of IPython's packages.
104 104 """
105 105 packages = ['IPython']
106 106 add_package(packages, 'config', tests=True, others=['default','profile'])
107 107 add_package(packages, 'core', tests=True)
108 108 add_package(packages, 'deathrow', tests=True)
109 109 add_package(packages, 'extensions')
110 110 add_package(packages, 'external')
111 111 add_package(packages, 'external.argparse')
112 112 add_package(packages, 'external.configobj')
113 113 add_package(packages, 'external.decorator')
114 114 add_package(packages, 'external.decorators')
115 115 add_package(packages, 'external.guid')
116 116 add_package(packages, 'external.Itpl')
117 117 add_package(packages, 'external.mglob')
118 118 add_package(packages, 'external.path')
119 add_package(packages, 'external.pretty')
120 119 add_package(packages, 'external.pyparsing')
121 120 add_package(packages, 'external.simplegeneric')
122 121 add_package(packages, 'external.validate')
123 122 add_package(packages, 'frontend')
124 123 add_package(packages, 'frontend.qt')
125 124 add_package(packages, 'frontend.qt.console', tests=True)
126 125 add_package(packages, 'frontend.terminal', tests=True)
127 126 add_package(packages, 'kernel', config=False, tests=True, scripts=True)
128 127 add_package(packages, 'kernel.core', config=False, tests=True)
129 128 add_package(packages, 'lib', tests=True)
130 129 add_package(packages, 'quarantine', tests=True)
131 130 add_package(packages, 'scripts')
132 131 add_package(packages, 'testing', tests=True)
133 132 add_package(packages, 'testing.plugin', tests=False)
134 133 add_package(packages, 'utils', tests=True)
135 134 add_package(packages, 'zmq')
136 135 add_package(packages, 'zmq.pylab')
137 136 return packages
138 137
139 138 #---------------------------------------------------------------------------
140 139 # Find package data
141 140 #---------------------------------------------------------------------------
142 141
143 142 def find_package_data():
144 143 """
145 144 Find IPython's package_data.
146 145 """
147 146 # This is not enough for these things to appear in an sdist.
148 147 # We need to muck with the MANIFEST to get this to work
149 148 package_data = {
150 149 'IPython.config.userconfig' : ['*'],
151 150 'IPython.testing' : ['*.txt']
152 151 }
153 152 return package_data
154 153
155 154
156 155 #---------------------------------------------------------------------------
157 156 # Find data files
158 157 #---------------------------------------------------------------------------
159 158
160 159 def make_dir_struct(tag,base,out_base):
161 160 """Make the directory structure of all files below a starting dir.
162 161
163 162 This is just a convenience routine to help build a nested directory
164 163 hierarchy because distutils is too stupid to do this by itself.
165 164
166 165 XXX - this needs a proper docstring!
167 166 """
168 167
169 168 # we'll use these a lot below
170 169 lbase = len(base)
171 170 pathsep = os.path.sep
172 171 lpathsep = len(pathsep)
173 172
174 173 out = []
175 174 for (dirpath,dirnames,filenames) in os.walk(base):
176 175 # we need to strip out the dirpath from the base to map it to the
177 176 # output (installation) path. This requires possibly stripping the
178 177 # path separator, because otherwise pjoin will not work correctly
179 178 # (pjoin('foo/','/bar') returns '/bar').
180 179
181 180 dp_eff = dirpath[lbase:]
182 181 if dp_eff.startswith(pathsep):
183 182 dp_eff = dp_eff[lpathsep:]
184 183 # The output path must be anchored at the out_base marker
185 184 out_path = pjoin(out_base,dp_eff)
186 185 # Now we can generate the final filenames. Since os.walk only produces
187 186 # filenames, we must join back with the dirpath to get full valid file
188 187 # paths:
189 188 pfiles = [pjoin(dirpath,f) for f in filenames]
190 189 # Finally, generate the entry we need, which is a pari of (output
191 190 # path, files) for use as a data_files parameter in install_data.
192 191 out.append((out_path, pfiles))
193 192
194 193 return out
195 194
196 195
197 196 def find_data_files():
198 197 """
199 198 Find IPython's data_files.
200 199
201 200 Most of these are docs.
202 201 """
203 202
204 203 docdirbase = pjoin('share', 'doc', 'ipython')
205 204 manpagebase = pjoin('share', 'man', 'man1')
206 205
207 206 # Simple file lists can be made by hand
208 207 manpages = filter(isfile, glob(pjoin('docs','man','*.1.gz')))
209 208 igridhelpfiles = filter(isfile,
210 209 glob(pjoin('IPython','extensions','igrid_help.*')))
211 210
212 211 # For nested structures, use the utility above
213 212 example_files = make_dir_struct(
214 213 'data',
215 214 pjoin('docs','examples'),
216 215 pjoin(docdirbase,'examples')
217 216 )
218 217 manual_files = make_dir_struct(
219 218 'data',
220 219 pjoin('docs','dist'),
221 220 pjoin(docdirbase,'manual')
222 221 )
223 222
224 223 # And assemble the entire output list
225 224 data_files = [ (manpagebase, manpages),
226 225 (pjoin(docdirbase, 'extensions'), igridhelpfiles),
227 226 ] + manual_files + example_files
228 227
229 228 return data_files
230 229
231 230
232 231 def make_man_update_target(manpage):
233 232 """Return a target_update-compliant tuple for the given manpage.
234 233
235 234 Parameters
236 235 ----------
237 236 manpage : string
238 237 Name of the manpage, must include the section number (trailing number).
239 238
240 239 Example
241 240 -------
242 241
243 242 >>> make_man_update_target('ipython.1') #doctest: +NORMALIZE_WHITESPACE
244 243 ('docs/man/ipython.1.gz',
245 244 ['docs/man/ipython.1'],
246 245 'cd docs/man && gzip -9c ipython.1 > ipython.1.gz')
247 246 """
248 247 man_dir = pjoin('docs', 'man')
249 248 manpage_gz = manpage + '.gz'
250 249 manpath = pjoin(man_dir, manpage)
251 250 manpath_gz = pjoin(man_dir, manpage_gz)
252 251 gz_cmd = ( "cd %(man_dir)s && gzip -9c %(manpage)s > %(manpage_gz)s" %
253 252 locals() )
254 253 return (manpath_gz, [manpath], gz_cmd)
255 254
256 255 #---------------------------------------------------------------------------
257 256 # Find scripts
258 257 #---------------------------------------------------------------------------
259 258
260 259 def find_scripts():
261 260 """
262 261 Find IPython's scripts.
263 262 """
264 263 kernel_scripts = pjoin('IPython','kernel','scripts')
265 264 main_scripts = pjoin('IPython','scripts')
266 265 scripts = [pjoin(kernel_scripts, 'ipengine'),
267 266 pjoin(kernel_scripts, 'ipcontroller'),
268 267 pjoin(kernel_scripts, 'ipcluster'),
269 268 pjoin(main_scripts, 'ipython'),
270 269 pjoin(main_scripts, 'ipython-qtconsole'),
271 270 pjoin(main_scripts, 'pycolor'),
272 271 pjoin(main_scripts, 'irunner'),
273 272 pjoin(main_scripts, 'iptest')
274 273 ]
275 274
276 275 # Script to be run by the windows binary installer after the default setup
277 276 # routine, to add shortcuts and similar windows-only things. Windows
278 277 # post-install scripts MUST reside in the scripts/ dir, otherwise distutils
279 278 # doesn't find them.
280 279 if 'bdist_wininst' in sys.argv:
281 280 if len(sys.argv) > 2 and \
282 281 ('sdist' in sys.argv or 'bdist_rpm' in sys.argv):
283 282 print("ERROR: bdist_wininst must be run alone. Exiting.",
284 283 file=sys.stderr)
285 284 sys.exit(1)
286 285 scripts.append(pjoin('scripts','ipython_win_post_install.py'))
287 286
288 287 return scripts
289 288
290 289 #---------------------------------------------------------------------------
291 290 # Verify all dependencies
292 291 #---------------------------------------------------------------------------
293 292
294 293 def check_for_dependencies():
295 294 """Check for IPython's dependencies.
296 295
297 296 This function should NOT be called if running under setuptools!
298 297 """
299 298 from setupext.setupext import (
300 299 print_line, print_raw, print_status,
301 300 check_for_zopeinterface, check_for_twisted,
302 301 check_for_foolscap, check_for_pyopenssl,
303 302 check_for_sphinx, check_for_pygments,
304 303 check_for_nose, check_for_pexpect
305 304 )
306 305 print_line()
307 306 print_raw("BUILDING IPYTHON")
308 307 print_status('python', sys.version)
309 308 print_status('platform', sys.platform)
310 309 if sys.platform == 'win32':
311 310 print_status('Windows version', sys.getwindowsversion())
312 311
313 312 print_raw("")
314 313 print_raw("OPTIONAL DEPENDENCIES")
315 314
316 315 check_for_zopeinterface()
317 316 check_for_twisted()
318 317 check_for_foolscap()
319 318 check_for_pyopenssl()
320 319 check_for_sphinx()
321 320 check_for_pygments()
322 321 check_for_nose()
323 322 check_for_pexpect()
324 323
325 324
326 325 def record_commit_info(pkg_dir, build_cmd=build_py):
327 326 """ Return extended build command class for recording commit
328 327
329 328 The extended command tries to run git to find the current commit, getting
330 329 the empty string if it fails. It then writes the commit hash into a file
331 330 in the `pkg_dir` path, named ``.git_commit_info.ini``.
332 331
333 332 In due course this information can be used by the package after it is
334 333 installed, to tell you what commit it was installed from if known.
335 334
336 335 To make use of this system, you need a package with a .git_commit_info.ini
337 336 file - e.g. ``myproject/.git_commit_info.ini`` - that might well look like
338 337 this::
339 338
340 339 # This is an ini file that may contain information about the code state
341 340 [commit hash]
342 341 # The line below may contain a valid hash if it has been substituted
343 342 # during 'git archive'
344 343 archive_subst_hash=$Format:%h$
345 344 # This line may be modified by the install process
346 345 install_hash=
347 346
348 347 The .git_commit_info file above is also designed to be used with git
349 348 substitution - so you probably also want a ``.gitattributes`` file in the
350 349 root directory of your working tree that contains something like this::
351 350
352 351 myproject/.git_commit_info.ini export-subst
353 352
354 353 That will cause the ``.git_commit_info.ini`` file to get filled in by ``git
355 354 archive`` - useful in case someone makes such an archive - for example with
356 355 via the github 'download source' button.
357 356
358 357 Although all the above will work as is, you might consider having something
359 358 like a ``get_info()`` function in your package to display the commit
360 359 information at the terminal. See the ``pkg_info.py`` module in the nipy
361 360 package for an example.
362 361 """
363 362 class MyBuildPy(build_cmd):
364 363 ''' Subclass to write commit data into installation tree '''
365 364 def run(self):
366 365 build_py.run(self)
367 366 import subprocess
368 367 proc = subprocess.Popen('git rev-parse --short HEAD',
369 368 stdout=subprocess.PIPE,
370 369 stderr=subprocess.PIPE,
371 370 shell=True)
372 371 repo_commit, _ = proc.communicate()
373 372 # We write the installation commit even if it's empty
374 373 cfg_parser = ConfigParser()
375 374 cfg_parser.read(pjoin(pkg_dir, '.git_commit_info.ini'))
376 375 cfg_parser.set('commit hash', 'install_hash', repo_commit)
377 376 out_pth = pjoin(self.build_lib, pkg_dir, '.git_commit_info.ini')
378 377 out_file = open(out_pth, 'wt')
379 378 cfg_parser.write(out_file)
380 379 out_file.close()
381 380 return MyBuildPy
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now