Ejemplo n.º 1
0
 def check_pyprc(self):
     output.part_title('Checking .pypirc for egg-release targets')
     pypirc_path = os.path.expanduser('~/.pypirc')
     if not os.path.isfile(pypirc_path):
         # ~/.pypirc required
         output.error('Could not find the file %s' % pypirc_path, exit=True)
     config = ConfigParser.ConfigParser()
     config.readfp(open(pypirc_path))
     indexservers = config.get('distutils', 'index-servers').strip().split('\n')
     sections = []
     basic_namespace = scm.get_package_name('.').split('.')[0]
     for srv in indexservers:
         # test if its properly configured
         if config.has_section(srv):
             print '* found target "%s"' % output.colorize(srv,
                                                           output.WARNING)
             sections.append(srv)
     if basic_namespace in sections:
         self.pypi_target = basic_namespace
     else:
         self.pypi_target = ''
     msg = 'Please specify a pypi target for the egg relase [%s]' % \
         output.colorize(self.pypi_target, output.BOLD_WARNING)
     pypi_target_input = input.prompt(msg, lambda v:\
                                          (self.pypi_target and not v) or v in
                                      sections
                                      and True or 'Please select a target listed above')
     if pypi_target_input:
         self.pypi_target = pypi_target_input
Ejemplo n.º 2
0
    def get_maintainer_for(
        self, package, trunk=True, branch=False, tag=False, name="", force_reload=False, prompt=False, with_extra=None
    ):
        """ Returns the maintainer of a package in trunk / branch / tag.
        The maintainer is cached in the package infos. The with_extra may
        be used for caching purpose.
        """
        # validate parameters
        if (trunk and branch and tag) or (not trunk and not branch and not tag):
            raise ValueError("Excepts one and only one of trunk, branch " + "and tag to be positive")
        if branch or tag and not name:
            raise ValueError("Provide a branch/tag name")

        # get package info
        data = self.get_info(package, force_reload, prompt)
        if not data:
            # we expect that get_info already has set some infos, so this case
            # should usually not happen, but its not an error.
            return None

        subdir = self._calculate_svn_subpath(trunk=trunk, branch=branch, tag=tag, name=name, with_extra=with_extra)

        # use cached maintainer infos from package info, if existing
        if not force_reload and data.get("maintainer", None):
            if data["maintainer"].get(subdir, _marker) != _marker:
                return data["maintainer"][subdir]

        # .. if not existing, get egginfo and update
        try:
            egg = get_egginfo_for(package, trunk=trunk, branch=branch, tag=tag, name=name, extra_require=with_extra)
        except Exception, exc:
            output.error("Error while loading setup.py of %s (%s): %s" % (package, subdir, str(exc)))
            return []
Ejemplo n.º 3
0
 def __call__(self):
     output.warning('GIT repositories are not supported yet ' +\
                        '(only svn or gitsvn)')
     if len(self.args) == 0:
         output.error('package_name is required', exit=1)
     package_name = self.args[0]
     git.setup_gitsvn_cache()
     default_vcs = config.Configuration().default_vcs
     if default_vcs == 'git':
         # already checked out once?
         cache_path = os.path.join(git.get_gitsvn_cache_path(),
                                   package_name)
         if not os.path.isdir(cache_path):
             svn_url = self.get_svn_url(package_name)
             git.checkout_gitsvn(svn_url)
         else:
             # cache_path existing ; just update and clone
             runcmd('cd %s; git reset --hard' % cache_path)
             runcmd('cd %s; git svn fetch' % cache_path)
             runcmd('cd %s; git svn rebase' % cache_path)
             runcmd('cp -r %s .' % cache_path)
             runcmd('cd %s ; git checkout %s' % (
                     package_name,
                     'master',
                     ))
             git.apply_svn_ignores(package_name)
     elif default_vcs == 'svn':
         svn_url = self.get_svn_url(package_name)
         runcmd('svn co %s %s' % (
                 svn_url,
                 package_name))
Ejemplo n.º 4
0
 def check_doc(self):
     if self.options.ignore_doc_errors:
         return
     output.part_title('Checking setup.py docstring (restructuredtext)')
     cmd = '%s setup.py check --restructuredtext --strict' % sys.executable
     if runcmd_with_exitcode(cmd, log=0)!=0:
         output.error('You have errors in your docstring (README.txt, HISTORY.txt, ...)'+\
                          '\nRun "ftw checkdocs" for more details.', exit=1)
