root/lang/python/tasktools/trunk/tasktools.py @ 6908

Revision 6908, 3.6 kB (checked in by yuin, 5 years ago)

/lang/python/tasktools/trunk/tasktools.py: change an api interface

Line 
1#vim: fileencoding=utf8
2""" tasktools
3
4``tasktools`` is a collection of enhancement to Python ``distutils(setuptools)``
5that allow you to more easily create extra commands.
6
7"""
8from __future__ import with_statement
9import re, sys, imp, os
10from os.path import join, abspath, dirname
11from contextlib import contextmanager
12try:
13  from setuptools import setup
14  def _clear_commands():
15    from pkg_resources import working_set as ws
16    setattr(ws.by_key["setuptools"], "_ep_map", {})
17except ImportError,e:
18  from distutils.core import setup
19  def _clear_commands(): pass
20from distutils.core import Command
21import distutils.dist
22from distutils.dist import Distribution
23import distutils.command
24
25__version__ = "1.0.0"
26__author__  = "Yusuke Inuzuka"
27
28class _Odict(dict): keys = lambda self: sorted(dict.keys(self))
29_va = dict(global_description=None, cmd_args={}, nssep="_", load_path=[])
30_cmds = _Odict()
31_namespace = []
32
33_get_ns = lambda:_namespace and _va["nssep"].join(_namespace)+_va["nssep"] or ""
34def global_description(desc): _va["global_description"] = desc
35def cmd_args(**v): _va["cmd_args"] = v
36def load_path(*path): _va["load_path"] = _va["load_path"] + list(path)
37def use_without_standard():
38  if not use_without_standard.initialized:
39    _va["nssep"] = ":"
40    _clear_commands()
41    distutils.dist.command_re = re.compile("[a-zA-Z0-9_:]+")
42    Distribution.common_usage = ""
43    def new_print_command_list (self, commands, header, max_length):
44      if header == "Standard commands": return
45      if "extra" in header.lower() : header = "Commands"
46      return self.old_print_command_list(commands, header, max_length)
47    setattr(Distribution, "old_print_command_list", getattr(Distribution, "print_command_list"))
48    setattr(Distribution, "print_command_list", new_print_command_list)
49    use_without_standard.initialized = True
50use_without_standard.initialized = False
51
52
53def run():
54  if _va["load_path"]:
55    def tasks(path):
56      result = []
57      for root, dirs, files in os.walk(path):
58        map(result.append, (join(root, i) for i in files if i == "tasks.py"))
59      return result
60
61    idf = "tasktools_dynamic_task%d"
62    for pa in _va["load_path"]:
63      for i, path in enumerate((abspath(i) for i in tasks(pa))):
64        imp.load_source(idf%i, path)
65
66  if use_without_standard.initialized and _va["global_description"]:
67    _arg = sys.argv[1] if len(sys.argv) > 1 else ""
68    if _arg in ["--help-commands", "--help", "-h"] and _va["global_description"]:
69      print "\n".join([u"#"*60, _va["global_description"], u"#"*60])
70  _va["cmd_args"].update({"cmdclass":_cmds})
71  setup(**_va["cmd_args"])
72
73class _CommandType(type):
74  def __new__(cls, class_name, class_bases, classdict):
75    d = dict(user_options=[], finalize_options=lambda s:None)
76    d.update(classdict)
77    def _(self):
78      [setattr(self,i[0].rstrip("="),None) for i in d["user_options"]]
79    d["initialize_options"] = _
80    d["boolean_options"] = [i for i,j,k in d["user_options"] if not i.endswith("=")]
81    def _(self):
82      map(self.run_command, self.get_sub_commands())
83      return classdict["run"](self)
84    d["run"] = _
85    name = _get_ns()+class_name.lower()
86    cls = type.__new__(cls, name, class_bases + (object,), d)
87    cls.description = cls.__doc__ and cls.__doc__.strip() or ""
88    if "sub_commands" in d:
89      cls.description += "\n\tsub commands:\n"+"\n".join("\t\t"+i for i,j in d["sub_commands"])
90    if class_name != "Task" : _cmds[name] = cls
91    return cls
92class Task(Command): __metaclass__ = _CommandType
93
94@contextmanager
95def namespace(name):
96  _namespace.append(name)
97  yield _get_ns()
98  _namespace.pop()
99
100__all__ = filter(lambda i: not i.startswith("_"), locals())
Note: See TracBrowser for help on using the browser.