From: fuzzyray Date: Wed, 24 Mar 2010 15:21:58 +0000 (-0000) Subject: Merge genscripts rev 406 X-Git-Tag: gentoolkit-0.3.0_rc10~6 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=db09a0e43e2e1cf98f0d789f651a1816a46dcba7;p=gentoolkit.git Merge genscripts rev 406 svn path=/trunk/gentoolkit/; revision=756 --- diff --git a/README.dev b/README.dev index 99a7ed4..6c025cb 100644 --- a/README.dev +++ b/README.dev @@ -16,6 +16,11 @@ Note: We are using VERSION="0.3.0" simply as an example. - Run Gentoolkit's test suite, make sure it passes: Note: requires dev-python/snakeoil + +Note: If running from the gentoolkit repository, please grab the eclean test file from: +http://code.google.com/p/genscripts/source/browse/trunk/gentoolkit/pym/gentoolkit/test/eclean/testdistfiles.tar.gz +Please do not add/commit the test file to the gentoolkit repository + ./setup.py test - Create a tag for the release diff --git a/TODO b/TODO index 997919e..1cee1a4 100644 --- a/TODO +++ b/TODO @@ -20,7 +20,6 @@ equery (modern): Add more --debug stuff Write tests for Dependencies._parser Profile Dependencies._parser - Tighten up CPV.split_cpv, it's slow and bad Extend PackageFormatter usage to everything that outputs packages to allow for purvasive use of -F, --format goodness @@ -32,4 +31,3 @@ Ebuild changes: For Next Release: - write NEWS file - - make CPV.__init__ more strict, it allows some silly stuff diff --git a/bin/glsa-check b/bin/glsa-check index 705e7b4..a783c27 100755 --- a/bin/glsa-check +++ b/bin/glsa-check @@ -4,12 +4,12 @@ # This program is licensed under the GPL, version 2 import sys +import os import codecs from functools import reduce import portage from portage.output import * -from portage import os from getopt import getopt, GetoptError diff --git a/pym/gentoolkit/analyse/__init__.py b/pym/gentoolkit/analyse/__init__.py index 82625b6..46d6185 100644 --- a/pym/gentoolkit/analyse/__init__.py +++ b/pym/gentoolkit/analyse/__init__.py @@ -38,7 +38,6 @@ import time from getopt import getopt, GetoptError import portage -from portage import os import gentoolkit as gen from gentoolkit import errors @@ -120,7 +119,7 @@ def main(): ) loaded_module.main(module_args) except portage.exception.AmbiguousPackageName as err: - raise errors.GentoolkitAmbiguousPackage(err) + raise errors.GentoolkitAmbiguousPackage(err.args[0]) except IOError as err: if err.errno != errno.EPIPE: raise diff --git a/pym/gentoolkit/analyse/base.py b/pym/gentoolkit/analyse/base.py index d45ccc6..d4febdb 100644 --- a/pym/gentoolkit/analyse/base.py +++ b/pym/gentoolkit/analyse/base.py @@ -19,8 +19,6 @@ import sys import time from getopt import gnu_getopt, GetoptError -from portage import os - import gentoolkit.pprinter as pp from gentoolkit.formatters import format_options from gentoolkit.base import mod_usage diff --git a/pym/gentoolkit/analyse/rebuild.py b/pym/gentoolkit/analyse/rebuild.py index c7cf1e5..e04d8be 100644 --- a/pym/gentoolkit/analyse/rebuild.py +++ b/pym/gentoolkit/analyse/rebuild.py @@ -13,6 +13,7 @@ what packages according to the Installed package database""" from __future__ import print_function +import os import sys import gentoolkit @@ -24,7 +25,6 @@ from gentoolkit.analyse.lib import (get_installed_use, get_flags, from gentoolkit.analyse.output import RebuildPrinter import portage -from portage import os def cpv_all_diff_use( diff --git a/pym/gentoolkit/base.py b/pym/gentoolkit/base.py index 29d3279..832d902 100644 --- a/pym/gentoolkit/base.py +++ b/pym/gentoolkit/base.py @@ -14,12 +14,11 @@ __docformat__ = 'epytext' import errno +import os import sys import time from getopt import gnu_getopt, GetoptError -from portage import os - import gentoolkit from gentoolkit import errors #from gentoolkit.textwrap_ import TextWrapper diff --git a/pym/gentoolkit/eclean/clean.py b/pym/gentoolkit/eclean/clean.py index 9f6d597..b2cc562 100644 --- a/pym/gentoolkit/eclean/clean.py +++ b/pym/gentoolkit/eclean/clean.py @@ -7,9 +7,9 @@ from __future__ import print_function +import os import sys -from portage import os import gentoolkit.pprinter as pp from gentoolkit.eclean.pkgindex import PkgIndex diff --git a/pym/gentoolkit/eclean/cli.py b/pym/gentoolkit/eclean/cli.py index 6a507ef..90eff68 100644 --- a/pym/gentoolkit/eclean/cli.py +++ b/pym/gentoolkit/eclean/cli.py @@ -16,13 +16,13 @@ __productname__ = "eclean" __description__ = "A cleaning tool for Gentoo distfiles and binaries." +import os import sys import re import time import getopt import portage -from portage import os from portage.output import white, yellow, turquoise, green, teal, red import gentoolkit.pprinter as pp diff --git a/pym/gentoolkit/eclean/exclude.py b/pym/gentoolkit/eclean/exclude.py index 74a982a..fa88ae1 100644 --- a/pym/gentoolkit/eclean/exclude.py +++ b/pym/gentoolkit/eclean/exclude.py @@ -7,11 +7,11 @@ from __future__ import print_function +import os import sys import re import portage -from portage import os from gentoolkit.pprinter import warn # Misc. shortcuts to some portage stuff: diff --git a/pym/gentoolkit/eclean/pkgindex.py b/pym/gentoolkit/eclean/pkgindex.py index f9d9f3c..a09ab55 100644 --- a/pym/gentoolkit/eclean/pkgindex.py +++ b/pym/gentoolkit/eclean/pkgindex.py @@ -7,12 +7,12 @@ from __future__ import print_function import subprocess +import os import sys import gentoolkit.pprinter as pp import portage -from portage import os class PkgIndex(object): diff --git a/pym/gentoolkit/eclean/search.py b/pym/gentoolkit/eclean/search.py index 4c5b0ac..91bb182 100644 --- a/pym/gentoolkit/eclean/search.py +++ b/pym/gentoolkit/eclean/search.py @@ -7,19 +7,18 @@ from __future__ import print_function +import os import re import stat import sys +from functools import partial import portage -from portage import os import gentoolkit import gentoolkit.pprinter as pp from gentoolkit.eclean.exclude import (exclDictMatchCP, exclDictExpand, exclDictExpandPkgname, exclMatchFilename) -#from gentoolkit.package import Package -from gentoolkit.helpers import walk # Misc. shortcuts to some portage stuff: @@ -28,7 +27,7 @@ pkgdir = port_settings["PKGDIR"] err = sys.stderr deprecated_message=""""Deprecation Warning: Installed package: %s - Is no longer in the tree or an installed overlay""" + Is no longer in the tree or an installed overlay""" DEPRECATED = pp.warn(deprecated_message) debug_modules = [] @@ -80,7 +79,8 @@ class DistfilesSearch(object): time_limit=0, size_limit=0, _distdir=distdir, - deprecate=False + deprecate=False, + extra_checks=() ): """Find all obsolete distfiles. @@ -121,8 +121,10 @@ class DistfilesSearch(object): # gather the files to be cleaned self.output("...checking limits for %d ebuild sources" %len(pkgs)) - clean_me = self._check_limits(_distdir, - size_limit, time_limit, exclude) + + checks = self._get_default_checks(size_limit, time_limit, exclude) + checks.extend(extra_checks) + clean_me = self._check_limits(_distdir, checks, clean_me) # remove any protected files from the list self.output("...removing protected sources from %s candidates to clean" %len(clean_me)) @@ -136,89 +138,104 @@ class DistfilesSearch(object): ####################### begin _check_limits code block - def _check_limits(self, - _distdir, - size_limit, - time_limit, - exclude, - clean_me={} - ): - """Checks files if they exceed size and/or time_limits, etc. - """ - checks = [self._isreg_limit_] + def _get_default_checks(self, size_limit, time_limit, excludes): + #checks =[(self._isreg_check_, "is_reg_check")] + checks =[self._isreg_check_] + if 'filenames' in excludes: + #checks.append((partial(self._filenames_check_, excludes), "Filenames_check")) + checks.append(partial(self._filenames_check_, excludes)) + else: + self.output(" - skipping exclude filenames check") if size_limit: - checks.append(self._size_limit_) - self.size_limit = size_limit + #checks.append((partial(self._size_check_, size_limit), "size_check")) + checks.append(partial(self._size_check_, size_limit)) else: self.output(" - skipping size limit check") if time_limit: - checks.append(self._time_limit_) - self.time_limit = time_limit + #print("time_limit = ", time_limit/1000000,"M sec") + #checks.append((partial(self._time_check_, time_limit), "time_check")) + checks.append(partial(self._time_check_, time_limit)) else: self.output(" - skipping time limit check") - if 'filenames' in exclude: - checks.append(self._filenames_limit_) - self.exclude = exclude - else: - self.output(" - skipping exclude filenames check") - max_index = len(checks) + return checks + + + def _check_limits(self, + _distdir, + checks, + clean_me=None + ): + """Checks files if they exceed size and/or time_limits, etc. + + To start with everything is considered dirty and is excluded + only if it matches some condition. + """ + if clean_me is None: + clean_me = {} for file in os.listdir(_distdir): filepath = os.path.join(_distdir, file) try: - file_stat = os.stat(filepath) - except: - continue - _index = 0 - next = True - skip_file = False - while _index= self.size_limit): - #print( "size match ", file, file_stat[stat.ST_SIZE]) - return False, True - return True, False - - def _time_limit_(self, file_stat, file): - """checks if the file exceeds the time_limit""" - if (file_stat[stat.ST_MTIME] >= self.time_limit): - #print( "time match ", file, file_stat[stat.ST_MTIME]) - return False, True - return True,False - - def _filenames_limit_(self, file_stat, file): + if (file_stat[stat.ST_SIZE] >= size_limit): + #print( "size mismatch ", file, file_stat[stat.ST_SIZE]) + return True, False + return False, True + + @staticmethod + def _time_check_(time_limit, file_stat, file): + """checks if the file exceeds the time_limit + (think forward, not back, time keeps increasing)""" + if (file_stat[stat.ST_MTIME] >= time_limit): + #print( "time match too young ", file, file_stat[stat.ST_MTIME]/1000000,"M sec.") + return True, False + #print( "time match too old", file, file_stat[stat.ST_MTIME]/1000000,"M sec.") + return False, True + + @staticmethod + def _filenames_check_(exclude, file_stat, file): """checks if the file matches an exclusion file listing""" # Try to match file name directly - if file in self.exclude['filenames']: - return False, True + if file in exclude['filenames']: + return True, False # See if file matches via regular expression matching else: file_match = False - for file_entry in self.exclude['filenames']: - if self.exclude['filenames'][file_entry].match(file): + for file_entry in exclude['filenames']: + if exclude['filenames'][file_entry].match(file): file_match = True break if file_match: - return False, True - return True, False + #print( "filename match ", file) + return True, False + return False, True ####################### end _check_limits code block - def _remove_protected(self, + @staticmethod + def _remove_protected( pkgs, clean_me ): @@ -242,8 +259,8 @@ class DistfilesSearch(object): def _non_destructive(self, destructive, fetch_restricted, - pkgs_ = {}, - exclude={} + pkgs_ = None, + exclude=None ): """performs the non-destructive checks @@ -254,7 +271,12 @@ class DistfilesSearch(object): @returns packages and thier SRC_URI's: {cpv: src_uri,} @rtype: dictionary """ - pkgs = pkgs_.copy() + if pkgs_ is None: + pkgs = {} + else: + pkgs = pkgs_.copy() + if exclude is None: + exclude = {} deprecated = {} # the following code block was split to optimize for speed # list all CPV from portree (yeah, that takes time...) @@ -272,7 +294,7 @@ class DistfilesSearch(object): cpvs.difference_update(installed_cpvs) self.output(" - getting fetch-restricted source file names " + "for %d remaining ebuilds" %len(cpvs)) - pkgs, _deprecated = self._fetch_restricted(destructive, pkgs, cpvs) + pkgs, _deprecated = self._fetch_restricted(pkgs, cpvs) deprecated.update(_deprecated) else: self.output(" - getting source file names " + @@ -281,18 +303,20 @@ class DistfilesSearch(object): deprecated.update(_deprecated) return pkgs, deprecated - def _fetch_restricted(self, destructive, pkgs_, cpvs): + def _fetch_restricted(self, pkgs_, cpvs): """perform fetch restricted non-destructive source filename lookups - @param destructive: boolean @param pkgs_: starting dictionary to add to @param cpvs: set of (cat/pkg-ver, ...) identifiers @return a new pkg dictionary @rtype: dictionary """ - pkgs = pkgs_.copy() + if pkgs_ is None: + pkgs = {} + else: + pkgs = pkgs_.copy() deprecated = {} for cpv in cpvs: # get SRC_URI and RESTRICT from aux_get @@ -326,7 +350,10 @@ class DistfilesSearch(object): @return a new pkg dictionary @rtype: dictionary """ - pkgs = pkgs_.copy() + if pkgs_ is None: + pkgs = {} + else: + pkgs = pkgs_.copy() deprecated = {} for cpv in cpvs: # get SRC_URI from aux_get @@ -344,7 +371,7 @@ class DistfilesSearch(object): def _destructive(self, package_names, exclude, - pkgs_={}, + pkgs_=None, installed_included=False ): """Builds on pkgs according to input options @@ -359,7 +386,10 @@ class DistfilesSearch(object): @returns pkgs: {cpv: src_uri,} """ - pkgs = pkgs_.copy() + if pkgs_ is None: + pkgs = {} + else: + pkgs = pkgs_.copy() deprecated = {} pkgset = set() if not installed_included: @@ -390,7 +420,8 @@ class DistfilesSearch(object): #self.output(" - done...") return pkgs, deprecated - def _get_excludes(self, exclude): + @staticmethod + def _get_excludes(exclude): """Expands the exclude dictionary into a set of CPV's @@ -433,7 +464,7 @@ class DistfilesSearch(object): def findPackages( options, - exclude={}, + exclude=None, destructive=False, time_limit=0, package_names=False, @@ -463,6 +494,8 @@ def findPackages( @rtype: dict @return clean_me i.e. {'cat/pkg-ver.tbz2': [filepath],} """ + if exclude is None: + exclude = {} clean_me = {} # create a full package dictionary @@ -475,7 +508,7 @@ def findPackages( print( pp.error("(Check your /etc/make.conf and environment)."), file=sys.stderr) print( pp.error("Error: %s" %str(er)), file=sys.stderr) exit(1) - for root, dirs, files in walk(pkgdir): + for root, dirs, files in os.walk(pkgdir): if root[-3:] == 'All': continue for file in files: diff --git a/pym/gentoolkit/equery/__init__.py b/pym/gentoolkit/equery/__init__.py index d511082..60ec161 100644 --- a/pym/gentoolkit/equery/__init__.py +++ b/pym/gentoolkit/equery/__init__.py @@ -8,9 +8,6 @@ from __future__ import print_function -# Move to Imports section after Python 2.6 is stable - - __all__ = ( 'format_options', 'format_package_names', @@ -25,12 +22,12 @@ __version__ = "svn" # ======= import errno +import os import sys import time from getopt import getopt, GetoptError import portage -from portage import os import gentoolkit from gentoolkit import CONFIG @@ -347,7 +344,7 @@ def main(): ) loaded_module.main(module_args) except portage.exception.AmbiguousPackageName as err: - raise errors.GentoolkitAmbiguousPackage(err) + raise errors.GentoolkitAmbiguousPackage(err.args[0]) except IOError as err: if err.errno != errno.EPIPE: raise diff --git a/pym/gentoolkit/equery/belongs.py b/pym/gentoolkit/equery/belongs.py index b426c3a..8e8abb3 100644 --- a/pym/gentoolkit/equery/belongs.py +++ b/pym/gentoolkit/equery/belongs.py @@ -31,9 +31,9 @@ from gentoolkit.helpers import FileOwner # ======= QUERY_OPTS = { - "fullRegex": False, - "earlyOut": False, - "nameOnly": False + "full_regex": False, + "early_out": False, + "name_only": False } # ======= @@ -62,7 +62,7 @@ class BelongsPrinter(object): name = pkg.cp else: name = str(pkg.cpv) - print(name) + pp.uprint(name) def print_verbose(self, pkg, cfile): "Format for full output." @@ -71,8 +71,7 @@ class BelongsPrinter(object): name = pkg.cp else: name = str(pkg.cpv) - print(pp.cpv(name), "(" + file_str + ")") - + pp.uprint(pp.cpv(name), "(" + file_str + ")") # ========= # Functions @@ -91,11 +90,11 @@ def parse_module_options(module_opts): sys.stderr.write(pp.warn("Use of --earlyout is deprecated.")) sys.stderr.write(pp.warn("Please use --early-out.")) print() - QUERY_OPTS['earlyOut'] = True + QUERY_OPTS['early_out'] = True elif opt in ('-f', '--full-regex'): - QUERY_OPTS['fullRegex'] = True + QUERY_OPTS['full_regex'] = True elif opt in ('-n', '--name-only'): - QUERY_OPTS['nameOnly'] = True + QUERY_OPTS['name_only'] = True def print_help(with_description=True): @@ -141,15 +140,17 @@ def main(input_args): sys.exit(2) if CONFIG['verbose']: - print(" * Searching for %s ... " % (pp.regexpquery(",".join(queries)))) + pp.uprint(" * Searching for %s ... " % ( + pp.regexpquery(",".join(queries))) + ) printer_fn = BelongsPrinter( - verbose=CONFIG['verbose'], name_only=QUERY_OPTS['nameOnly'] + verbose=CONFIG['verbose'], name_only=QUERY_OPTS['name_only'] ) find_owner = FileOwner( - is_regex=QUERY_OPTS['fullRegex'], - early_out=QUERY_OPTS['earlyOut'], + is_regex=QUERY_OPTS['full_regex'], + early_out=QUERY_OPTS['early_out'], printer_fn=printer_fn ) diff --git a/pym/gentoolkit/equery/changes.py b/pym/gentoolkit/equery/changes.py index 0a5f9d0..b290f0a 100644 --- a/pym/gentoolkit/equery/changes.py +++ b/pym/gentoolkit/equery/changes.py @@ -8,9 +8,6 @@ from __future__ import print_function -# Move to Imports sections when Python 2.6 is stable - - __docformat__ = 'epytext' # ======= @@ -18,10 +15,9 @@ __docformat__ = 'epytext' # ======= import sys +import os from getopt import gnu_getopt, GetoptError -from portage import os - import gentoolkit.pprinter as pp from gentoolkit import errors from gentoolkit.atom import Atom @@ -34,8 +30,8 @@ from gentoolkit.query import Query # ======= QUERY_OPTS = { - 'onlyLatest': False, - 'showFullLog': False, + 'only_latest': False, + 'show_full_log': False, 'limit': None, 'from': None, 'to': None @@ -86,9 +82,9 @@ def parse_module_options(module_opts): print_help() sys.exit(0) elif opt in ('-f', '--full'): - QUERY_OPTS['showFullLog'] = True + QUERY_OPTS['show_full_log'] = True elif opt in ('-l', '--latest'): - QUERY_OPTS['onlyLatest'] = True + QUERY_OPTS['only_latest'] = True elif opt in ('--limit',): set_limit(posarg) elif opt in ('--from',): @@ -103,9 +99,9 @@ def print_entries(entries): len_entries = len(entries) for i, entry in enumerate(entries, start=1): if i < len_entries: - print(entry) + pp.uprint(entry) else: - print(entry.strip()) + pp.uprint(entry.strip()) def set_limit(posarg): @@ -157,10 +153,10 @@ def main(input_args): # Output # - if (QUERY_OPTS['onlyLatest'] or ( + if (QUERY_OPTS['only_latest'] or ( changelog.entries and not changelog.indexed_entries )): - print(changelog.latest.strip()) + pp.uprint(changelog.latest.strip()) else: end = QUERY_OPTS['limit'] or len(changelog.indexed_entries) if QUERY_OPTS['to'] or QUERY_OPTS['from']: @@ -170,7 +166,7 @@ def main(input_args): to_ver=QUERY_OPTS['to'] )[:end] ) - elif QUERY_OPTS['showFullLog']: + elif QUERY_OPTS['show_full_log']: print_entries(changelog.full[:end]) else: # Raises GentoolkitInvalidAtom here if invalid diff --git a/pym/gentoolkit/equery/check.py b/pym/gentoolkit/equery/check.py index 7353b31..84be634 100644 --- a/pym/gentoolkit/equery/check.py +++ b/pym/gentoolkit/equery/check.py @@ -14,12 +14,12 @@ __docformat__ = 'epytext' # Imports # ======= +import os import sys from functools import partial from getopt import gnu_getopt, GetoptError import portage.checksum as checksum -from portage import os import gentoolkit.pprinter as pp from gentoolkit import errors @@ -213,10 +213,10 @@ def checks_printer(cpv, data, verbose=True, only_failures=False): else: if verbose: if not cpv in seen: - print("* Checking %s ..." % (pp.emph(str(cpv)))) + pp.uprint("* Checking %s ..." % (pp.emph(str(cpv)))) seen.append(cpv) else: - print("%s:" % cpv, end=' ') + pp.uprint("%s:" % cpv, end=' ') if verbose: for err in errs: diff --git a/pym/gentoolkit/equery/depends.py b/pym/gentoolkit/equery/depends.py index 4fccaaa..2890365 100644 --- a/pym/gentoolkit/equery/depends.py +++ b/pym/gentoolkit/equery/depends.py @@ -28,9 +28,9 @@ from gentoolkit.cpv import CPV # ======= QUERY_OPTS = { - "includeMasked": False, - "onlyDirect": True, - "maxDepth": -1, + "include_masked": False, + "only_direct": True, + "max_depth": -1, } # ======= @@ -53,7 +53,8 @@ class DependPrinter(object): """Verbosely prints a set of dep strings.""" sep = ' ? ' if (depatom and use_conditional) else '' - print(indent + pp.cpv(cpv), "(" + use_conditional + sep + depatom + ")") + pp.uprint(indent + pp.cpv(cpv), "(" + use_conditional + + sep + depatom + ")") # W0613: *Unused argument %r* # pylint: disable-msg=W0613 @@ -61,7 +62,7 @@ class DependPrinter(object): def print_quiet(indent, cpv, use_conditional, depatom): """Quietly prints a subset set of dep strings.""" - print(indent + pp.cpv(cpv)) + pp.uprint(indent + pp.cpv(cpv)) def format_depend(self, dep, dep_is_displayed): """Format a dependency for printing. @@ -131,9 +132,9 @@ def parse_module_options(module_opts): print_help() sys.exit(0) elif opt in ('-a', '--all-packages'): - QUERY_OPTS['includeMasked'] = True + QUERY_OPTS['include_masked'] = True elif opt in ('-D', '--indirect'): - QUERY_OPTS['onlyDirect'] = False + QUERY_OPTS['only_direct'] = False elif opt in ('--depth'): if posarg.isdigit(): depth = int(posarg) @@ -143,7 +144,7 @@ def parse_module_options(module_opts): print() print_help(with_description=False) sys.exit(2) - QUERY_OPTS["maxDepth"] = depth + QUERY_OPTS["max_depth"] = depth def main(input_args): @@ -176,7 +177,7 @@ def main(input_args): print() pkg = Dependencies(query) - if QUERY_OPTS['includeMasked']: + if QUERY_OPTS['include_masked']: pkggetter = get_cpvs else: pkggetter = get_installed_cpvs @@ -184,9 +185,9 @@ def main(input_args): if CONFIG['verbose']: print(" * These packages depend on %s:" % pp.emph(pkg.cpv)) pkg.graph_reverse_depends( - pkgset=sorted(pkggetter(), key = CPV), - max_depth=QUERY_OPTS["maxDepth"], - only_direct=QUERY_OPTS["onlyDirect"], + pkgset=sorted(pkggetter(), key=CPV), + max_depth=QUERY_OPTS["max_depth"], + only_direct=QUERY_OPTS["only_direct"], printer_fn=dep_print ) diff --git a/pym/gentoolkit/equery/depgraph.py b/pym/gentoolkit/equery/depgraph.py index 53f0b5b..9fbdd42 100644 --- a/pym/gentoolkit/equery/depgraph.py +++ b/pym/gentoolkit/equery/depgraph.py @@ -155,21 +155,23 @@ def depgraph_printer( pkg.environment('KEYWORDS'))] mask = pp.masking(mask) try: - print(' '.join((indent, decorator, pp.cpv(str(pkg.cpv)), atom, mask, use))) + pp.uprint(' '.join( + (indent, decorator, pp.cpv(str(pkg.cpv)), atom, mask, use) + )) except AttributeError: # 'NoneType' object has no attribute 'cpv' - print(''.join((indent, decorator, "(no match for %r)" % dep.atom))) + pp.uprint(''.join((indent, decorator, "(no match for %r)" % dep.atom))) def make_depgraph(pkg, printer_fn): """Create and display depgraph for each package.""" + print() if CONFIG['verbose']: - print() # blank line improves readability & package version separation - print(" * " + pp.subsection("dependency graph for ") + pp.cpv(str(pkg.cpv))) + pp.uprint(" * " + pp.subsection("dependency graph for ") + + pp.cpv(str(pkg.cpv))) else: - print() - print("%s:" % pkg.cpv) + pp.uprint("%s:" % pkg.cpv) # Print out the first package printer_fn(0, pkg, None, initial_pkg=True) @@ -186,7 +188,7 @@ def make_depgraph(pkg, printer_fn): n_packages = pp.number(str(len(deps))) max_seen = pp.number(str(max(x[0] for x in deps))) info = "[ %s stats: packages (%s), max depth (%s) ]" - print(info % (pkgname, n_packages, max_seen)) + pp.uprint(info % (pkgname, n_packages, max_seen)) def main(input_args): diff --git a/pym/gentoolkit/equery/files.py b/pym/gentoolkit/equery/files.py index ac2dc13..2843baf 100644 --- a/pym/gentoolkit/equery/files.py +++ b/pym/gentoolkit/equery/files.py @@ -14,11 +14,11 @@ __docformat__ = 'epytext' # Imports # ======= +import os import sys from getopt import gnu_getopt, GetoptError import portage -from portage import os import gentoolkit.pprinter as pp from gentoolkit.equery import (format_filetype, format_options, mod_usage, @@ -103,7 +103,7 @@ def display_files(contents): if contents[name][0] == "dir": if len(last) == 0: last = basename - print(pp.path(indent + basename[0])) + pp.uprint(pp.path(indent + basename[0])) continue for i, directory in enumerate(basename): try: @@ -113,16 +113,17 @@ def display_files(contents): pass last = basename if len(last) == 1: - print(pp.path(indent + last[0])) + pp.uprint(pp.path(indent + last[0])) continue - print(pp.path(indent + "> /" + last[-1])) + pp.uprint(pp.path(indent + "> /" + last[-1])) elif contents[name][0] == "sym": - print(pp.path(indent + "+"), end=' ') - print(pp.path_symlink(basename[-1] + " -> " + contents[name][2])) + pp.uprint(pp.path(indent + "+"), end=' ') + pp.uprint(pp.path_symlink(basename[-1] + " -> " + + contents[name][2])) else: - print(pp.path(indent + "+ ") + basename[-1]) + pp.uprint(pp.path(indent + "+ ") + basename[-1]) else: - print(format_filetype( + pp.uprint(format_filetype( name, contents[name], show_type=QUERY_OPTS["show_type"], @@ -309,7 +310,7 @@ def main(input_args): for pkg in matches: if CONFIG['verbose']: - print(" * Contents of %s:" % pp.cpv(str(pkg.cpv))) + pp.uprint(" * Contents of %s:" % pp.cpv(str(pkg.cpv))) contents = pkg.parsed_contents() display_files(filter_contents(contents)) diff --git a/pym/gentoolkit/equery/hasuse.py b/pym/gentoolkit/equery/hasuse.py index 88c9da1..03b989e 100644 --- a/pym/gentoolkit/equery/hasuse.py +++ b/pym/gentoolkit/equery/hasuse.py @@ -104,7 +104,7 @@ def display_useflags(query, pkg): not QUERY_OPTS["in_porttree"]): if not 'O' in pkgstr.location: return - print(pkgstr) + pp.uprint(pkgstr) @@ -163,7 +163,7 @@ def main(input_args): print() if CONFIG['verbose']: - print(" * Searching for USE flag %s ... " % pp.emph(query)) + pp.uprint(" * Searching for USE flag %s ... " % pp.emph(query)) for pkg in matches: display_useflags(query, pkg) diff --git a/pym/gentoolkit/equery/list_.py b/pym/gentoolkit/equery/list_.py index 84b1a7e..d783e02 100644 --- a/pym/gentoolkit/equery/list_.py +++ b/pym/gentoolkit/equery/list_.py @@ -199,7 +199,7 @@ def main(input_args): not QUERY_OPTS["in_porttree"]): if not 'O' in pkgstr.location: continue - print(pkgstr) + pp.uprint(pkgstr) if QUERY_OPTS["include_mask_reason"]: ms_int, ms_orig = pkgstr.format_mask_status() @@ -217,9 +217,9 @@ def main(input_args): status = ', '.join(ms_orig) explanation = mask_reason[0] mask_location = mask_reason[1] - print(" * Masked by %r" % status) - print(" * %s:" % mask_location) - print('\n'.join( + pp.uprint(" * Masked by %r" % status) + pp.uprint(" * %s:" % mask_location) + pp.uprint('\n'.join( [' * %s' % line.lstrip(' #') for line in explanation.splitlines()] )) diff --git a/pym/gentoolkit/equery/meta.py b/pym/gentoolkit/equery/meta.py index 210a2b3..eb63102 100644 --- a/pym/gentoolkit/equery/meta.py +++ b/pym/gentoolkit/equery/meta.py @@ -15,13 +15,11 @@ __docformat__ = 'epytext' # ======= import re +import os import sys -import codecs from getopt import gnu_getopt, GetoptError from functools import partial -from portage import os - import gentoolkit.pprinter as pp from gentoolkit import errors from gentoolkit import keyword @@ -219,7 +217,7 @@ def format_keywords(keywords): result = [] - for kw in sorted(keywords, cmp=keyword.compare_strs): + for kw in sorted(keywords, key=keyword.Keyword): if kw.startswith('-'): # arch masked kw = pp.keyword(kw, stable=False, hard_masked=True) @@ -251,15 +249,9 @@ def format_keywords_line(pkg, fmtd_keywords, slot, verstr_len): def call_format_functions(best_match, matches): """Call information gathering functions and display the results.""" - if hasattr(sys.stdout, "buffer"): - utf8_stdout = codecs.getwriter("utf-8")(sys.stdout.buffer) - else: - utf8_stdout = codecs.getwriter("utf-8")(sys.stdout) - uprint = partial(print, file=utf8_stdout) - if CONFIG['verbose']: repo = best_match.repo_name() - uprint(" * %s [%s]" % (pp.cpv(best_match.cp), pp.section(repo))) + pp.uprint(" * %s [%s]" % (pp.cpv(best_match.cp), pp.section(repo))) got_opts = False if any(QUERY_OPTS.values()): @@ -277,7 +269,7 @@ def call_format_functions(best_match, matches): print_sequence(format_list(herds)) else: for herd in herds: - uprint(format_line(herd, "Herd: ", " " * 13)) + pp.uprint(format_line(herd, "Herd: ", " " * 13)) if QUERY_OPTS["maintainer"] or not got_opts: maints = format_maintainers(best_match.metadata.maintainers()) @@ -285,10 +277,10 @@ def call_format_functions(best_match, matches): print_sequence(format_list(maints)) else: if not maints: - uprint(format_line([], "Maintainer: ", " " * 13)) + pp.uprint(format_line([], "Maintainer: ", " " * 13)) else: for maint in maints: - uprint(format_line(maint, "Maintainer: ", " " * 13)) + pp.uprint(format_line(maint, "Maintainer: ", " " * 13)) if QUERY_OPTS["upstream"] or not got_opts: upstream = format_upstream(best_match.metadata.upstream()) @@ -296,11 +288,11 @@ def call_format_functions(best_match, matches): upstream = format_list(upstream) else: upstream = format_list(upstream, "Upstream: ", " " * 13) - print_sequence(upstream, file = utf8_stdout) + print_sequence(upstream) if not got_opts: pkg_loc = best_match.package_path() - uprint(format_line(pkg_loc, "Location: ", " " * 13)) + pp.uprint(format_line(pkg_loc, "Location: ", " " * 13)) if QUERY_OPTS["keywords"] or not got_opts: # Get {: [u'ia64', u'm68k', ...], ...} @@ -314,18 +306,18 @@ def call_format_functions(best_match, matches): match, fmtd_keywords, slot, verstr_len ) if QUERY_OPTS["keywords"]: - uprint(keywords_line) + pp.uprint(keywords_line) else: indent = " " * (16 + verstr_len) - uprint(format_line(keywords_line, "Keywords: ", indent)) + pp.uprint(format_line(keywords_line, "Keywords: ", indent)) if QUERY_OPTS["description"]: desc = best_match.metadata.descriptions() - print_sequence(format_list(desc), file = utf8_stdout) + print_sequence(format_list(desc)) if QUERY_OPTS["useflags"]: useflags = format_useflags(best_match.metadata.use()) - print_sequence(format_list(useflags), file = utf8_stdout) + print_sequence(format_list(useflags)) if QUERY_OPTS["xml"]: print_file(os.path.join(best_match.package_path(), 'metadata.xml')) diff --git a/pym/gentoolkit/equery/size.py b/pym/gentoolkit/equery/size.py index 27aa8ec..4151767 100644 --- a/pym/gentoolkit/equery/size.py +++ b/pym/gentoolkit/equery/size.py @@ -82,7 +82,7 @@ def display_size(match_set): size, files, uncounted = pkg.size() if CONFIG['verbose']: - print(" * %s" % pp.cpv(str(pkg.cpv))) + pp.uprint(" * %s" % pp.cpv(str(pkg.cpv))) print("Total files : %s".rjust(25) % pp.number(str(files))) if uncounted: @@ -97,7 +97,7 @@ def display_size(match_set): print("Total size : %s".rjust(25) % size_str) else: info = "%s: total(%d), inaccessible(%d), size(%s)" - print(info % (str(pkg.cpv), files, uncounted, size)) + pp.uprint(info % (str(pkg.cpv), files, uncounted, size)) def format_bytes(bytes_, precision=2): diff --git a/pym/gentoolkit/equery/uses.py b/pym/gentoolkit/equery/uses.py index 181f219..4eba500 100644 --- a/pym/gentoolkit/equery/uses.py +++ b/pym/gentoolkit/equery/uses.py @@ -14,12 +14,13 @@ __docformat__ = 'epytext' # Imports # ======= +import os import sys from functools import partial from getopt import gnu_getopt, GetoptError from glob import glob -from portage import os, settings +from portage import settings import gentoolkit.pprinter as pp from gentoolkit import errors @@ -97,22 +98,22 @@ def display_useflags(output): restrict = "(%s %s)" % (pp.emph("Restricted to"), pp.cpv(restrict)) twrap.initial_indent = flag_name - print(twrap.fill(restrict)) + pp.uprint(twrap.fill(restrict)) if desc: twrap.initial_indent = twrap.subsequent_indent - print(twrap.fill(desc)) + pp.uprint(twrap.fill(desc)) else: print(" : ") else: if desc: twrap.initial_indent = flag_name desc = twrap.fill(desc) - print(desc) + pp.uprint(desc) else: twrap.initial_indent = flag_name print(twrap.fill("")) else: - print(markers[in_makeconf] + flag) + pp.uprint(markers[in_makeconf] + flag) def get_global_useflags(): diff --git a/pym/gentoolkit/equery/which.py b/pym/gentoolkit/equery/which.py index 104d057..5259d46 100644 --- a/pym/gentoolkit/equery/which.py +++ b/pym/gentoolkit/equery/which.py @@ -16,10 +16,10 @@ __docformat__ = 'epytext' # Imports # ======= +import os import sys from getopt import gnu_getopt, GetoptError -from portage import os import gentoolkit.pprinter as pp from gentoolkit import errors @@ -96,7 +96,7 @@ def main(input_args): pkg = sorted(matches).pop() ebuild_path = pkg.ebuild_path() if ebuild_path: - print(os.path.normpath(ebuild_path)) + pp.uprint(os.path.normpath(ebuild_path)) else: sys.stderr.write( pp.warn("No ebuilds to satisfy %s" % pkg.cpv) diff --git a/pym/gentoolkit/formatters.py b/pym/gentoolkit/formatters.py index f79fa72..413a1c8 100644 --- a/pym/gentoolkit/formatters.py +++ b/pym/gentoolkit/formatters.py @@ -10,8 +10,6 @@ import errno import sys import time -from portage import os - import gentoolkit from gentoolkit.textwrap_ import TextWrapper import gentoolkit.pprinter as pp diff --git a/pym/gentoolkit/glsa/__init__.py b/pym/gentoolkit/glsa/__init__.py index ab8dcdd..425faf9 100644 --- a/pym/gentoolkit/glsa/__init__.py +++ b/pym/gentoolkit/glsa/__init__.py @@ -17,6 +17,7 @@ __author__ = "Marius Mauch " import sys +import os try: from urllib import urlopen except ImportError: @@ -38,7 +39,6 @@ except ImportError: sys.path.insert(0, "/usr/lib/portage/pym") import portage -from portage import os # Note: the space for rgt and rlt is important !! opMapping = {"le": "<=", "lt": "<", "eq": "=", "gt": ">", "ge": ">=", diff --git a/pym/gentoolkit/helpers.py b/pym/gentoolkit/helpers.py index 6888619..c1c6788 100644 --- a/pym/gentoolkit/helpers.py +++ b/pym/gentoolkit/helpers.py @@ -10,8 +10,6 @@ the query module, where they are called as: Query('portage').find_*(). """ -from __future__ import print_function - __all__ = ( 'ChangeLog', 'FileOwner', @@ -19,7 +17,6 @@ __all__ = ( 'get_installed_cpvs', 'get_uninstalled_cpvs', 'uniqify', - 'walk' ) __docformat__ = 'epytext' @@ -27,14 +24,13 @@ __docformat__ = 'epytext' # Imports # ======= +import os import sys import re import codecs from functools import partial from itertools import chain -from portage import os, _unicode_decode, _encodings - from gentoolkit import pprinter as pp from gentoolkit import errors from gentoolkit.atom import Atom @@ -437,20 +433,16 @@ def get_installed_cpvs(predicate=None): def print_file(path): """Display the contents of a file.""" - out = sys.stdout - if hasattr(out, "buffer"): - out = out.buffer - with open(path, "rb") as open_file: lines = open_file.read() - print(lines.strip(), file = out) + pp.uprint(lines.strip()) -def print_sequence(seq, file = sys.stdout): +def print_sequence(seq): """Print every item of a sequence.""" for item in seq: - print(item, file = file) + pp.uprint(item) def uniqify(seq, preserve_order=True): @@ -464,20 +456,4 @@ def uniqify(seq, preserve_order=True): return result - -def walk(top, topdown = True, onerror = None, followlinks = False): - """Variant of os.walk that always returns unicode filenames""" - for root, dirs, files in os.walk(top, topdown, onerror, followlinks): - root = _unicode_decode(root, _encodings["fs"], errors = "strict") - dirs = [ - _unicode_decode(x, _encodings["fs"], errors = "strict") - for x in dirs - ] - files = [ - _unicode_decode(x, _encodings["fs"], errors = "strict") - for x in files - ] - # XXX: in contrast with os.walk we ignore modifications to dirs here - yield root, dirs, files - # vim: set ts=4 sw=4 tw=79: diff --git a/pym/gentoolkit/keyword.py b/pym/gentoolkit/keyword.py index d555e7c..3260bf0 100644 --- a/pym/gentoolkit/keyword.py +++ b/pym/gentoolkit/keyword.py @@ -30,6 +30,35 @@ class Keyword(object): def __init__(self, keyword): self.keyword = keyword + arch, sep, os = keyword.partition('-') + self.arch = arch + self.os = os + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return False + return self.keyword == other.keyword + + def __ne__(self, other): + return not self == other + + def __lt__(self, other): + if not isinstance(other, self.__class__): + raise TypeError("other isn't of %s type, is %s" % ( + self.__class__, other.__class__) + ) + if self.os < other.os: + return True + return self.arch < other.arch + + def __le__(self, other): + return self == other or self < other + + def __gt__(self, other): + return not self <= other + + def __ge__(self, other): + return self == other or self > other def __str__(self): return self.keyword @@ -55,9 +84,11 @@ def compare_strs(kw1, kw2): kw2_arch, sep, kw2_os = kw2.partition('-') if kw1_arch != kw2_arch: if kw1_os != kw2_os: - return cmp(kw1_os, kw2_os) - return cmp(kw1_arch, kw2_arch) - return cmp(kw1_os, kw2_os) + return -1 if kw1_os < kw2_os else 1 + return -1 if kw1_arch < kw2_arch else 1 + if kw1_os == kw2_os: + return 0 + return -1 if kw1_os < kw2_os else 1 def reduce_keywords(keywords): diff --git a/pym/gentoolkit/metadata.py b/pym/gentoolkit/metadata.py index 730d993..d9ff678 100644 --- a/pym/gentoolkit/metadata.py +++ b/pym/gentoolkit/metadata.py @@ -43,10 +43,11 @@ __docformat__ = 'epytext' # Imports # ======= +import os import re import xml.etree.cElementTree as etree -from portage import os, settings +from portage import settings # ======= # Classes diff --git a/pym/gentoolkit/package.py b/pym/gentoolkit/package.py index 9c11275..169097f 100644 --- a/pym/gentoolkit/package.py +++ b/pym/gentoolkit/package.py @@ -43,10 +43,11 @@ FORMAT_TMPL_VARS = ( # Imports # ======= +import os from string import Template import portage -from portage import os, settings +from portage import settings from portage.util import LazyItemsDict import gentoolkit.pprinter as pp diff --git a/pym/gentoolkit/pprinter.py b/pym/gentoolkit/pprinter.py index 2c60299..7ab60dc 100644 --- a/pym/gentoolkit/pprinter.py +++ b/pym/gentoolkit/pprinter.py @@ -35,6 +35,7 @@ __all__ = ( # ======= import sys +import locale import portage.output as output from portage import archlist @@ -146,4 +147,39 @@ def warn(string): """Returns a warning string.""" return "!!! " + string + "\n" +try: + unicode +except NameError: + unicode = str + +def uprint(*args, **kw): + """Replacement for the builtin print function. + + This version gracefully handles characters not representable in the + user's current locale (through the errors='replace' handler). + + @see: >>> help(print) + """ + + sep = kw.pop('sep', ' ') + end = kw.pop('end', '\n') + file = kw.pop("file", sys.stdout) + if kw: + raise TypeError("got invalid keyword arguments: {0}".format(list(kw))) + file = getattr(file, 'buffer', file) + + encoding = locale.getpreferredencoding() + + def encoded_args(): + for arg in args: + if isinstance(arg, bytes): + yield arg + else: + yield unicode(arg).encode(encoding, 'replace') + + sep = sep.encode(encoding, 'replace') + end = end.encode(encoding, 'replace') + text = sep.join(encoded_args()) + file.write(text + end) + # vim: set ts=4 sw=4 tw=79: diff --git a/pym/gentoolkit/query.py b/pym/gentoolkit/query.py index 764f82b..c18d19e 100644 --- a/pym/gentoolkit/query.py +++ b/pym/gentoolkit/query.py @@ -75,23 +75,27 @@ class Query(object): def print_summary(self): """Print a summary of the query.""" - cpv = CPV(self.query) - cat, pkg = cpv.category, cpv.name + cpv.fullversion - if cat and not self.is_regex: - cat_str = "in %s " % pp.emph(cat.lstrip('><=~!')) - else: + if self.query_type == "set": cat_str = "" - - if self.is_regex: pkg_str = pp.emph(self.query) else: - pkg_str = pp.emph(pkg) + cpv = CPV(self.query) + cat, pkg = cpv.category, cpv.name + cpv.fullversion + if cat and not self.is_regex: + cat_str = "in %s " % pp.emph(cat.lstrip('><=~!')) + else: + cat_str = "" + + if self.is_regex: + pkg_str = pp.emph(self.query) + else: + pkg_str = pp.emph(pkg) repo = '' if self.repo_filter is not None: repo = ' %s' % pp.section(self.repo_filter) - print(" * Searching%s for %s %s..." % (repo, pkg_str, cat_str)) + pp.uprint(" * Searching%s for %s %s..." % (repo, pkg_str, cat_str)) def smart_find( self, @@ -193,7 +197,7 @@ class Query(object): # catch the ambiguous package Exception except portage.exception.AmbiguousPackageName as err: matches = [] - for pkgkey in err[0]: + for pkgkey in err.args[0]: matches.extend(VARDB.match(pkgkey)) except portage.exception.InvalidAtom as err: raise errors.GentoolkitInvalidAtom(err) diff --git a/pym/gentoolkit/test/eclean/creator.py b/pym/gentoolkit/test/eclean/creator.py index 8ab8739..db0eba4 100644 --- a/pym/gentoolkit/test/eclean/creator.py +++ b/pym/gentoolkit/test/eclean/creator.py @@ -6,10 +6,6 @@ # # $Header$ -__version__= "0.0.1" -__author__ = "Brian Dolbec" -__email__ = "brian.dolbec@gmail.com" - from __future__ import with_statement from __future__ import print_function @@ -20,10 +16,13 @@ import random import gentoolkit.pprinter as pp +__version__= "0.0.1" +__author__ = "Brian Dolbec" +__email__ = "brian.dolbec@gmail.com" -dir_mode = 0774 -file_mode = 0644 +dir_mode = int('0774', 8) +file_mode = int('0644', 8) def make_dir(path): @@ -34,9 +33,9 @@ def make_dir(path): Will Error and exit if the target dir already exits""" try: os.makedirs(path, dir_mode) - except EnvironmentError, er: + except EnvironmentError as er: print( pp.error("Error creating path:%s" %path), file=sys.stderr) - print( pp.error("Error: %s" %str(er), file=sys.stderr) + print( pp.error("Error: %s" %str(er), file=sys.stderr)) sys.exit(1) @@ -60,7 +59,7 @@ def make_dist(path, files, clean_dict=None): if file_ not in clean_dict: # it is included in a multifile target continue - elif clean_dict[file_] = []: + elif clean_dict[file_] == []: clean_dict[file_] = filepath else: file_list = clean_dict[file_] @@ -174,7 +173,7 @@ class TestDirCreation(object): 'xine-lib-1.1.15-textrel-fix.patch': [], 'xine-lib-1.1.16.3.tar.bz2': [], 'xorg-server-1.5.3.tar.bz2': ['xorg-server-1.5.3.tar.bz2', - 'xorg-server-1.5.3-gentoo-patches-08.tar.bz2'] + 'xorg-server-1.5.3-gentoo-patches-08.tar.bz2'], 'symlink-test-1.2.3.tar.bz2': distfile_symlink } @@ -234,10 +233,10 @@ class TestDirCreation(object): # add some symlinks to it path = os.path.join(self.options['target_path'], 'distfiles') make_symlinks(path, distfile_symlink, - dist_clean['symlink-test-1.2.3.tar.bz2']): + dist_clean['symlink-test-1.2.3.tar.bz2']) # create the packages dir and populate it path = os.path.join(self.options['target_path'], 'packages') - make_pkgs(path, self.package_dict, self.pkg_clean): + make_pkgs(path, self.package_dict, self.pkg_clean) self.targets_init = True - def get_ + #def get_ diff --git a/pym/gentoolkit/test/eclean/distsupport.py b/pym/gentoolkit/test/eclean/distsupport.py new file mode 100644 index 0000000..c9bb944 --- /dev/null +++ b/pym/gentoolkit/test/eclean/distsupport.py @@ -0,0 +1,174 @@ +# Copyright(c) 2009, Gentoo Foundation +# Copyright 2010 Brian Dolbec +# +# License: GPL2/BSD + +# $Header$ + + +from __future__ import print_function + +import os +import unittest +from tempfile import NamedTemporaryFile, mkdtemp +import subprocess + + + +dir_mode = 0774 + +CPVS = [u'sys-auth/consolekit-0.4.1', u'sys-apps/devicekit-power-014', + u'media-libs/sdl-pango-0.1.2', u'sys-apps/help2man-1.37.1', + u'app-emulation/emul-linux-x86-baselibs-20100220' +] + +PROPS = { + u'sys-apps/devicekit-power-014': {u'SRC_URI': + u'http://hal.freedesktop.org/releases/DeviceKit-power-014.tar.gz', + u"RESTRICT": u''}, + u'sys-apps/help2man-1.37.1': {u"SRC_URI": u'mirror://gnu/help2man/help2man-1.37.1.tar.gz', + u"RESTRICT": u''}, + u'sys-auth/consolekit-0.4.1': { u"SRC_URI": + u'http://www.freedesktop.org/software/ConsoleKit/dist/ConsoleKit-0.4.1.tar.bz2', + u"RESTRICT": u''}, + u'app-emulation/emul-linux-x86-baselibs-20100220': { + u"SRC_URI": u'mirror://gentoo/emul-linux-x86-baselibs-20100220.tar.gz', + u"RESTRICT": u'strip'}, + u'media-libs/sdl-pango-0.1.2': { + u"SRC_URI": u'mirror://sourceforge/sdlpango/SDL_Pango-0.1.2.tar.gz http://zarb.org/~gc/t/SDL_Pango-0.1.2-API-adds.patch', + u"RESTRICT": u''} +} + +FILES = [ + u'DeviceKit-power-014.tar.gz', + u'help2man-1.37.1.tar.gz', + u'ConsoleKit-0.4.1.tar.bz2', + u'emul-linux-x86-baselibs-20100220.tar.gz', + u'SDL_Pango-0.1.2.tar.gz', + u'SDL_Pango-0.1.2-API-adds.patch' +] + + +class Dbapi(object): + """Fake portage dbapi class used to return + pre-determined test data in place of a live system + + @param cp_all: list of cat/pkg's to use for testing + eg: ['app-portage/gentoolkit', 'app-portage/porthole',...] + @param cpv_all: list of cat/pkg-ver's to use for testing. + @param props: dictionary of ebuild properties to use for testing. + eg: {'cpv': {"SRC_URI": 'http://...', "RESTRICT": restriction},} + @param cp_list: ????????? + """ + + def __init__(self, cp_all=None, cpv_all=None, props=None, + cp_list=None, name=None): + self._cp_all = cp_all + self._cpv_all = cpv_all + self._props = props + self._cp_list = cp_list + self.name = name + #print(self.name, "DBAPI: cpv_all=") + #print(self._cpv_all) + #print(self.name, "DBAPI: props=") + #print(self._props) + + def cp_all(self): + return self._cp_all[:] + + def cp_list(self, package): + #need to determine the data to return + # and gather some from a live system to use for testing + pass + + def cpv_all(self): + return self._cpv_all + + def cpv_exists(self, cpv): + return cpv in self._cpv_all + + def aux_get(self, cpv, prop_list): + """only need stubs for ["SRC_URI","RESTRICT"] + """ + #print("FAKE DBAPI", cpv, prop_list) + props = [] + for prop in prop_list: + if cpv in self._props: + props.append(self._props[cpv][prop]) + else: + raise KeyError, self.name + return props + + +class OutputSimulator(object): + """Simple output accumulator used for testing. + Simulates eclean.output.OutputControl class """ + + def __init__(self, callback): + self.callback = callback + + def set_data(self, data): + """sets the data for the progress_controller to return + for the test being performed""" + self.data = data + + def einfo(self, message=""): + self.callback('einfo', message) + + def eprompt(self, message): + self.callback('eprompt', message) + + def prettySize(self, size, justify=False, color=None): + self.callback('prettySize', size) + + def yesNoAllPrompt(self, message="Dummy"): + self.callback('yesNoAllPrompt', message) + + def progress_controller(self, size, key, clean_list, file_type): + self.callback('progress_controller', self.data) + return self.data + + def total(self, mode, size, num_files, verb, action): + pass + + def list_pkgs(self, pkgs): + self.callback('list_pkgs', pkgs) + + +class TestDisfiles(object): + + def __init__(self): + self.workdir = None + self.target_file = None + self.target_symlink = None + self.test_filepaths = None + + def setUp(self): + # create the dist dir + self.tmpdir = mkdtemp() + #print("New tmpdir =", self.tmpdir) + os.chmod(self.tmpdir, dir_mode) + self.workdir = os.path.join(self.tmpdir, 'distfiles') + dir = os.path.dirname(os.path.abspath(__file__)) + file = os.path.join(dir,"testdistfiles.tar.gz") + command = "tar -xpf %s -C %s" %(file, self.tmpdir) + retcode = subprocess.call(command, shell=True) + # create a symlink as part of the test files + #print() + self.target_symlink = "symlink-1.0.0.tar.gz" + os.symlink(file, os.path.join(self.workdir, self.target_symlink)) + self.files = FILES[:] + self.files.append(self.target_symlink) + self.test_filepaths = [] + for file in self.files: + self.test_filepaths.append(os.path.join(self.workdir, file)) + + def tearDown(self): + for file in self.test_filepaths: + os.unlink(file) + #print("deleting workdir =", self.workdir) + os.rmdir(self.workdir) + #print("deleting tmpdir =", self.tmpdir) + os.rmdir(self.tmpdir) + + diff --git a/pym/gentoolkit/test/eclean/test_clean.py b/pym/gentoolkit/test/eclean/test_clean.py index 82a9841..25a760a 100644 --- a/pym/gentoolkit/test/eclean/test_clean.py +++ b/pym/gentoolkit/test/eclean/test_clean.py @@ -6,7 +6,7 @@ # # $Header$ -from __future__ import with_statement +from __future__ import print_function __version__= "0.0.1" __author__ = "Brian Dolbec" @@ -19,7 +19,10 @@ import os import sys import gentoolkit.pprinter as pp -from test import test_support +try: + from test import test_support +except ImportError: + from test import support as test_support from gentoolkit.eclean.clean import CleanUp @@ -94,23 +97,23 @@ class Controllers(object): def useage(): """output run options""" - print "Useage: test_clean [OPTONS] path=test-dir" - print " where test-dir is the location to create and populate" - print "the testing distfiles and packages directories." - print "All tests in this module test only the clean.py module functions" - print - print "OPTIONS:" - print " -a, --all run all tests" - print " -c, --clean clean up any previous test dirs & files" - print " -D, --distfiles run the distfiles cleaning test" - print " -k, --keep-dirs keep the test directories and files after the test" - print " -p, --pretend run the test in pretend mode only" - print " -P, --packages run the packages cleaning test" - print " -S, --symlinks run the symlinks test" - print " --path the location to create the temporary distfiles" - print " and packages directories that will be test cleaned" - print " --version test module version" - print + print("Useage: test_clean [OPTONS] path=test-dir") + print(" where test-dir is the location to create and populate") + print("the testing distfiles and packages directories.") + print("All tests in this module test only the clean.py module functions") + print() + print("OPTIONS:") + print(" -a, --all run all tests") + print(" -c, --clean clean up any previous test dirs & files") + print(" -D, --distfiles run the distfiles cleaning test") + print(" -k, --keep-dirs keep the test directories and files after the test") + print(" -p, --pretend run the test in pretend mode only") + print(" -P, --packages run the packages cleaning test") + print(" -S, --symlinks run the symlinks test") + print(" --path the location to create the temporary distfiles") + print(" and packages directories that will be test cleaned") + print(" --version test module version") + print() def parse_opts(): @@ -123,8 +126,8 @@ def parse_opts(): "pretend", "symlinks", "keep-dirs", "clean"]) #print opts #print args - except GetoptError, e: - print >> sys.stderr, e.msg + except GetoptError as e: + print(e.msg, file=sys.stderr) usage() sys.exit(1) @@ -142,7 +145,7 @@ if __name__ == "__main__": try: main(True) except KeyboardInterrupt: - print "Aborted." + print("Aborted.") sys.exit(130) sys.exit(0) diff --git a/pym/gentoolkit/test/eclean/test_search.py b/pym/gentoolkit/test/eclean/test_search.py index 1970784..e399fa1 100644 --- a/pym/gentoolkit/test/eclean/test_search.py +++ b/pym/gentoolkit/test/eclean/test_search.py @@ -1,5 +1,4 @@ # Copyright(c) 2009, Gentoo Foundation -# Copyright: 2006-2008 Brian Harring # Copyright 2010 Brian Dolbec # # License: GPL2/BSD @@ -10,91 +9,323 @@ from __future__ import print_function +from tempfile import NamedTemporaryFile, mkdtemp import unittest -from test import test_support +import re -from gentoolkit.eclean.search import * +try: + from test import test_support +except ImportError: + from test import support as test_support -class Dbapi(object): - """Fake portage dbapi class used to return - pre-determined test data in place of a live system +from gentoolkit.test.eclean.distsupport import * +from gentoolkit.eclean.search import DistfilesSearch - @param cp_all: list of cat/pkg's to use for testing - eg: ['app-portage/gentoolkit', 'app-portage/porthole',...] - @param cpv_all: list of cat/pkg-ver's to use for testing. - @param props: dictionary of ebuild properties to use for testing. - eg: {'cpv': {"SRC_URI": 'http://...', "RESTRICT": restriction},} - @param cp_list: ????????? + +"""Tests for eclean's distfiles search functions.""" + + +class DistLimits(DistfilesSearch): + """subclass the DistfilesSearch class in order to override a number of + functions to isolate & test""" + + def __init__(self, + output=lambda x: None, + portdb=None, + vardb=None, + ): + DistfilesSearch.__init__(self, output, portdb, vardb) + self.data = None + + def set_data(self, data): + """sets the data for the functions to return for + the test being performed""" + self.data = data + + +class TestCheckLimits(unittest.TestCase): + """Test the eclean.search.DistfilesSearch._check_limits() group. + + it will test [ _get_default_checks(), _check_limits(), + _isreg_check_(), _size_check_(), _time_check_(), _filenames_check_()] """ - def __init__(self, cp_all=[], cpv_all=[], props={}, cp_list=[]): - self._cp_all = cp_all - self._cpv_all = cpv_all - self._props = props - self._cp_list = cp_list + test_excludes = { + 'blank': {}, + 'filenames': { + 'filenames': {'help2man-1.37.1.tar.gz': re.compile('help2man-1.37.1.tar.gz')} + } + } + + def setUp(self): + self.testdata = [ + # test is_reg_limit alone, will give a base clean_me + { 'test': 'is_reg_limit', + 'params': (0, 0, self.test_excludes['blank']), + 'results': FILES[:], + 'output': [" - skipping size limit check", + " - skipping time limit check", + " - skipping exclude filenames check" + ] + }, + # test size_limit trip + { 'test': 'size_limit', + 'params': (1024000, 0, self.test_excludes['blank']), + 'results': FILES[:3] + FILES[4:], + 'output': [ + " - skipping time limit check", + " - skipping exclude filenames check" + ] + }, + # test time_limit trip + { 'test': 'time_limit', + 'params': (0,1112671872, self.test_excludes['blank']), + 'results': [FILES[4]], # + FILES[5:], + 'output': [" - skipping size limit check", + " - skipping exclude filenames check" + ] + }, + # test filenames_limit trip + { 'test': 'filenames_limit', + 'params': (0, 0, self.test_excludes['filenames']), + 'results': FILES[:1] + FILES[2:], + 'output': [" - skipping size limit check", + " - skipping time limit check", + ] + } + ] + + self.testwork = TestDisfiles() + self.testwork.setUp() + self.workdir = self.testwork.workdir + self.target_class = DistLimits() #DistCheckLimits() + self.output = OutputSimulator(self.callback) + self.target_class.output = self.output + self.callback_data = [] + self.test_index = 0 + + def tearDown(self): + self.testwork.tearDown() + #pass + + def get_test(self, num): + return self.testdata[num] + + def callback(self, id, data): + self.callback_data.append(data) + + def set_limits(self, test): + limit = {} + #set is_reg always to testdata[0] + t1 = self.testdata[0] + limit[t1['test']] = {} + name = test['test'] + limit[name] = {} + limits = test['limits'] + for i in range(6): + file = self.testwork.files[i] + limits = test['limits'] + limit[t1['test']][file] = t1['limits'][i] + if name != t1['test']: + limit[name][file] = limits[i] + return limit - def cp_all(self): - return self._cp_all[:] - def cp_list(self, package): - #need to determine the data to return - # and gather some from a live system to use for testing - pass + def test_check_limits(self): + """Testing DistfilesSearch._check_limits()""" + # pass in output=self.output.einfo + self.target_class.output = self.output.einfo + run_callbacks = [] + run_results = [] + print() + # run the tests + for i in range(4): + clean_me = {} + test = self.get_test(i) + #print("test =", test['test']) + if not test: + print("Error getting test data for index:", i) + #self.target_class.set_data(self.set_limits(test)) + size_chk, time_chk, exclude = test["params"] + checks = self.target_class._get_default_checks(size_chk, time_chk, exclude) + clean_me = self.target_class._check_limits(self.workdir, checks, clean_me) + results = sorted(clean_me) + run_results.append(results) + self.callback_data.sort() + run_callbacks.append(self.callback_data) + self.callback_data = [] + results = None - def cpv_all(self): - return self._cpv_all + # check results + for i in range(4): + test = self.get_test(i) + print("test =", test['test']) + if not test: + print("Error getting test data for index:", i) + test['results'].sort() + #print("actual=", run_results[i]) + #print("should-be=", test['results']) + self.failUnlessEqual(run_results[i], test["results"], + "/ntest_check_limits, test# %d, test=%s, diff=%s" + %(i, test['test'], str(set(run_results[i]).difference(test['results']))) + ) + test['output'].sort() + self.failUnlessEqual(run_callbacks[i], test['output']) - def cpv_exists(self, cpv): - return cpv in self._cpv_all - def aux_get(self, cpv, prop_list): - """only need stubs for ["SRC_URI","RESTRICT"] - """ - props = [] - for prop in prop_list: - props.append(self._props[cpv][prop]) +class TestFetchRestricted(unittest.TestCase): + """Tests eclean.search.DistfilesSearch._fetch_restricted and _unrestricted + functions + """ + + def setUp(self): + self.vardb = Dbapi(cp_all=[], cpv_all=CPVS, + props=PROPS, cp_list=[], name="FAKE VARDB") + self.portdb = Dbapi(cp_all=[], cpv_all=CPVS[:4], + props=self.get_props(CPVS[:4]), cp_list=[], name="FAKE PORTDB") + # set a fetch restricted pkg + self.portdb._props[CPVS[0]]["RESTRICT"] = u'fetch' + self.callback_data = [] + self.output = self.output = OutputSimulator(self.callback) + self.target_class = DistfilesSearch(self.output.einfo, self.portdb, self.vardb) + self.target_class.portdb = self.portdb + self.target_class.portdb = self.portdb + self.testdata = { + 'fetch_restricted1':{ + 'deprecated': + {u'app-emulation/emul-linux-x86-baselibs-20100220': u'mirror://gentoo/emul-linux-x86-baselibs-20100220.tar.gz' + }, + 'pkgs': + {u'sys-auth/consolekit-0.4.1': u'http://www.freedesktop.org/software/ConsoleKit/dist/ConsoleKit-0.4.1.tar.bz2' + }, + 'output': [ + u'!!! "Deprecation Warning: Installed package: app-emulation/emul-linux-x86-baselibs-20100220\n\tIs no longer in the tree or an installed overlay\n' + ] + }, + 'fetch_restricted2':{ + 'deprecated': + {u'app-emulation/emul-linux-x86-baselibs-20100220': u'mirror://gentoo/emul-linux-x86-baselibs-20100220.tar.gz' + }, + 'pkgs': + {u'sys-auth/consolekit-0.4.1': u'http://www.freedesktop.org/software/ConsoleKit/dist/ConsoleKit-0.4.1.tar.bz2' + }, + 'output': [ + u'!!! "Deprecation Warning: Installed package: app-emulation/emul-linux-x86-baselibs-20100220\n\tIs no longer in the tree or an installed overlay\n', + ' - Key Error looking up: app-portage/deprecated-pkg-1.0.0' + ] + }, + 'unrestricted1':{ + 'deprecated':{ + u'app-emulation/emul-linux-x86-baselibs-20100220': u'mirror://gentoo/emul-linux-x86-baselibs-20100220.tar.gz' + }, + 'pkgs': { + u'sys-apps/devicekit-power-014': u'http://hal.freedesktop.org/releases/DeviceKit-power-014.tar.gz', + u'sys-apps/help2man-1.37.1': u'mirror://gnu/help2man/help2man-1.37.1.tar.gz', + u'sys-auth/consolekit-0.4.1': u'http://www.freedesktop.org/software/ConsoleKit/dist/ConsoleKit-0.4.1.tar.bz2', + u'app-emulation/emul-linux-x86-baselibs-20100220': u'mirror://gentoo/emul-linux-x86-baselibs-20100220.tar.gz', + u'media-libs/sdl-pango-0.1.2': u'mirror://sourceforge/sdlpango/SDL_Pango-0.1.2.tar.gz http://zarb.org/~gc/t/SDL_Pango-0.1.2-API-adds.patch' + }, + 'output': [ + u'!!! "Deprecation Warning: Installed package: app-emulation/emul-linux-x86-baselibs-20100220\n\tIs no longer in the tree or an installed overlay\n', + ] + }, + 'unrestricted2':{ + 'deprecated':{ + u'app-emulation/emul-linux-x86-baselibs-20100220': u'mirror://gentoo/emul-linux-x86-baselibs-20100220.tar.gz' + }, + 'pkgs': { + u'sys-apps/devicekit-power-014': u'http://hal.freedesktop.org/releases/DeviceKit-power-014.tar.gz', + u'sys-apps/help2man-1.37.1': u'mirror://gnu/help2man/help2man-1.37.1.tar.gz', + u'sys-auth/consolekit-0.4.1': u'http://www.freedesktop.org/software/ConsoleKit/dist/ConsoleKit-0.4.1.tar.bz2', + u'app-emulation/emul-linux-x86-baselibs-20100220': u'mirror://gentoo/emul-linux-x86-baselibs-20100220.tar.gz', + u'media-libs/sdl-pango-0.1.2': u'mirror://sourceforge/sdlpango/SDL_Pango-0.1.2.tar.gz http://zarb.org/~gc/t/SDL_Pango-0.1.2-API-adds.patch' + }, + 'output': [ + u'!!! "Deprecation Warning: Installed package: app-emulation/emul-linux-x86-baselibs-20100220\n\tIs no longer in the tree or an installed overlay\n', + ' - Key Error looking up: app-portage/deprecated-pkg-1.0.0' + ] + } + } + + + + def get_props(self, cpvs): + props = {} + for cpv in cpvs: + props[cpv] = PROPS[cpv] return props + def callback(self, id, data): + self.callback_data.append(data) + + + def test__fetch_restricted(self): + pkgs, deprecated = self.target_class._fetch_restricted(None, CPVS) + self.results = { + 'fetch_restricted1': { + 'pkgs': pkgs, + 'deprecated': deprecated, + 'output': self.callback_data + } + } + + self.callback_data = [] + cpvs = CPVS[:] + cpvs.append('app-portage/deprecated-pkg-1.0.0') + pkgs, deprecated = self.target_class._fetch_restricted(None, cpvs) + self.results['fetch_restricted2'] = { + 'pkgs': pkgs, + 'deprecated': deprecated, + 'output': self.callback_data + } + + for key in sorted(self.results): + testdata = self.testdata[key] + results = self.results[key] + for item in sorted(testdata): + self.failUnlessEqual(sorted(testdata[item]), sorted(results[item]), + "\ntest_fetch_restricted: %s %s data does not match\nresult=" %(key, item) +\ + str(results[item]) + "\ntestdata=" + str(testdata[item])) + + + + def test_unrestricted(self): + pkgs, deprecated = self.target_class._unrestricted(None, CPVS) + self.results = { + 'unrestricted1': { + 'pkgs': pkgs, + 'deprecated': deprecated, + 'output': self.callback_data + } + } + self.callback_data = [] + cpvs = CPVS[:] + cpvs.append('app-portage/deprecated-pkg-1.0.0') + pkgs, deprecated = self.target_class._unrestricted(None, cpvs) + self.results['unrestricted2'] = { + 'pkgs': pkgs, + 'deprecated': deprecated, + 'output': self.callback_data + } + for key in sorted(self.results): + testdata = self.testdata[key] + results = self.results[key] + for item in sorted(testdata): + self.failUnlessEqual( sorted(testdata[item]), sorted(results[item]), + "\ntest_unrestricted: %s %s data does not match\nresult=" %(key, item) +\ + str(results[item]) + "\ntestdata=" + str(testdata[item])) -"""Tests for eclean's search modules.""" - -class TestFindDistfiles(unittest.TestCase): - uris = [ - u'/usr/portage/distfiles/xdg-utils-1.0.2.tgz', - u'/usr/portage/distfiles/readline60-003', - u'/usr/portage/distfiles/bash-completion-1.1.tar.bz2', - u'/usr/portage/distfiles/libgweather-2.26.2.1.tar.bz2', - u'/usr/portage/distfiles/libwnck-2.26.2.tar.bz2', - u'/usr/portage/distfiles/gnome-cups-manager-0.33.tar.bz2', - u'/usr/portage/distfiles/audiofile-0.2.6-constantise.patch.bz2', - u'/usr/portage/distfiles/vixie-cron-4.1-gentoo-r4.patch.bz2', - u'/usr/portage/distfiles/evince-2.26.2.tar.bz2', - u'/usr/portage/distfiles/lxml-2.2.2.tgz' - ] - filenames = [ - u'audiofile-0.2.6-constantise.patch.bz2', - u'bash-completion-1.1.tar.bz2', - u'evince-2.26.2.tar.bz2', - u'gnome-cups-manager-0.33.tar.bz2', - u'libgweather-2.26.2.1.tar.bz2', - u'libwnck-2.26.2.tar.bz2', - u'lxml-2.2.2.tgz', - u'readline60-003', - u'vixie-cron-4.1-gentoo-r4.patch.bz2', - u'xdg-utils-1.0.2.tgz' - ] - - def test_get_filenames_from_uris(self): - fns = sorted(get_filenames_from_uris(self.uris)) - print(fns) - for fn, fn2 in zip(self.filenames, fns): - self.failUnlessEqual(fn, fn2) def test_main(): - test_support.run_unittest(TestFindDistfiles) + + # Run tests + test_support.run_unittest(TestCheckLimits('test_check_limits')) + test_support.run_unittest( TestFetchRestricted('test__fetch_restricted')) + test_support.run_unittest( TestFetchRestricted('test_unrestricted')) + if __name__ == '__main__': test_main() diff --git a/pym/gentoolkit/test/test_helpers.py b/pym/gentoolkit/test/test_helpers.py index 6571f47..5bafaae 100644 --- a/pym/gentoolkit/test/test_helpers.py +++ b/pym/gentoolkit/test/test_helpers.py @@ -1,3 +1,4 @@ +import os import unittest import warnings from tempfile import NamedTemporaryFile, mktemp @@ -6,8 +7,6 @@ try: except ImportError: from test import support as test_support -from portage import os - from gentoolkit import helpers diff --git a/pym/gentoolkit/test/test_keyword.py b/pym/gentoolkit/test/test_keyword.py index 5418961..3e72e5f 100644 --- a/pym/gentoolkit/test/test_keyword.py +++ b/pym/gentoolkit/test/test_keyword.py @@ -1,3 +1,4 @@ +import sys import unittest import warnings from tempfile import NamedTemporaryFile @@ -6,9 +7,8 @@ try: except ImportError: from test import support as test_support -from portage import os - from gentoolkit import keyword +from gentoolkit.test import cmp class TestGentoolkitKeyword(unittest.TestCase): @@ -44,7 +44,9 @@ class TestGentoolkitKeyword(unittest.TestCase): '~amd64', '~ppc', '~x86', '~amd64-linux', '~x86-linux', '~ppc-macos', '~x86-macos', '~x86-solaris' ] - self.failUnlessEqual(sorted(kwds_presort, cmp=compare_strs), kwds_postsort) + if sys.hexversion < 0x3000000: + self.failUnlessEqual(sorted(kwds_presort, cmp=compare_strs), kwds_postsort) + self.failUnlessEqual(sorted(kwds_presort, key = keyword.Keyword), kwds_postsort) def test_main(): diff --git a/pym/gentoolkit/test/test_query.py b/pym/gentoolkit/test/test_query.py index 56f26e6..c020be1 100644 --- a/pym/gentoolkit/test/test_query.py +++ b/pym/gentoolkit/test/test_query.py @@ -6,8 +6,6 @@ try: except ImportError: from test import support as test_support -from portage import os - from gentoolkit import query from gentoolkit import errors diff --git a/pym/gentoolkit/test/test_syntax.py b/pym/gentoolkit/test/test_syntax.py index 77fa5dc..325034a 100644 --- a/pym/gentoolkit/test/test_syntax.py +++ b/pym/gentoolkit/test/test_syntax.py @@ -1,14 +1,12 @@ import unittest import py_compile -from portage import os +import os osp = os.path -from gentoolkit.helpers import walk - """Does a basic syntax check by compiling all modules. From Portage.""" -pym_dirs = walk(osp.dirname(osp.dirname(osp.dirname(__file__)))) +pym_dirs = os.walk(osp.dirname(osp.dirname(osp.dirname(__file__)))) blacklist_dirs = frozenset(('.svn', 'test')) class TestForSyntaxErrors(unittest.TestCase): diff --git a/setup.py b/setup.py index 217d526..dc84037 100755 --- a/setup.py +++ b/setup.py @@ -12,7 +12,6 @@ from glob import glob import os sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'pym')) -from gentoolkit.helpers import walk __version__ = os.getenv('VERSION', default='9999') @@ -91,7 +90,7 @@ def load_test(): packages = [ str('.'.join(root.split(os.sep)[1:])) - for root, dirs, files in walk('pym/gentoolkit') + for root, dirs, files in os.walk('pym/gentoolkit') if '__init__.py' in files ]