Ejemplo n.º 5
0
 def __call__(self):
     # warning
     output.warning('It\'s no longer recommended to use a installation ' +\
                        'in site-packages, since we have a implicit ' +\
                        'dependency to zope.')
     output.warning('Use the buildout instead: ' +\
                        'https://svn.4teamwork.ch/repos/buildout/ftw.manager/')
     output.error('Quitting. See help for enforcing update...')
     if not self.options.ignore_warning:
         return
     # / warning
     from pkg_resources import load_entry_point
     easy_install = load_entry_point('setuptools==0.6c9', 'console_scripts',
                                     'easy_install')
     easy_install(['-U', '-f', self.options.findLinks, 'ftw.manager'])
Ejemplo n.º 6
0
 def find_buildout_directory(self):
     path = ['.']
     while 1:
         dir = os.listdir('/'.join(path))
         if '/'==os.path.abspath('/'.join(path)):
             output.error('No buildout directory with existing bin/instance* found', exit=1)
             # die
         if '#instance' in '#'.join(dir):
             # we are in the bin folder
             path.append('..')
             return os.path.abspath('/'.join(path))
         if 'bin' in dir:
             bin_contents = os.listdir('/'.join(path+['bin']))
             if '#instance' in '#'.join(bin_contents):
                 # valid buildout directory reached
                 return os.path.abspath('/'.join(path))
         path.append('..')
Ejemplo n.º 7
0
 def __call__(self):
     scm.tested_for_scms(('svn', 'gitsvn'), '.')
     svn_url = scm.get_svn_url('.').split('/')
     svn_root_url = scm.get_package_root_url('.').split('/')
     package_name = scm.get_package_name('.')
     path = os.path.abspath(os.path.join(
             (len(svn_url) - len(svn_root_url) - 1) * '../',
             package_name.replace('.', '/'),
             'version.txt',
             ))
     if not os.path.isfile(path):
         output.error('Could not find file %s' % path, exit=1)
     version = open(path).read().strip()
     print '  Version of %s: %s' % (
         output.colorize(package_name, output.WARNING),
         output.colorize(version, output.WARNING),
         )
Ejemplo n.º 8
0
 def __call__(self):
     scm.tested_for_scms(('svn', 'gitsvn', 'git'), '.')
     scm.require_package_root_cwd()
     if len(self.args) < 1:
         output.error('Language code is required', exit=1)
     lang = self.args[0]
     # check
     self.check_conditions()
     package_name = scm.get_package_name('.')
     if self.options.domain:
         domain = self.options.domain
     else:
         domain = package_name
     # check pot file
     pot_path = os.path.join(self.locales_dir, '%s.pot' % domain)
     if not os.path.exists(pot_path):
         output.error('Could not find pot file at: %s' % pot_path, exit=1)
     # check language directory
     lang_dir = os.path.join(self.locales_dir, lang, 'LC_MESSAGES')
     if not os.path.isdir(lang_dir):
         runcmd('mkdir -p %s' % lang_dir)
     # touch po file
     po_file = os.path.join(lang_dir, '%s.po' % domain)
     if not os.path.isfile(po_file):
         runcmd('touch %s' % po_file)
     # sync
     output.part_title('Syncing language "%s"' % lang)
     cmd = '%s sync --pot %s %s' % (
         self.i18ndude,
         pot_path,
         po_file,
         )
     runcmd(cmd)
     # remove language
     output.part_title('Removing language code from po file')
     data = open(po_file).read().split('\n')
     file = open(po_file, 'w')
     for row in data:
         if not row.startswith('"Language-Code') and \
                 not row.startswith('"Language-Name'):
             file.write(row)
             file.write('\n')
     file.close()
Ejemplo n.º 9
0
def check_project_layout(directory_or_url, raise_exception=True, ask_for_creation=True):
    """
    Checks if the project has a default svn layout with the folders
    trunk, tags and branches.
    """
    if not raise_exception:
        try:
            url = get_package_root_url(directory_or_url)
        except InvalidProjectLayout:
            return False
    else:
        url = get_package_root_url(directory_or_url)
    dircontent = runcmd('svn ls %s' % url, log=False, respond=True)
    dircontent = [x.strip()[:-1] for x in dircontent]
    # check if there are the expected folders
    excpected = ('trunk', 'tags', 'branches')
    missing = []
    for dir in excpected:
        if dir not in dircontent:
            missing.append(dir)
    # ask what to do, if there are folders missing
    if len(missing)>0:
        if ask_for_creation:
            output.error('[%s] Invalid project layout, folders missing: ' %
                         get_package_name(url) + ', '.join(missing))
            if input.prompt_bool('Would you like to create the missing folders?'):
                cmd = 'svn mkdir '
                cmd += ' '.join([os.path.join(url, dir) for dir in missing])
                cmd += ' -m "created folders: %s for package %s"' % (
                        ', '.join(missing),
                        get_package_name(directory_or_url),
                )
                runcmd(cmd, log=True, respond=True)
                # need to clean caches
                flush_cache(runcmd)
                flush_cache(runcmd_with_exitcode)
                return check_project_layout(directory_or_url, raise_exception=raise_exception, ask_for_creation=False)
        if raise_exception:
            raise InvalidProjectLayout
        else:
            return False
    return True
