diff options
author | Sylvain Th?nault <sylvain.thenault@logilab.fr> | 2009-08-07 10:54:45 +0200 |
---|---|---|
committer | Sylvain Th?nault <sylvain.thenault@logilab.fr> | 2009-08-07 10:54:45 +0200 |
commit | 29fbb301a61d85214a0de76b7308ffb7d9c9fd96 (patch) | |
tree | 4016396e39749c537439473b648eb39e5908dbb9 | |
parent | a37b556013111e0593f2600acc3dab71bff2968b (diff) | |
download | logilab-common-29fbb301a61d85214a0de76b7308ffb7d9c9fd96.tar.gz |
remove modules deprecated for a while
-rw-r--r-- | bind.py | 263 | ||||
-rwxr-xr-x | debian.intrepid/rules | 2 | ||||
-rw-r--r-- | html.py | 42 | ||||
-rw-r--r-- | logger.py | 150 | ||||
-rw-r--r-- | patricia.py | 178 | ||||
-rw-r--r-- | test/unittest_logger.py | 53 | ||||
-rw-r--r-- | twisted_distutils.py | 213 |
7 files changed, 1 insertions, 900 deletions
diff --git a/bind.py b/bind.py deleted file mode 100644 index 2838972..0000000 --- a/bind.py +++ /dev/null @@ -1,263 +0,0 @@ -"""Optimize globals in certain functions by binding their names to values -provided in a dictionnary. - -:copyright: 2002-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr -:license: General Public License version 2 - http://www.gnu.org/licenses -""" -__docformat__ = "restructuredtext en" - -from warnings import warn -warn('logilab.common.bind module is deprecated and will disappear in a near release', - DeprecationWarning, stacklevel=2) - -# TODO: unit tests -# * this module provide a function bind(func,vars) which replaces every -# global variable 'm' by the value vars['m'] if such value exists in dict - -from dis import HAVE_ARGUMENT -from new import code as make_code, function as make_function -import inspect - -LOAD_GLOBAL = 116 -LOAD_CONST = 100 -EXTENDED_ARG = 143 -STORE_GLOBAL = 97 - -def bind_code(co, globals): - """ - Take a code object and a dictionnary and returns a new code object where - the opcodes LOAD_GLOBAL are replaced by LOAD_CONST whenever the global's - name appear in the dictionnary - """ - consts = list(co.co_consts) - assigned = {} - - code = co.co_code - new_code = "" - n = len(code) - i = 0 - while i < n: - c = code[i] - op = ord(c) - i += 1 - if op >= HAVE_ARGUMENT: - oparg = ord(code[i]) + ord(code[i+1]) * 256 - i += 2 - else: - oparg = None - if op == LOAD_GLOBAL: - name = co.co_names[oparg] - if name in globals: - k = assigned.get(name, None) - if k == None: - k = len(consts) - assigned[name] = len(consts) - consts.append(globals[name]) - op = LOAD_CONST - oparg = k - new_code += chr(op) - if oparg is not None: - new_code += chr(oparg & 255) - new_code += chr( (oparg>>8) & 255 ) - - return make_code(co.co_argcount, - co.co_nlocals, - co.co_stacksize, - co.co_flags, - new_code, - tuple(consts), - co.co_names, - co.co_varnames, - co.co_filename, - co.co_name, - co.co_firstlineno, - co.co_lnotab ) - - -def bind(f, globals): - """Returns a new function whose code object has been - bound by bind_code()""" - newcode = bind_code(f.func_code, globals) - defaults = f.func_defaults or () - return make_function(newcode, f.func_globals, f.func_name, defaults) - -if type(__builtins__) == dict: - builtins = __builtins__ -else: - builtins = __builtins__.__dict__ - -bind_code_opt = bind(bind_code, builtins ) -bind_code_opt = bind(bind_code_opt, globals() ) - - -def optimize_module(m, global_consts): - if not inspect.ismodule(m): - raise TypeError - d = {} - for i in global_consts: - v = m.__dict__.get(i) - d[i] = v - builtins = m.__builtins__ - for name, f in m.__dict__.items(): - if inspect.isfunction(f): - f = bind(f, builtins) - if d: - f = bind(f, d) - m.__dict__[name] = f - - - - -def analyze_code(co, globals, consts_dict, consts_list): - """Take a code object and a dictionnary and returns a - new code object where the opcodes LOAD_GLOBAL are replaced - by LOAD_CONST whenever the global's name appear in the - dictionnary""" - modified_globals = [] - for c in co.co_consts: - if c not in consts_list: - consts_list.append(c) - modified = [] - code = co.co_code - new_code = "" - n = len(code) - i = 0 - extended_arg = 0 - while i < n: - c = code[i] - op = ord(c) - i += 1 - if op >= HAVE_ARGUMENT: - oparg = ord(code[i]) + ord(code[i+1])*256 + extended_arg - extended_arg = 0 - i += 2 - else: - oparg = None - if op == EXTENDED_ARG: - extended_arg = oparg*65536L - - if op == LOAD_GLOBAL: - name = co.co_names[oparg] - if name in globals: - k = consts_dict.get(name, None) - if k == None: - k = len(consts_list) - consts_dict[name] = k - consts_list.append(globals[name]) - if op == STORE_GLOBAL: - name = co.co_names[oparg] - if name in globals: - modified_globals.append(name) - return modified_globals - -def rewrite_code(co, consts_dict, consts_tuple): - """Take a code object and a dictionnary and returns a - new code object where the opcodes LOAD_GLOBAL are replaced - by LOAD_CONST whenever the global's name appear in the - dictionnary""" - code = co.co_code - new_code = "" - n = len(code) - i = 0 - consts_list = list(consts_tuple) - while i < n: - c = code[i] - op = ord(c) - i += 1 - extended_arg = 0 - if op >= HAVE_ARGUMENT: - oparg = ord(code[i]) + ord(code[i+1])*256+extended_arg - extended_arg = 0 - i += 2 - else: - oparg = None - if op == EXTENDED_ARG: - extended_arg = oparg*65536L - elif op == LOAD_GLOBAL: - name = co.co_names[oparg] - k = consts_dict.get(name) - if k is not None: - op = LOAD_CONST - oparg = k - elif op == LOAD_CONST: - val = co.co_consts[oparg] - oparg = consts_list.index(val) - new_code += chr(op) - if oparg is not None: - new_code += chr(oparg & 255) - new_code += chr( (oparg>>8) & 255 ) - - return make_code(co.co_argcount, - co.co_nlocals, - co.co_stacksize, - co.co_flags, - new_code, - consts_tuple, - co.co_names, - co.co_varnames, - co.co_filename, - co.co_name, - co.co_firstlineno, - co.co_lnotab ) - -def optimize_module_2(m, globals_consts, bind_builtins=1): - if not inspect.ismodule(m): - raise TypeError - consts_dict = {} - consts_list = [] - if type(globals_consts) == list or type(globals_consts) == tuple: - globals = {} - for i in globals_consts: - v = m.__dict__.get(i) - globals[i] = v - else: - globals = globals_consts - if bind_builtins: - for builtin_name, builtin_value in m.__builtins__.items(): - # this way it is possible to redefine a builtin in globals_consts - globals.setdefault(builtin_name, builtin_value) - functions = {} - for name, f in m.__dict__.items(): - if inspect.isfunction(f): - functions[name] = f - analyze_code(f.func_code, globals, consts_dict, consts_list) - consts_list = tuple(consts_list) - for name, f in functions.items(): - newcode = rewrite_code(f.func_code, consts_dict, consts_list) - defaults = f.func_defaults or () - m.__dict__[name] = make_function(newcode, f.func_globals, f.func_name, - defaults) - - -def run_bench(n): - from time import time - t = time() - g = globals() - for i in range(n): - test = bind(bind_code, g) - t1 = time()-t - bind2 = bind(bind, {'bind_code':bind_code_opt}) - t = time() - for i in range(n): - test=bind2(bind_code, g) - t2 = time()-t - print "1 regular version", t1 - print "2 optimized version", t2 - print "ratio (1-2)/1 : %f %%" % (100.*(t1-t2)/t1) - - -def test_pystone(): - from test import pystone - for _ in range(5): - pystone.main() - optimize_module(pystone, ('TRUE','FALSE','Proc0','Proc1','Proc2','Proc3', - 'Proc4','Proc5','Proc6','Proc7','Proc8','Func1', - ' Func2','Func3')) - optimize_module(pystone, builtins.keys()) - for _ in range(5): - pystone.main() - - -if __name__ == "__main__": - run_bench(1000) diff --git a/debian.intrepid/rules b/debian.intrepid/rules index 937f9df..80739ef 100755 --- a/debian.intrepid/rules +++ b/debian.intrepid/rules @@ -23,7 +23,7 @@ ifeq (,$(findstring nocheck,$(DEB_BUILD_OPTIONS))) # we need this hack because we have to import "logilab.common.pytest" # but since it's a namespace package, we need to "simulate" it touch $(CURDIR)/build/lib/logilab/__init__.py - -PYTHONPATH=$(CURDIR)/build/lib/ $(CURDIR)/build/scripts-2.5/pytest + PYTHONPATH=$(CURDIR)/build/lib/ $(CURDIR)/build/scripts-2.5/pytest rm -f $(CURDIR)/build/lib/logilab/__init__.py endif diff --git a/html.py b/html.py deleted file mode 100644 index 8097ec0..0000000 --- a/html.py +++ /dev/null @@ -1,42 +0,0 @@ -"""Print traceback in HTML. - -:copyright: 2000-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr -:license: General Public License version 2 - http://www.gnu.org/licenses -""" -__docformat__ = "restructuredtext en" - -from warnings import warn -warn('html module is deprecated and will disappear in a near release', - DeprecationWarning, stacklevel=2) - -import traceback -from xml.sax.saxutils import escape - -# mk html traceback error ##################################################### - -def html_traceback(info, exception, - title='', encoding='ISO-8859-1', body=''): - """Return an html formatted traceback from python exception infos. - """ - #typ, value, tbck = info - stacktb = traceback.extract_tb(info[2]) #tbck) - strings = [] - if body: - strings.append('<div class="error_body">') - strings.append(body) - strings.append('</div>') - if title: - strings.append('<h1 class="error">%s</h1>'% escape(title)) - strings.append('<p class="error">%s</p>' % escape(str(exception))) - strings.append('<div class="error_traceback">') - for stackentry in stacktb : - strings.append('<b>File</b> <b class="file">%s</b>, <b>line</b> ' - '<b class="line">%s</b>, <b>function</b> ' - '<b class="function">%s</b>:<br/>'%( - escape(stackentry[0]), stackentry[1], stackentry[2])) - if stackentry[3]: - string = escape(repr(stackentry[3])[1:-1])#.encode(encoding) - strings.append(' %s<br/>\n' % string) - strings.append('</div>') - return '\n'.join(strings) diff --git a/logger.py b/logger.py deleted file mode 100644 index 2af5963..0000000 --- a/logger.py +++ /dev/null @@ -1,150 +0,0 @@ -"""Define a logger interface and two concrete loggers: one which prints -everything on stdout, the other using syslog. - -:copyright: 2000-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr -:license: General Public License version 2 - http://www.gnu.org/licenses - -# FIXME use logging from stdlib instead. -""" -__docformat__ = "restructuredtext en" - -from warnings import warn -warn('logilab.common.logger module is deprecated and will disappear in a future release. \ -use logging module instead.', - DeprecationWarning, stacklevel=2) - -import sys -import traceback -import time - - -LOG_EMERG = 0 -LOG_ALERT = 1 -LOG_CRIT = 2 -LOG_ERR = 3 -LOG_WARN = 4 -LOG_NOTICE = 5 -LOG_INFO = 6 -LOG_DEBUG = 7 - -INDICATORS = ['emergency', 'alert', 'critical', 'error', - 'warning', 'notice', 'info', 'debug'] - - -def make_logger(method='print', threshold=LOG_DEBUG, sid=None, output=None): - """return a logger for the given method - - known methods are 'print', 'eprint' and syslog' - """ - if method == 'print': - if output is None: - output = sys.stdout - return PrintLogger(threshold, output, sid=sid) - elif method == 'eprint': - return PrintLogger(threshold, sys.stderr, sid=sid) - elif method == 'syslog': - return SysLogger(threshold, sid) - elif method == 'file': - if not output: - raise ValueError('No logfile specified') - else: - logfile = open(output, 'a') - return PrintLogger(threshold, logfile, sid=sid) - else: - raise ValueError('Unknown logger method: %r' % method) - - -class AbstractLogger: - """logger interface. - Priorities allow to filter on the importance of events - An event gets logged if it's priority is lower than the threshold""" - - def __init__(self, threshold=LOG_DEBUG, priority_indicator=1): - self.threshold = threshold - self.priority_indicator = priority_indicator - - def log(self, priority=LOG_DEBUG, message='', substs=None): - """log a message with priority <priority> - substs are optional substrings - """ - #print 'LOG', self, priority, self.threshold, message - if priority <= self.threshold : - if substs is not None: - message = message % substs - if self.priority_indicator: - message = '[%s] %s' % (INDICATORS[priority], message) - self._writelog(priority, message) - - def _writelog(self, priority, message): - """Override this method in concrete class """ - raise NotImplementedError() - - def log_traceback(self, priority=LOG_ERR, tb_info=None): - """log traceback information with priority <priority> - """ - assert tb_info is not None - e_type, value, tbck = tb_info - stacktb = traceback.extract_tb(tbck) - l = ['Traceback (most recent call last):'] - for stackentry in stacktb : - if stackentry[3]: - plus = '\n %s' % stackentry[3] - else: - plus = '' - l.append('filename="%s" line_number="%s" function_name="%s"%s' % - (stackentry[0], stackentry[1], stackentry[2], plus)) - try: - l.append(str(e_type) + ': ' + value.__str__()) - except UnicodeError: - l.append(str(e_type) + ' (message can\'t be displayed)') - - self.log(priority, '\n'.join(l)) - - -class PrintLogger(AbstractLogger): - """logger implementation - - log everything to a file, using the standard output by default - """ - - def __init__(self, threshold, output=sys.stdout, sid=None, - encoding='UTF-8'): - AbstractLogger.__init__(self, threshold) - self.output = output - self.sid = sid - self.encoding = encoding - - def _writelog(self, priority, message): - """overridden from AbstractLogger""" - if isinstance(message, unicode): - message = message.encode(self.encoding, 'replace') - if self.sid is not None: - self.output.write('[%s] [%s] %s\n' % (time.asctime(), self.sid, - message)) - else: - self.output.write('[%s] %s\n' % (time.asctime(), message)) - self.output.flush() - -class SysLogger(AbstractLogger): - """ logger implementation - - log everything to syslog daemon - use the LOCAL_7 facility - """ - - def __init__(self, threshold, sid=None, encoding='UTF-8'): - import syslog - AbstractLogger.__init__(self, threshold) - if sid is None: - sid = 'syslog' - self.encoding = encoding - syslog.openlog(sid, syslog.LOG_PID) - - def _writelog(self, priority, message): - """overridden from AbstractLogger""" - import syslog - if isinstance(message, unicode): - message = message.encode(self.encoding, 'replace') - syslog.syslog(priority | syslog.LOG_LOCAL7, message) - diff --git a/patricia.py b/patricia.py deleted file mode 100644 index 65805f9..0000000 --- a/patricia.py +++ /dev/null @@ -1,178 +0,0 @@ -"""A Python implementation of PATRICIA tree. - -PATRICIA - Practical Algorithm to Retrieve Information Coded in Alphanumeric - D.R.Morrison (1968). -See http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Tree/PATRICIA.html if you -want to know what's a PATRICIA tree... - -TODO: _ advanced search - _ profile code - _ use mxTextTools ? - -:copyright: 2000-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr -:license: General Public License version 2 - http://www.gnu.org/licenses -""" -__docformat__ = "restructuredtext en" - -from warnings import warn -warn('logilab.common.patricia module is deprecated and will disappear in a near release', - DeprecationWarning, stacklevel=2) - -def prefix(prfx, string): - """return the index of the first character from string which differs from - prefix - """ - i = 0 - while i < len(prfx): - if i == len(string) or prfx[i] != string[i]: - break - i += 1 - return i - -def split(index, string): - """split a string on index, returning a 3-uple : - (string before index, character at index, string after index) - """ - return string[:index], string[index], string[index+1:] - - -class PatriciaNode: - """a PATRICIA trie node - """ - - def __init__(self, value='', leaf=0, data=None): - self.value = value - self.edges = {} - if leaf: - self.datas = [data] - else: - self.datas = [] - - def insert(self, string, data): - """ insert the string in the trie and associate data to it - if the string exists is the trie, data is added to the existing datas - """ - # are we arrived ? - if self.value == string: - self.datas.append(data) - # not yet ! - else: - # check we don't break compression (value don't match) - ind = prefix(self.value, string) - if ind < len(self.value): - # split this node - pfx, e, self.value = split(ind, self.value) - if ind < len(string): - n = PatriciaNode(pfx) - n.edges[string[ind]] = PatriciaNode(string[ind+1:], 1, data) - else: - n = PatriciaNode(pfx, 1, data) - n.edges[e] = self - return n - n_pfx, n_e, n_sfx = split(len(self.value), string) - if n_e in self.edges: - self.edges[n_e] = self.edges[n_e].insert(n_sfx, data) - else: - self.edges[n_e] = PatriciaNode(n_sfx, 1, data) - return self - - def remove(self, string): - """ return datas associated with string and remove string from the trie - raise KeyError if the key isn't found - FIXME: we should change the trie structure - """ - if string == self.value and self.datas: - datas = self.datas - self.datas = [] - return datas - else: - pfx, e, sfx = split(len(self.value), string) - if self.value == pfx: - return self.edges[e].remove(sfx) - raise KeyError(string) - - def lookup(self, string): - """ return datas associated with string - raise KeyError if the key isn't found - """ - if string == self.value: - if self.datas: - return self.datas - raise KeyError(string) - else: # len(self.value) < len(string): - pfx, e, sfx = split(len(self.value), string) - if self.value == pfx: - return self.edges[e].lookup(sfx) - raise KeyError(string) - - def pfx_search(self, pfx, depth=-1): - """ return all string with prefix pfx """ - sfxs = [] - if pfx and self.value[:len(pfx)] != pfx: - pfx, e, sfx = split(len(self.value), pfx) - if self.value == pfx and e in self.edges: - sfxs = ['%s%s%s' % (self.value, e, sfx) - for sfx in self.edges[e].pfx_search(sfx, depth)] - else: - if depth != 0: - for e, child in self.edges.items(): - search = child.pfx_search('', depth-1-len(self.value)) - sfxs += ['%s%s%s' % (self.value, e, sfx) - for sfx in search] - if (depth < 0 or len(self.value) <= depth): - if self.datas: - sfxs.append(self.value) - return sfxs - - def __str__(self, indent=''): - node_str = ''.join([' %s%s:\n%s' % (indent, key, - a.__str__(' %s' % indent)) - for key, a in self.edges.items()]) - return '%s%s, %s\n%s' % (indent, self.value, self.datas, node_str) - - def __repr__(self): - return '<PatriciaNode id=%s value=%s childs=%s datas=%s>' % ( - id(self), self.value, self.edges.keys(), self.datas) - - -class PatriciaTrie: - """ wrapper class for a patricia tree - delegates to the root of the tree (PatriciaNode) - """ - - def __init__(self): - self._trie = None - self.words = 0 - - def insert(self, string, data=None): - """ insert a string into the tree """ - self.words += 1 - if self._trie is None: - self._trie = PatriciaNode(string, 1, data) - else: - self._trie = self._trie.insert(string, data) - - def remove(self, string): - """ remove a string from the tree """ - if self._trie is not None: - return self._trie.remove(string) - raise KeyError(string) - - def lookup(self, string): - """ look for a string into the tree """ - if self._trie is not None: - return self._trie.lookup(string) - raise KeyError(string) - - def pfx_search(self, string, depth=-1): - """ search all words begining by <string> """ - if self._trie is not None: - return self._trie.pfx_search(string, depth) - raise KeyError(string) - - def __str__(self): - return self._trie.__str__() - - def __repr__(self): - return '<PatriciaTrie id=%s words=%s>' % (id(self), self.words) diff --git a/test/unittest_logger.py b/test/unittest_logger.py deleted file mode 100644 index 071893f..0000000 --- a/test/unittest_logger.py +++ /dev/null @@ -1,53 +0,0 @@ -"""unittests for logilab.common.logger""" - -from tempfile import mktemp -import os -import sys -from cStringIO import StringIO - -from logilab.common.testlib import TestCase, unittest_main -from logilab.common.logger import * - - -def get_logged_messages(output): - """strip timestamps and extract effective logged text - (log lines look like: [timestamp] message) - """ - return [line.split(']')[-1].strip() for line in output.splitlines()] - - -class LoggerTC(TestCase): - - def test_defaultlogging(self): - # redirect stdout so that we can test - stdout_backup = sys.stdout - sys.stdout = StringIO() - # make default logger - logger = make_logger() - logger.log(message='hello') - logger.log(message='world') - output = sys.stdout.getvalue() - msg = get_logged_messages(output) - # restore stdout - sys.stdout = stdout_backup - self.assertEquals(msg, ['hello', 'world']) - - def test_filelogging(self): - filename = mktemp(dir='/tmp') - # make file logger - logger = make_logger(method='file', output=filename) - logger.log(message='hello') - logger.log(message='world') - # make sure everything gets flushed (testing purpose) - logger.output.flush() - output = open(filename).read() #os.read(descr, 300) - # close everything correcly - #os.close(descr) - logger.output.close() - # remove file - os.remove(filename) - self.assertEquals(get_logged_messages(output), ['hello', 'world']) - -if __name__ == '__main__': - unittest_main() - diff --git a/twisted_distutils.py b/twisted_distutils.py deleted file mode 100644 index 0d8a455..0000000 --- a/twisted_distutils.py +++ /dev/null @@ -1,213 +0,0 @@ -"""Distutils extensions for twisted framework. - -This module enables the installation of plugins.tml files using standard -distutils syntax. It adds the following commands to the standard -setup.py commands: - - build_twisted_plugins: build (i.e. copy) plugins - - install_twisted_plugins: install plugins - -Additionally, the following commands have been modified to deal with -plugins files: - - sdist - - build - - install - -To use these extenstion, you should import the setup fonction from this -module, and use it normally. To list the plugins.tml files, use the -twisted_plugins keyword argument to the setup function:: - - from twisted_distutils import setup # you can also import Extension if needed - - if __name__ == '__main__': - setup(name='my_twisted_app', - version='1.0', - author='me', - packages=['my_package'], - twisted_plugins = ['my_package/plugins.tml']) - -Note that you can use this to install files that are not twisted plugins in any -package directory of your application. - -:copyright: 2000-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr -:license: General Public License version 2 - http://www.gnu.org/licenses -""" -__docformat__ = "restructuredtext en" - -# (c) 2002 Alexandre Fayolle <alexandre.fayolle@free.fr> -# This module is heavily based on code copied from the python distutils -# framework, especially distutils.command.build_script, -# distutils.command.install_script. Many thanks to the authors of these -# modules. -# This module is provided as is, I'm not responsible if anything bad -# happens to you or your python library while using this module. You may -# freely copy it, distribute it and use it in your library or to distribute -# your applications. I'd appreciate if you could drop me an email if you plan -# to do so <wink>. -# -# Happy twisting! - -from warnings import warn -warn('this module is deprecated and will disappear in a near release', - DeprecationWarning, stacklevel=1) - -from distutils.core import Distribution, Command -from distutils.command.install import install -from distutils.command.build import build -from distutils.command.sdist import sdist -from distutils.dep_util import newer -from distutils.util import convert_path -import os - -class twisted_sdist(sdist): - def add_defaults(self): - sdist.add_defaults(self) - if self.distribution.has_twisted_plugins(): - plugins = self.get_finalized_command('build_twisted_plugins') - self.filelist.extend(plugins.get_source_files()) - -class twisted_install(install): - def initialize_options (self): - install.initialize_options(self) - self.twisted_plugins = None - - def has_twisted_plugins(self): - return self.distribution.has_twisted_plugins() - - sub_commands = [] - sub_commands.extend(install.sub_commands) - sub_commands.append(('install_twisted_plugins', has_twisted_plugins)) - - -class twisted_build(build): - def initialize_options (self): - build.initialize_options(self) - self.twisted_plugins = None - - def has_twisted_plugins(self): - return self.distribution.has_twisted_plugins() - - sub_commands = [] - sub_commands.extend(build.sub_commands) - sub_commands.append(('build_twisted_plugins', has_twisted_plugins)) - -class build_twisted_plugins (Command): - - description = "\"build\" twisted plugins (copy)" - - user_options = [ - ('build-dir=', 'd', "directory to \"build\" (copy) to"), - ('force', 'f', "forcibly build everything (ignore file timestamps"), - ] - - boolean_options = ['force'] - - - def initialize_options (self): - self.build_dir = None - self.twisted_plugins = None - self.force = None - self.outfiles = None - - def get_source_files(self): - return self.twisted_plugins - - def finalize_options (self): - self.set_undefined_options('build', - ('build_lib', 'build_dir'), - ('force', 'force')) - self.twisted_plugins = self.distribution.twisted_plugins - - - def run (self): - if not self.twisted_plugins: - return - self.copy_twisted_plugins() - - - def copy_twisted_plugins (self): - """Copy each plugin listed in 'self.twisted_plugins'. - """ - self.mkpath(self.build_dir) - for plugin in self.twisted_plugins: - adjust = 0 - plugin = convert_path(plugin) - outfile = os.path.join(self.build_dir, plugin) - if not self.force and not newer(plugin, outfile): - self.announce("not copying %s (up-to-date)" % plugin) - continue - - # Always open the file, but ignore failures in dry-run mode -- - # that way, we'll get accurate feedback if we can read the - # plugin. - try: - f = open(plugin, "r") - except IOError: - if not self.dry_run: - raise - f = None - else: - f.close() - self.copy_file(plugin, outfile) - - -class install_twisted_plugins(Command): - - description = "install twisted plugins" - - user_options = [ - ('install-dir=', 'd', "directory to install scripts to"), - ('build-dir=','b', "build directory (where to install from)"), - ('force', 'f', "force installation (overwrite existing files)"), - ('skip-build', None, "skip the build steps"), - ] - - boolean_options = ['force', 'skip-build'] - - - def initialize_options (self): - self.install_dir = None - self.force = 0 - self.build_dir = None - self.skip_build = None - - def finalize_options (self): - self.set_undefined_options('build', ('build_lib', 'build_dir')) - self.set_undefined_options('install', - ('install_lib', 'install_dir'), - ('force', 'force'), - ('skip_build', 'skip_build'), - ) - - def run (self): - if not self.skip_build: - self.run_command('build_twisted_plugins') - self.outfiles = self.copy_tree(self.build_dir, self.install_dir) - - def get_inputs (self): - return self.distribution.twisted_plugins or [] - - def get_outputs(self): - return self.outfiles or [] - - - -class TwistedDistribution(Distribution): - def __init__(self,attrs=None): - self.twisted_plugins = None - Distribution.__init__(self, attrs) - self.cmdclass = {'install':twisted_install, - 'install_twisted_plugins':install_twisted_plugins, - 'build':twisted_build, - 'build_twisted_plugins':build_twisted_plugins, - 'sdist':twisted_sdist, - } - - def has_twisted_plugins(self): - return self.twisted_plugins and len(self.twisted_plugins) > 0 - - -def setup(**attrs): - from distutils import core - attrs['distclass'] = TwistedDistribution - core.setup(**attrs) |