source: publico/il.spdo/trunk/PasteScript-1.7.4.2-py2.6.egg/paste/script/create_distro.py @ 5327

Última Alteração nesse arquivo desde 5327 foi 5327, incluída por fabianosantos, 8 anos atrás

Import inicial.

File size: 16.6 KB
Linha 
1# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
2# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
3import re
4import sys
5import os
6import pkg_resources
7from command import Command, BadCommand
8import copydir
9import pluginlib
10import fnmatch
11try:
12    set
13except NameError:
14    from sets import Set as set
15
16class CreateDistroCommand(Command):
17
18    usage = 'PACKAGE_NAME [VAR=VALUE VAR2=VALUE2 ...]'
19    summary = "Create the file layout for a Python distribution"
20    short_description = summary
21
22    description = """\
23    Create a new project.  Projects are typically Python packages,
24    ready for distribution.  Projects are created from templates, and
25    represent different kinds of projects -- associated with a
26    particular framework for instance.
27    """
28
29    parser = Command.standard_parser(
30        simulate=True, no_interactive=True, quiet=True, overwrite=True)
31    parser.add_option('-t', '--template',
32                      dest='templates',
33                      metavar='TEMPLATE',
34                      action='append',
35                      help="Add a template to the create process")
36    parser.add_option('-o', '--output-dir',
37                      dest='output_dir',
38                      metavar='DIR',
39                      default='.',
40                      help="Write put the directory into DIR (default current directory)")
41    parser.add_option('--svn-repository',
42                      dest='svn_repository',
43                      metavar='REPOS',
44                      help="Create package at given repository location (this will create the standard trunk/ tags/ branches/ hierarchy)")
45    parser.add_option('--list-templates',
46                      dest='list_templates',
47                      action='store_true',
48                      help="List all templates available")
49    parser.add_option('--list-variables',
50                      dest="list_variables",
51                      action="store_true",
52                      help="List all variables expected by the given template (does not create a package)")
53    parser.add_option('--inspect-files',
54                      dest='inspect_files',
55                      action='store_true',
56                      help="Show where the files in the given (already created) directory came from (useful when using multiple templates)")
57    parser.add_option('--config',
58                      action='store',
59                      dest='config',
60                      help="Template variables file")
61
62    _bad_chars_re = re.compile('[^a-zA-Z0-9_]')
63
64    default_verbosity = 1
65    default_interactive = 1
66
67    def command(self):
68        if self.options.list_templates:
69            return self.list_templates()
70        asked_tmpls = self.options.templates or ['basic_package']
71        templates = []
72        for tmpl_name in asked_tmpls:
73            self.extend_templates(templates, tmpl_name)
74        if self.options.list_variables:
75            return self.list_variables(templates)
76        if self.verbose:
77            print 'Selected and implied templates:'
78            max_tmpl_name = max([len(tmpl_name) for tmpl_name, tmpl in templates])
79            for tmpl_name, tmpl in templates:
80                print '  %s%s  %s' % (
81                    tmpl_name, ' '*(max_tmpl_name-len(tmpl_name)),
82                    tmpl.summary)
83            print
84        if not self.args:
85            if self.interactive:
86                dist_name = self.challenge('Enter project name')
87            else:
88                raise BadCommand('You must provide a PACKAGE_NAME')
89        else:
90            dist_name = self.args[0].lstrip(os.path.sep)
91
92        templates = [tmpl for name, tmpl in templates]
93        output_dir = os.path.join(self.options.output_dir, dist_name)
94       
95        pkg_name = self._bad_chars_re.sub('', dist_name.lower())
96        vars = {'project': dist_name,
97                'package': pkg_name,
98                'egg': pluginlib.egg_name(dist_name),
99                }
100        vars.update(self.parse_vars(self.args[1:]))
101        if self.options.config and os.path.exists(self.options.config):
102            for key, value in self.read_vars(self.options.config).items():
103                vars.setdefault(key, value)
104       
105        if self.verbose: # @@: > 1?
106            self.display_vars(vars)
107
108        if self.options.inspect_files:
109            self.inspect_files(
110                output_dir, templates, vars)
111            return
112        if not os.path.exists(output_dir):
113            # We want to avoid asking questions in copydir if the path
114            # doesn't exist yet
115            copydir.all_answer = 'y'
116       
117        if self.options.svn_repository:
118            self.setup_svn_repository(output_dir, dist_name)
119
120        # First we want to make sure all the templates get a chance to
121        # set their variables, all at once, with the most specialized
122        # template going first (the last template is the most
123        # specialized)...
124        for template in templates[::-1]:
125            vars = template.check_vars(vars, self)
126
127        # Gather all the templates egg_plugins into one var
128        egg_plugins = set()
129        for template in templates:
130            egg_plugins.update(template.egg_plugins)
131        egg_plugins = list(egg_plugins)
132        egg_plugins.sort()
133        vars['egg_plugins'] = egg_plugins
134           
135        for template in templates:
136            self.create_template(
137                template, output_dir, vars)
138
139        found_setup_py = False
140        paster_plugins_mtime = None
141        if os.path.exists(os.path.join(output_dir, 'setup.py')):
142            # Grab paster_plugins.txt's mtime; used to determine if the
143            # egg_info command wrote to it
144            try:
145                egg_info_dir = pluginlib.egg_info_dir(output_dir, dist_name)
146            except IOError:
147                egg_info_dir = None
148            if egg_info_dir is not None:
149                plugins_path = os.path.join(egg_info_dir, 'paster_plugins.txt')
150                if os.path.exists(plugins_path):
151                    paster_plugins_mtime = os.path.getmtime(plugins_path)
152
153            self.run_command(sys.executable, 'setup.py', 'egg_info',
154                             cwd=output_dir,
155                             # This shouldn't be necessary, but a bug in setuptools 0.6c3 is causing a (not entirely fatal) problem that I don't want to fix right now:
156                             expect_returncode=True)
157            found_setup_py = True
158        elif self.verbose > 1:
159            print 'No setup.py (cannot run egg_info)'
160
161        package_dir = vars.get('package_dir', None)
162        if package_dir:
163            output_dir = os.path.join(output_dir, package_dir)
164
165        # With no setup.py this doesn't make sense:
166        if found_setup_py:
167            # Only write paster_plugins.txt if it wasn't written by
168            # egg_info (the correct way). leaving us to do it is
169            # deprecated and you'll get warned
170            egg_info_dir = pluginlib.egg_info_dir(output_dir, dist_name)
171            plugins_path = os.path.join(egg_info_dir, 'paster_plugins.txt')
172            if len(egg_plugins) and (not os.path.exists(plugins_path) or \
173                    os.path.getmtime(plugins_path) == paster_plugins_mtime):
174                if self.verbose:
175                    print >> sys.stderr, \
176                        ('Manually creating paster_plugins.txt (deprecated! '
177                         'pass a paster_plugins keyword to setup() instead)')
178                for plugin in egg_plugins:
179                    if self.verbose:
180                        print 'Adding %s to paster_plugins.txt' % plugin
181                    if not self.simulate:
182                        pluginlib.add_plugin(egg_info_dir, plugin)
183       
184        if self.options.svn_repository:
185            self.add_svn_repository(vars, output_dir)
186
187        if self.options.config:
188            write_vars = vars.copy()
189            del write_vars['project']
190            del write_vars['package']
191            self.write_vars(self.options.config, write_vars)
192       
193    def create_template(self, template, output_dir, vars):
194        if self.verbose:
195            print 'Creating template %s' % template.name
196        template.run(self, output_dir, vars)
197
198    def setup_svn_repository(self, output_dir, dist_name):
199        # @@: Use subprocess
200        svn_repos = self.options.svn_repository
201        svn_repos_path = os.path.join(svn_repos, dist_name).replace('\\','/')
202        svn_command = 'svn'
203        if sys.platform == 'win32':
204            svn_command += '.exe'
205        # @@: The previous method of formatting this string using \ doesn't work on Windows
206        cmd = '%(svn_command)s mkdir %(svn_repos_path)s' + \
207            ' %(svn_repos_path)s/trunk %(svn_repos_path)s/tags' + \
208            ' %(svn_repos_path)s/branches -m "New project %(dist_name)s"'
209        cmd = cmd % {
210            'svn_repos_path': svn_repos_path,
211            'dist_name': dist_name,
212            'svn_command':svn_command,
213        }
214        if self.verbose:
215            print "Running:"
216            print cmd
217        if not self.simulate:
218            os.system(cmd)
219        svn_repos_path_trunk = os.path.join(svn_repos_path,'trunk').replace('\\','/')
220        cmd = svn_command+' co "%s" "%s"' % (svn_repos_path_trunk, output_dir)
221        if self.verbose:
222            print "Running %s" % cmd
223        if not self.simulate:
224            os.system(cmd)
225
226    ignore_egg_info_files = [
227        'top_level.txt',
228        'entry_points.txt',
229        'requires.txt',
230        'PKG-INFO',
231        'namespace_packages.txt',
232        'SOURCES.txt',
233        'dependency_links.txt',
234        'not-zip-safe']
235
236    def add_svn_repository(self, vars, output_dir):
237        svn_repos = self.options.svn_repository
238        egg_info_dir = pluginlib.egg_info_dir(output_dir, vars['project'])
239        svn_command = 'svn'
240        if sys.platform == 'win32':
241            svn_command += '.exe'
242        self.run_command(svn_command, 'add', '-N', egg_info_dir)
243        paster_plugins_file = os.path.join(
244            egg_info_dir, 'paster_plugins.txt')
245        if os.path.exists(paster_plugins_file):
246            self.run_command(svn_command, 'add', paster_plugins_file)
247        self.run_command(svn_command, 'ps', 'svn:ignore',
248                         '\n'.join(self.ignore_egg_info_files),
249                         egg_info_dir)
250        if self.verbose:
251            print ("You must next run 'svn commit' to commit the "
252                   "files to repository")
253
254    def extend_templates(self, templates, tmpl_name):
255        if '#' in tmpl_name:
256            dist_name, tmpl_name = tmpl_name.split('#', 1)
257        else:
258            dist_name, tmpl_name = None, tmpl_name
259        if dist_name is None:
260            for entry in self.all_entry_points():
261                if entry.name == tmpl_name:
262                    tmpl = entry.load()(entry.name)
263                    dist_name = entry.dist.project_name
264                    break
265            else:
266                raise LookupError(
267                    'Template by name %r not found' % tmpl_name)
268        else:
269            dist = pkg_resources.get_distribution(dist_name)
270            entry = dist.get_entry_info(
271                'paste.paster_create_template', tmpl_name)
272            tmpl = entry.load()(entry.name)
273        full_name = '%s#%s' % (dist_name, tmpl_name)
274        for item_full_name, item_tmpl in templates:
275            if item_full_name == full_name:
276                # Already loaded
277                return
278        for req_name in tmpl.required_templates:
279            self.extend_templates(templates, req_name)
280        templates.append((full_name, tmpl))
281       
282    def all_entry_points(self):
283        if not hasattr(self, '_entry_points'):
284            self._entry_points = list(pkg_resources.iter_entry_points(
285            'paste.paster_create_template'))
286        return self._entry_points
287
288    def display_vars(self, vars):
289        vars = vars.items()
290        vars.sort()
291        print 'Variables:'
292        max_var = max([len(n) for n, v in vars])
293        for name, value in vars:
294            print '  %s:%s  %s' % (
295                name, ' '*(max_var-len(name)), value)
296       
297    def list_templates(self):
298        templates = []
299        for entry in self.all_entry_points():
300            try:
301                templates.append(entry.load()(entry.name))
302            except Exception, e:
303                # We will not be stopped!
304                print 'Warning: could not load entry point %s (%s: %s)' % (
305                    entry.name, e.__class__.__name__, e)
306        max_name = max([len(t.name) for t in templates])
307        templates.sort(lambda a, b: cmp(a.name, b.name))
308        print 'Available templates:'
309        for template in templates:
310            # @@: Wrap description
311            print '  %s:%s  %s' % (
312                template.name,
313                ' '*(max_name-len(template.name)),
314                template.summary)
315       
316    def inspect_files(self, output_dir, templates, vars):
317        file_sources = {}
318        for template in templates:
319            self._find_files(template, vars, file_sources)
320        self._show_files(output_dir, file_sources)
321        self._show_leftovers(output_dir, file_sources)
322
323    def _find_files(self, template, vars, file_sources):
324        tmpl_dir = template.template_dir()
325        self._find_template_files(
326            template, tmpl_dir, vars, file_sources)
327
328    def _find_template_files(self, template, tmpl_dir, vars,
329                             file_sources, join=''):
330        full_dir = os.path.join(tmpl_dir, join)
331        for name in os.listdir(full_dir):
332            if name.startswith('.'):
333                continue
334            if os.path.isdir(os.path.join(full_dir, name)):
335                self._find_template_files(
336                    template, tmpl_dir, vars, file_sources,
337                    join=os.path.join(join, name))
338                continue
339            partial = os.path.join(join, name)
340            for name, value in vars.items():
341                partial = partial.replace('+%s+' % name, value)
342            if partial.endswith('_tmpl'):
343                partial = partial[:-5]
344            file_sources.setdefault(partial, []).append(template)
345
346    _ignore_filenames = ['.*', '*.pyc', '*.bak*']
347    _ignore_dirs = ['CVS', '_darcs', '.svn']
348
349    def _show_files(self, output_dir, file_sources, join='', indent=0):
350        pad = ' '*(2*indent)
351        full_dir = os.path.join(output_dir, join)
352        names = os.listdir(full_dir)
353        dirs = [n for n in names
354                if os.path.isdir(os.path.join(full_dir, n))]
355        fns = [n for n in names
356               if not os.path.isdir(os.path.join(full_dir, n))]
357        dirs.sort()
358        names.sort()
359        for name in names:
360            skip_this = False
361            for ext in self._ignore_filenames:
362                if fnmatch.fnmatch(name, ext):
363                    if self.verbose > 1:
364                        print '%sIgnoring %s' % (pad, name)
365                    skip_this = True
366                    break
367            if skip_this:
368                continue
369            partial = os.path.join(join, name)
370            if partial not in file_sources:
371                if self.verbose > 1:
372                    print '%s%s (not from template)' % (pad, name)
373                continue
374            templates = file_sources.pop(partial)
375            print '%s%s from:' % (pad, name)
376            for template in templates:
377                print '%s  %s' % (pad, template.name)
378        for dir in dirs:
379            if dir in self._ignore_dirs:
380                continue
381            print '%sRecursing into %s/' % (pad, dir)
382            self._show_files(
383                output_dir, file_sources,
384                join=os.path.join(join, dir),
385                indent=indent+1)
386
387    def _show_leftovers(self, output_dir, file_sources):
388        if not file_sources:
389            return
390        print
391        print 'These files were supposed to be generated by templates'
392        print 'but were not found:'
393        file_sources = file_sources.items()
394        file_sources.sort()
395        for partial, templates in file_sources:
396            print '  %s from:' % partial
397            for template in templates:
398                print '    %s' % template.name
399
400    def list_variables(self, templates):
401        for tmpl_name, tmpl in templates:
402            if not tmpl.read_vars():
403                if self.verbose > 1:
404                    self._show_template_vars(
405                        tmpl_name, tmpl, 'No variables found')
406                continue
407            self._show_template_vars(tmpl_name, tmpl)
408
409    def _show_template_vars(self, tmpl_name, tmpl, message=None):
410        title = '%s (from %s)' % (tmpl.name, tmpl_name)
411        print title
412        print '-'*len(title)
413        if message is not None:
414            print '  %s' % message
415            print
416            return
417        tmpl.print_vars(indent=2)
Note: Veja TracBrowser para ajuda no uso do navegador do trac.
 

The contents and data of this website are published under license:
Creative Commons 4.0 Brasil - Atribuir Fonte - Compartilhar Igual.