Ejemplo n.º 10
0
 def __call__(self):
     path = ['.']
     zopeFound = False
     while not zopeFound:
         dir = os.listdir('/'.join(path))
         if '/' == os.path.abspath('/'.join(path)):
             error('File system root reached: no zope instance found ..',
                   exit=True)
         elif 'bin' in dir:
             binContents = os.listdir('/'.join(path + ['bin']))
             instances = filter(lambda x: x.startswith('instance'),
                                binContents)
             if len(instances) > 0:
                 zopeFound = True
             else:
                 path.append('..')
         else:
             path.append('..')
     p = os.path.abspath('/'.join(path + ['bin', instances[0]]))
     cmd = '%s %s' % (p, ' '.join(sys.argv[2:]))
     runcmd(cmd, log=True)
Ejemplo n.º 11
0
 def check_conditions(self):
     self.i18ndude = 'i18ndude'
     # we should be in a local repository
     try:
         package_name = scm.get_package_name('.')
         print '  using package name:', package_name
     except scm.NotAScm:
         output.error('Not in a SVN- or GIT-Checkout, unable to guess '
                      'package name', exit=1)
     # get package root
     package_root = scm.get_package_root_path('.')
     print '  using package root path:', package_root
     # check locales directory
     self.locales_dir = os.path.abspath(os.path.join(
             package_root,
             '/'.join(package_name.split('.')),
             'locales',
             ))
     print '  using locales dir:', self.locales_dir
     if not os.path.isdir(self.locales_dir):
         runcmd('mkdir -p %s' % self.locales_dir)
Ejemplo n.º 12
0
 def __call__(self):
     if len(self.args)<2:
         output.error('At least 2 arguments are required', exit=1)
     if len(self.args)>3:
         output.error('At most 3 arguments are required', exit=1)
     # extract and check arguments
     if len(self.args)==2:
         self.fromnr, self.action = self.args
         self.tonr = self.fromnr
     elif len(self.args)==3:
         self.fromnr, self.tonr, self.action = self.args
     self.fromnr = int(self.unalias(self.fromnr))
     self.tonr = int(self.unalias(self.tonr))
     if self.tonr < self.fromnr:
         output.error('FROM (%s) must be lower than TO (%s)' % (
                 str(self.fromnr),
                 str(self.tonr),
         ))
     # find instances
     instance_names = ['instance' + str(self.alias(x))
                         for x in range(self.fromnr, self.tonr+1)]
     instance_paths = []
     for name in instance_names:
         path = os.path.join(self.find_buildout_directory(), 'bin', name)
         if os.path.exists(path):
             instance_paths.append(path)
             print ' * found %s' % path
         else:
             output.warning('%s not found: skipping' % path)
     # call instances
     for i, path in enumerate(instance_paths):
         if i!=0 and self.options.delay:
             print ' * waiting for %s second' % str(self.options.delay)
             time.sleep(self.options.delay)
         runcmd('%s %s' % (path, self.action))
Ejemplo n.º 13
0
    def __call__(self):
        """Run the checks
        """
        scm.tested_for_scms(('svn', 'gitsvn', 'git'), '.')
        if not os.path.exists('setup.py'):
            raise Exception('Could not find setup.py')
        if scm.has_local_changes('.'):
            output.error('You have local changes, please commit them first.',
                         exit=True)

        self.checks = []

        all_checks = []
        # get all checks from parser
        for option in self.parser.option_list:
            # get all options with a dest= starting with check_
            if option.dest and option.dest.startswith('check_'):
                opt_value = getattr(self.options, option.dest)
                short_name = option.dest[len('check_'):]
                if opt_value:
                    self.checks.append(short_name)
                all_checks.append(short_name)

        # if there are no checks activated by parementer, activate all
        if not len(self.checks):
            self.checks = all_checks

        # run the checks
        if 'setup' in self.checks:
            self.check_setup_py()
        if 'paster' in self.checks:
            self.check_paster_stuff()
        if 'description' in self.checks:
            self.check_description()
        if 'requires' in self.checks:
            self.check_requires()
        if 'zcml' in self.checks:
            self.check_zcml()
Ejemplo n.º 14
0
 def __call__(self):
     if not os.path.isfile('setup.py'):
         output.error('File not found: %s' % os.path.abspath('setup.py'),
                      exit=1)
     cmd = '%s setup.py check --restructuredtext --strict' % sys.executable
     if self.options.show:
         self.show_description()
         return
     elif self.options.browser:
         description = '\n'.join(self.get_description())
         response = open('long_description.html', 'w+')
         publish_file(writer_name='html',
                      destination=response,
                      source=StringIO(description))
         runcmd_with_exitcode('open long_description.html')
         return
     code, response, error = runcmd_with_exitcode(cmd, log=True,
                                                  respond=True,
                                                  respond_error=True)
     if code == 0:
         print '* docs okay'
     else:
         xpr = re.compile('\(line ([\d]*)\)')
         description = self.get_description()
         error = error.strip().split('\n')
         for err in error:
             print output.colorize(err, output.ERROR)
             line = xpr.search(err)
             if line:
                 line_nr = int(line.groups()[0]) - 1
                 start_line = line_nr - self.options.offrows
                 start_line = start_line > 0 and start_line or 0
                 end_line = line_nr + self.options.offrows + 1
                 end_line = end_line < len(description) and \
                     end_line or len(description)
                 line_range = range(start_line, end_line)
                 self.show_description(line_range, higlight=line_nr)
                 print ''
Ejemplo n.º 15
0
def is_git_svn(directory):
    directory = os.path.abspath(directory)
    dir = directory.split('/')
    while len(dir)>1:
        path = '/'.join(dir)
        gitconfig = os.path.join(path, '.git', 'config')
        if os.path.isfile(gitconfig) and '[svn-remote' in open(gitconfig).read():
            # check if the remote really works. maybe we have just migrated the package
            # and do not use the svn remote any more
            foo, out, err = runcmd_with_exitcode('cd %s ; git svn info' % path,
                                                 log=False, respond=True,
                                                 respond_error=True)
            if len(err.strip()):
                output.error('Your svn remote is not working. Fix it or '
                             'remove it. (%s)' % directory,
                             exit=True)
            return True
        # if there is .svn (but no .git) it is a .svn directory and
        # do not have to continue walking up...
        if svn.is_subversion(path):
            return False
        dir.pop()
    return False
Ejemplo n.º 16
0
 def analyse(self):
     output.part_title('Checking subversion project')
     if not scm.is_scm('.'):
         # without subversion or gitsvn it doesnt work...
         output.error('Current directory is not a repository of type svn, '
         'git-svn, git.',
                      exit=True)
     # update newest remote changes
     if scm.is_git('.') or scm.is_git_svn('.'):
         git.pull_changes('.')
         git.push_committed_changes('.')
     elif scm.is_subversion('.'):
         svn.update('.')
     # remote should be there
     if scm.is_git('.') and not scm.is_git_svn('.'):
         if not git.has_remote('origin'):
             output.error('There is no remote "origin", which is needd',
             exit=True)
     # run it at repo root
     if scm.is_subversion('.') or scm.is_git_svn('.'):
         root_svn = scm.get_package_root_url('.')
         if not svn.check_project_layout(root_svn, raise_exception=False,
         ask_for_creation=False):
             # we should have the folders trunk, tags, branches in the project
             output.error('Project does not have default layout with trunk, ' +\
                              'tags and branches. At least one folder is missing.',
                          exit=True)
         if not self.options.release_egg_only:
             here_url = scm.get_svn_url('.')
             here_root = scm.get_package_root_url('.')
             is_trunk = here_url == here_root +'/trunk'
             is_branch = '/'.join(here_url.split('/')[:-1]) == here_root + '/branches'
             if not is_trunk and not is_branch:
                 # command must be run at the "trunk" folder of a package
                 output.error('Please run this command at the root of the package ' +\
                                  '(trunk/branch folder)', exit=True)
     elif scm.is_git('.'):
         if not os.path.exists('.git'):
             output.error('Please run this command at the root of the package ' +\
                              'checkout', exit=True)
     # .. other checks
     if not os.path.isfile('setup.py'):
         # setup.py is required
         output.error('Could not find the file ./setup.py', exit=True)
     if not os.path.isfile('docs/HISTORY.txt'):
         # docs/HISTORY.txt is required
         output.error('Could not find the file ./docs/HISTORY.txt', exit=True)
     if os.path.isfile('setup.cfg'):
         # setup.cfg is not necessary, it should not be used since the development
         # stuff makes bad distribution versions
         output.error('setup.cfg should not be used anymore')
         if input.prompt_bool('Should I delete setup.cfg?'):
             scm.remove_files('setup.cfg')
             scm.commit_files('Removed setup.cfg', 'setup.cfg')
     version_file = os.path.join(scm.get_package_name('.').replace('.', '/'),
                                 'version.txt')
     if not os.path.isfile(version_file):
         # version.txt is required
         output.error('Could not find the file %s' % version_file, exit=True)
     # check MANIFEST.in
     self.check_manifest()
     # check subversion state
     if scm.has_local_changes('.'):
         output.error('You have local changes, please commit them first.',
                      exit=True)
Ejemplo n.º 17
0
    def check_requires(self):
        """ Checks, if there are missing dependencies
        """
        self.notify_part('Check dependencies')
        # get current requires
        requires = self.egginfo.install_requires

        # extend it with extra requires
        if self.egginfo.extras_require:
            for ename, erequires in self.egginfo.extras_require.items():
                requires.extend(erequires)

        print ' current requirements (including extras):'
        for egg in requires:
            print '    -', egg
        print ''

        # add the requirements without extras too
        for egg in requires[:]:
            if '[' in egg:
                requires.append(egg.split('[')[0])

        self.notify_check('Its not necessary to import some default plone / zope stuff')
        failures = False
        for egg in requires:
            if egg in PACKAGE_REQUIREMENTS_INADVISABLE and egg not in TESTING_PACKAGES:
                self.notify(False, 'Maybe you should remove the requirement ' +\
                                output.colorize(egg, output.ERROR) +\
                                output.colorize('. It seems to be in a python, ' +\
                                                    'zope or plone distribution and ' +\
                                                    'those packages should not be ' +\
                                                    'set as requirement.', output.WARNING),
                            problem_level=2)
                failures = True
        if not failures:
            self.notify(True)

        self.notify_check('Check imports on python files and zcml stuff')
        propose_requires = []

        # contains ipath:file mapping of python and zcml imports
        ipath_file_mapping = {}

        # SEARCH PYTHON FILES
        # make a grep on python files
        py_grep_results = runcmd("find . -name '*.py' -exec grep -Hr 'import ' {} \;",
                                 respond=True)
        # cleanup:
        # - strip rows
        # - remove the rows with spaces (they are not realle imports)
        # - remove "as xxx"
        py_grep_results = filter(lambda row: ' ' in row,
                                 [row.strip().split(' as ')[0] for row in py_grep_results])

        for row in py_grep_results:
            file_, statement = row.split(':')
            # make a import path
            ipath = statement.replace('from ', '').replace(' import ',
                                                           '.').replace('import', '').strip()
            ipath = ipath.replace('...', '').replace('>>>', '')
            ipath_parts = ipath.split('.')

            if '#' in ipath:
                continue

            # ignore namespace imports (python internals etc)
            if len(ipath_parts) == 1:
                continue

            ipath_file_mapping[ipath] = file_

        # SEARCH ZCML FILES
        cmd = "find . -name '*.zcml' -exec grep -Hr '\(layer\|package\|for\)=' {} \;"
        zcml_grep_results = runcmd(cmd, respond=True)

        # cleanup results
        zcml_xpr = re.compile('(for|layer)="(.*?)("|$)')
        for row in zcml_grep_results:
            file_, stmt = row.split(':', 1)
            stmt = stmt.strip()
            match = zcml_xpr.search(stmt)
            if not match:
                # maybe we have a more complicated statement (e.g. multiline)
                break
            ipath = match.groups()[1].strip()

            ipath = ipath.replace('*', '').strip()

            if '#' in ipath:
                continue

            if not ipath.startswith('.'):
                ipath_file_mapping[ipath] = file_

        # for later use
        guessed_related_packages = self._get_guessed_related_packages()

        # HANDLE ALL IMPORTS
        for ipath, file_ in ipath_file_mapping.items():
            ipath_parts = ipath.split('.')
            # ignore local imports
            if ipath.startswith(scm.get_package_name('.')):
                continue

            # is it already required?
            found = False
            for egg in requires:
                if ipath.startswith(egg):
                    found = True
                    break
            if not found:
                # is it already proposed?
                for egg in propose_requires:
                    if ipath.startswith(egg):
                        found = True
                        break
            if not found:
                # is it ignored?
                for egg in PACKAGE_REQUIREMENTS_INADVISABLE + TESTING_PACKAGES:
                    if ipath.startswith(egg):
                        found = True
                        break
            if found:
                continue

            # maybe we have a module which import relatively
            module_path = os.path.join(os.path.dirname(file_),
                                       ipath_parts[0])
            if os.path.isfile(module_path + '.py') or \
                    os.path.isfile(module_path + '/__init__.py'):
                continue

            # start on level 2 and for searching egg
            guessed_egg_names = ['.'.join(ipath_parts[:i])
                                 for i, part in enumerate(ipath_parts)
                                 if i > 1]

            # does one of the eggs exist?
            found = False

            # is there package in our src directory, if we are in one?
            for egg_name in guessed_egg_names:
                if egg_name.strip() in guessed_related_packages:
                    if egg_name.strip() not in propose_requires:
                        propose_requires.append(egg_name.strip())
                    found = True
                    break

            # .. in pypi
            if not found:
                for egg_name in guessed_egg_names:
                    if len(self.find_egg_in_index(egg_name)) > 0:
                        if egg_name.strip() not in propose_requires:
                            propose_requires.append(egg_name.strip())
                        found = True
                        break

            # .. or do we have one in the svn cache?
            if not found:
                for egg_name in guessed_egg_names:
                    if scm.guess_package_url(egg_name):
                        if egg_name.strip() not in propose_requires:
                            propose_requires.append(egg_name.strip())
                        found = True
                        break

            if not found:
                print '  ', output.colorize(ipath, output.INFO), 'in', \
                    output.colorize(file_, output.INFO), \
                    output.colorize('is not covered by requirements '
                                    'and I could find a egg with such a name',
                                    output.WARNING)

        if scm.get_package_name('.') in propose_requires:
            propose_requires.remove(scm.get_package_name('.'))

        if len(propose_requires)==0:
            self.notify(True)
            return
        propose_requires.sort()
        print ''
        print '  There are some requirements missing. I propose to add these:'
        for egg in propose_requires:
            print '   ', egg
        print ''

        # try to add them automatically:
        if input.prompt_bool('Should I try to add them?'):
            rows = open('setup.py').read().split('\n')
            # find "install_requires"
            frows = filter(lambda row:row.strip().startswith('install_requires='),
                           rows)
            if len(frows) != 1:
                output.error('Somethings wrong with your setup.py: expected only '
                             'one row containing "install_requires=", but '
                             'got %i' % len(frows), exit=1)
            insert_at = rows.index(frows[0]) + 1
            for egg in propose_requires:
                rows.insert(insert_at, ' ' * 8 + "'%s'," % egg)
            file_ = open('setup.py', 'w')
            file_.write('\n'.join(rows))
            file_.close()
            self._validate_setup_py()
            scm.add_and_commit_files('setup.py: added missing dependencies',
                                     'setup.py')
            self.notify_fix_completed()
Ejemplo n.º 18
0
    def check_setup_py(self):
        """setup.py checks
        """
        self.notify_part('Check setup.py')

        # MAINTAINER
        self.notify_check('Maintainer should be defined')
        maintainer = self.egginfo.get_maintainer()
        if maintainer and maintainer != 'UNKNOWN':
            self.notify(True)
        else:
            if len(filter(lambda row: row.startswith('maintainer'),
                          open('setup.py').read().split('\n'))) > 0:
                self.notify(False, 'maintainer is defined as variable but is '
                            'not used in setup call',
                            'add "maintainer=maintainer," to the setup call',
                            1, pause=False)
                if input.prompt_bool('Should I try to fix it?'):
                    rows = open('setup.py').read().split('\n')
                    file_ = open('setup.py', 'w')
                    found = False
                    for i, row in enumerate(rows):
                        file_.write(row)
                        if i != len(rows) - 1:
                            file_.write('\n')
                        if row.strip().startswith('author_email='):
                            file_.write(' ' * 6)
                            file_.write('maintainer=maintainer,')
                            file_.write('\n')
                            found = True
                    file_.close()
                    if not found:
                        output.error('Could not find keyword author_email in '
                                     'your setup.py, you have to fix it '
                                     'manually, sorry.', exit=1)
                    else:
                        self._validate_setup_py()
                        scm.add_and_commit_files(
                            'setup.py: register maintainer',
                            'setup.py')
                        self.notify_fix_completed()
                    print ''
            else:
                self.notify(False,
                            'maintainer is not defined in the egg at all',
                            'check %s on how to define a maintainer' % \
                                WIKI_PYTHON_EGGS)

        # VERSION.TXT
        self.notify_check('version.txt file exists')
        versiontxt_path = scm.get_package_name('.').replace('.', '/') + \
            '/version.txt'
        if os.path.exists(versiontxt_path) and os.path.isfile(versiontxt_path):
            self.notify(True)
        elif os.path.exists(versiontxt_path):
            self.notify(False, '%s exists but is not a file !?' % \
                            versiontxt_path,
                        'it should be a file containing the package version',
                        0)
        else:
            self.notify(False, '%s does not exist' % versiontxt_path,
                        pause=False)
            if input.prompt_bool('Should I try to fix it?'):
                version = self.egginfo.get_version()
                file_ = open(versiontxt_path, 'w')
                file_.write(version)
                file_.close()
                scm.add_and_commit_files('Added version.txt file',
                                         versiontxt_path)
                self.notify_fix_completed()
                print ''

        # VERSION
        self.notify_check('Version is taken form version.txt')
        rows = open('setup.py').read().split('\n')
        version_rows = filter(lambda row: row.startswith('version ='), rows)
        if len(version_rows) != 1:
            self.notify(False, 'I\'m confused, it seems that you have a mess '
                        'with your versions.',
                        'check %s on how to define versions properly' % \
                            WIKI_PYTHON_EGGS)
        elif not version_rows[0].startswith('version = open('):
            self.notify(False, 'I\'m guessing that the version in your '
                        'setup.py is not taken from %s' % versiontxt_path,
                        'check %s on how to define versions properly' % \
                            WIKI_PYTHON_EGGS, pause=False)
            if input.prompt_bool('Should I try to fix it?'):
                new_version_row = "version = open('%s').read().strip()" % \
                    versiontxt_path
                rows[rows.index(version_rows[0])] = new_version_row
                file_ = open('setup.py', 'w')
                file_.write('\n'.join(rows))
                file_.close()
                self._validate_setup_py()
                scm.add_and_commit_files('setup.py: using version.txt',
                                         'setup.py')
                self.notify_fix_completed()
        else:
            self.notify(True)

        # NAMESPACES
        self.notify_check('Check namespaces')
        guessed_namespaces = []
        namespace_parts = scm.get_package_name('.').split('.')
        for i, space in enumerate(namespace_parts[:-1]):
            guessed_namespaces.append('.'.join(namespace_parts[:i + 1]))
        if set(guessed_namespaces) == set(self.egginfo.namespace_packages):
            self.notify(True)
        else:
            print '  current namespaces: ', str(
                self.egginfo.namespace_packages)
            print '  expected namespaces:', str(guessed_namespaces)
            print '  package name:       ', scm.get_package_name('.')
            self.notify(False, 'I think your namespace_packages declaration '
                        'is wrong', pause=False)
            if input.prompt_bool('Should I try to fix it?'):
                guessed_namespaces.sort()
                rows = open('setup.py').read().split('\n')
                nsrows = filter(lambda x:
                                    x.strip().startswith('namespace_packages'),
                                rows)
                if len(nsrows) != 1:
                    output.error('Could not fix it: expected one and only one'
                                 ' line beginning with "namespace_packages"'
                                 ' in setup.py..',
                                 exit=True)
                else:
                    new_row = nsrows[0].split('=')[0] + '=' + \
                        str(guessed_namespaces) + ','
                    rows[rows.index(nsrows[0])] = new_row
                    file_ = open('setup.py', 'w')
                    file_.write('\n'.join(rows))
                    file_.close()
                    self._validate_setup_py()
                    scm.add_and_commit_files(
                        'setup.py: fixed namespace_packages', 'setup.py')
                    self.notify_fix_completed()

        # VARIOUS CHECKS
        self.notify_check('Various setup.py checks')
        failure = False

        # .. name
        if self.egginfo.get_name() != scm.get_package_name('.'):
            failure = True
            self.notify(False, 'Name: Expected name in setup.py to be ' + \
                            '"%s" ' % scm.get_package_name('.') + \
                            'but it was "%s"' % self.egginfo.get_name())

        # maintainer in description
        if self.egginfo.get_maintainer() not in self.egginfo.get_description():
            failure = True
            self.notify(False, 'Description: Maintainer is not defined '
                        'in description',
                        'Check out %s' % WIKI_PYTHON_EGGS, 2)

        # docs/HISTORY.txt
        setuppy = open('setup.py').read()
        if 'HISTORY.txt' not in setuppy or \
                not os.path.exists('docs/HISTORY.txt') or \
                open('docs/HISTORY.txt').read() not in \
                self.egginfo.get_long_description():
            self.notify(False, 'docs/HISTORY.txt embedded be used in '
                        'long_description',
                        'Check long_description on %s' % WIKI_PYTHON_EGGS)

        # author: use maintainer
        expected_author = '%s, 4teamwork GmbH' % self.egginfo.get_maintainer()
        if self.egginfo.get_author() != expected_author:
            failure = True
            self.notify(False, 'Author: Expected author to be "%s""' % \
                            expected_author + \
                            ' but it is "%s"' % self.egginfo.get_author(),
                        'Check out %s' % WIKI_PYTHON_EGGS, 2)

        # author email
        if self.egginfo.get_author_email() != 'mailto:[email protected]':
            failure = True
            self.notify(False, 'Author email: the email should be'
                        ' "mailto:[email protected]"',
                        'Check out %s' % WIKI_PYTHON_EGGS, 2)

        # license
        if self.egginfo.get_license() != 'GPL2':
            failure = True
            self.notify(False, 'License: the license should be "GPL2"',
                        'Check out %s' % WIKI_PYTHON_EGGS, 2)

        # .. ok?
        if not failure:
            self.notify(True)

        # run egg_info
        self.notify_check('we should be able to run `setup.py egg_info`')
        state, out, errors = self._validate_setup_py()
        if out:
            print '   ', out.replace('\n', '\n    ')
        if errors:
            print '   ', errors.replace('\n', '\n    ')
        if state == 0:
            self.notify(True)
        else:
            state.notify(False, 'Cant run `python setup.py egg_info`, see '
                         'errors above', 0)
Ejemplo n.º 19
0
    def pre_build_check(self):
        """ Check if a build will work later. Check this before doing anything
        by building and loading the egg.
        """
        output.part_title('Make a test-build for preventing bad dists')
        cwd = os.getcwd()
        # make a sdist
        runcmd('%s setup.py sdist' % sys.executable)
        os.chdir('dist')
        # switch dir
        print output.colorize('cd dist', output.INFO)
        # extract
        runcmd('tar -xf *.tar.gz')
        # find extracted dir / chdir
        distdir = None
        for file_ in os.listdir('.'):
            if os.path.isdir(file_):
                distdir = file_
                break
        if not distdir:
            output.error('Something is wrong: could not find extracted dist directory',
                         exit=1)
        os.chdir(distdir)
        print output.colorize('cd %s' % distdir, output.INFO)
        # test setup.py
        cmd = '%s setup.py egg_info' % sys.executable
        state, response, error = runcmd_with_exitcode(cmd,
                                                      respond=True,
                                                      respond_error=True)
        # cd back to original dir
        os.chdir(cwd)
        # remove stuff
        runcmd('rm -rf dist')
        # did it work?
        if state != 0:
            output.error('Something\'s wrong: could not load setup.py on distribution, ' +\
                             'you may have a problem with your setup.py / MANIFEST.in:',
                         exit=(not error and True or False))
            if response:
                print output.colorize(response, output.INFO)
            if error:
                output.error(error, exit=True)

        # check locales
        locales_dir = os.path.join(scm.get_package_name('.').replace('.', '/'),
                                   'locales')
        if os.path.isdir(locales_dir):
            for basedir, dirs, files in os.walk(locales_dir):
                for file_ in files:
                    path = os.path.join(basedir, file_)
                    if path.endswith('.po'):
                        # check with msgfmt
                        exitcode, errors = runcmd_with_exitcode(
                            'msgfmt -o /dev/null %s' % path,
                            log=True,
                            respond_error=True)
                        if exitcode > 0:
                            output.error(errors, exit=True)

                        data = open(path).read()
                        if 'fuzzy' in data:
                            print path
                            output.error('You have "Fuzzy" entries in your '
                            'translations! I\'m not releasing '
                                         'it like this.', exit=True)
Ejemplo n.º 20
0
    def _get_buildout_pinning_mapping(self):
        """ Example:
        (
        ('buildout.cfg', (('foo.bar', None, '1.7'), (...))),
        ('http://kgs...', (('foo.bar', 'a_extra', '1.3'))),
        )
        """
        buildout_file = os.path.abspath(self.options.buildout)
        self.find_links = []
        if not os.path.isfile(buildout_file):
            error('Buildout not found at %s' % buildout_file,
                  exit=True)
        # load buildout with config parsers
        data = []
        loaded = []
        version_section_name = 'versions'

        # load extends
        def load_extends(file, dir):
            if file.startswith('http'):
                # kgs / http
                path = self._download_file(file)
            else:
                # local
                path = os.path.join(dir, file)

            # is it already loaded?
            if path in loaded:
                return

            # load it
            parser = ConfigParser.SafeConfigParser()
            parser.read(path)
            loaded.append(path)

            # get the defined versions
            if parser.has_section(version_section_name):
                subdata = []
                for pkg, version in parser.items(version_section_name):
                    extra = None
                    if '[' in pkg and ']' in pkg:
                        extra = pkg.split('[')[1].split(']')[0]
                    subdata.append((pkg, extra, version))
                # make a pretty relative name
                pretty_name = file
                buildout_dir = os.path.dirname(buildout_file)
                if path.startswith(buildout_dir):
                    pretty_name = path[len(buildout_dir) + 1:]
                data.insert(0, (pretty_name, subdata))

            # follow extends
            if parser.has_option('buildout', 'extends'):
                extend_files = parser.get('buildout', 'extends').split()
                for file in extend_files:
                    load_extends(file.strip(), os.path.dirname(path))

            # remember find_links
            if parser.has_option('buildout', 'find-links'):
                for link in parser.get('buildout', 'find-links').split():
                    link = link.strip()
                    if link:
                        self.find_links.append(link)

        load_extends(os.path.basename(buildout_file),
                     os.path.abspath(os.path.dirname(buildout_file)))

        return data