root/galaxy-central/eggs/nose-0.11.1-py2.6.egg/nose/config.py @ 3

リビジョン 3, 21.1 KB (コミッタ: kohda, 14 年 前)

Install Unix tools  http://hannonlab.cshl.edu/galaxy_unix_tools/galaxy.html

行番号 
1import logging
2import optparse
3import os
4import re
5import sys
6import ConfigParser
7from optparse import OptionParser
8from nose.util import absdir, tolist
9from nose.plugins.manager import NoPlugins
10from warnings import warn
11
12log = logging.getLogger(__name__)
13
14# not allowed in config files
15option_blacklist = ['help', 'verbose']
16
17config_files = [
18    # Linux users will prefer this
19    "~/.noserc",
20    # Windows users will prefer this
21    "~/nose.cfg"
22    ]
23
24# plaforms on which the exe check defaults to off
25# Windows and IronPython
26exe_allowed_platforms = ('win32', 'cli')
27
28
29class NoSuchOptionError(Exception):
30    def __init__(self, name):
31        Exception.__init__(self, name)
32        self.name = name
33
34
35class ConfigError(Exception):
36    pass
37
38
39class ConfiguredDefaultsOptionParser(object):
40    """
41    Handler for options from commandline and config files.
42    """
43    def __init__(self, parser, config_section, error=None, file_error=None):
44        self._parser = parser
45        self._config_section = config_section
46        if error is None:
47            error = self._parser.error
48        self._error = error
49        if file_error is None:
50            file_error = lambda msg, **kw: error(msg)
51        self._file_error = file_error
52
53    def _configTuples(self, cfg, filename):
54        config = []
55        if self._config_section in cfg.sections():
56            for name, value in cfg.items(self._config_section):
57                config.append((name, value, filename))
58        return config
59
60    def _readFromFilenames(self, filenames):
61        config = []
62        for filename in filenames:
63            cfg = ConfigParser.RawConfigParser()
64            try:
65                cfg.read(filename)
66            except ConfigParser.Error, exc:
67                raise ConfigError("Error reading config file %r: %s" %
68                                  (filename, str(exc)))
69            config.extend(self._configTuples(cfg, filename))
70        return config
71
72    def _readFromFileObject(self, fh):
73        cfg = ConfigParser.RawConfigParser()
74        try:
75            filename = fh.name
76        except AttributeError:
77            filename = '<???>'
78        try:
79            cfg.readfp(fh)
80        except ConfigParser.Error, exc:
81            raise ConfigError("Error reading config file %r: %s" %
82                              (filename, str(exc)))
83        return self._configTuples(cfg, filename)
84
85    def _readConfiguration(self, config_files):
86        try:
87            config_files.readline
88        except AttributeError:
89            filename_or_filenames = config_files
90            if isinstance(filename_or_filenames, basestring):
91                filenames = [filename_or_filenames]
92            else:
93                filenames = filename_or_filenames
94            config = self._readFromFilenames(filenames)
95        else:
96            fh = config_files
97            config = self._readFromFileObject(fh)
98        return config
99
100    def _processConfigValue(self, name, value, values, parser):
101        opt_str = '--' + name
102        option = parser.get_option(opt_str)
103        if option is None:
104            raise NoSuchOptionError(name)
105        else:
106            option.process(opt_str, value, values, parser)
107
108    def _applyConfigurationToValues(self, parser, config, values):
109        for name, value, filename in config:
110            if name in option_blacklist:
111                continue
112            try:
113                self._processConfigValue(name, value, values, parser)
114            except NoSuchOptionError, exc:
115                self._file_error(
116                    "Error reading config file %r: "
117                    "no such option %r" % (filename, exc.name),
118                    name=name, filename=filename)
119            except optparse.OptionValueError, exc:
120                msg = str(exc).replace('--' + name, repr(name), 1)
121                self._file_error("Error reading config file %r: "
122                                 "%s" % (filename, msg),
123                                 name=name, filename=filename)
124
125    def parseArgsAndConfigFiles(self, args, config_files):
126        values = self._parser.get_default_values()
127        try:
128            config = self._readConfiguration(config_files)
129        except ConfigError, exc:
130            self._error(str(exc))
131        else:
132            self._applyConfigurationToValues(self._parser, config, values)
133        return self._parser.parse_args(args, values)
134
135
136class Config(object):
137    """nose configuration.
138
139    Instances of Config are used throughout nose to configure
140    behavior, including plugin lists. Here are the default values for
141    all config keys::
142
143      self.env = env = kw.pop('env', {})
144      self.args = ()
145      self.testMatch = re.compile(r'(?:^|[\\b_\\.%s-])[Tt]est' % os.sep)
146      self.addPaths = not env.get('NOSE_NOPATH', False)
147      self.configSection = 'nosetests'
148      self.debug = env.get('NOSE_DEBUG')
149      self.debugLog = env.get('NOSE_DEBUG_LOG')
150      self.exclude = None
151      self.getTestCaseNamesCompat = False
152      self.includeExe = env.get('NOSE_INCLUDE_EXE',
153                                sys.platform in exe_allowed_platforms)
154      self.ignoreFiles = (re.compile(r'^\.'),
155                          re.compile(r'^_'),
156                          re.compile(r'^setup\.py$')
157                          )
158      self.include = None
159      self.loggingConfig = None
160      self.logStream = sys.stderr
161      self.options = NoOptions()
162      self.parser = None
163      self.plugins = NoPlugins()
164      self.srcDirs = ('lib', 'src')
165      self.runOnInit = True
166      self.stopOnError = env.get('NOSE_STOP', False)
167      self.stream = sys.stderr
168      self.testNames = ()
169      self.verbosity = int(env.get('NOSE_VERBOSE', 1))
170      self.where = ()
171      self.workingDir = None   
172    """
173
174    def __init__(self, **kw):
175        self.env = env = kw.pop('env', {})
176        self.args = ()
177        self.testMatchPat = env.get('NOSE_TESTMATCH',
178                                    r'(?:^|[\b_\.%s-])[Tt]est' % os.sep)
179        self.testMatch = re.compile(self.testMatchPat)
180        self.addPaths = not env.get('NOSE_NOPATH', False)
181        self.configSection = 'nosetests'
182        self.debug = env.get('NOSE_DEBUG')
183        self.debugLog = env.get('NOSE_DEBUG_LOG')
184        self.exclude = None
185        self.getTestCaseNamesCompat = False
186        self.includeExe = env.get('NOSE_INCLUDE_EXE',
187                                  sys.platform in exe_allowed_platforms)
188        self.ignoreFiles = (re.compile(r'^\.'),
189                            re.compile(r'^_'),
190                            re.compile(r'^setup\.py$')
191                            )
192        self.include = None
193        self.loggingConfig = None
194        self.logStream = sys.stderr
195        self.options = NoOptions()
196        self.parser = None
197        self.plugins = NoPlugins()
198        self.srcDirs = ('lib', 'src')
199        self.runOnInit = True
200        self.stopOnError = env.get('NOSE_STOP', False)
201        self.stream = sys.stderr
202        self.testNames = []
203        self.verbosity = int(env.get('NOSE_VERBOSE', 1))
204        self.where = ()
205        self.workingDir = os.getcwd()
206        self.traverseNamespace = False
207        self.firstPackageWins = False
208        self.parserClass = OptionParser
209       
210        self._default = self.__dict__.copy()
211        self.update(kw)
212        self._orig = self.__dict__.copy()
213
214    def __repr__(self):
215        d = self.__dict__.copy()
216        # don't expose env, could include sensitive info
217        d['env'] = {}
218        keys = [ k for k in d.keys()
219                 if not k.startswith('_') ]
220        keys.sort()
221        return "Config(%s)" % ', '.join([ '%s=%r' % (k, d[k])
222                                          for k in keys ])
223    __str__ = __repr__
224
225    def _parseArgs(self, argv, cfg_files):
226        def warn_sometimes(msg, name=None, filename=None):
227            if (hasattr(self.plugins, 'excludedOption') and
228                self.plugins.excludedOption(name)):
229                msg = ("Option %r in config file %r ignored: "
230                       "excluded by runtime environment" %
231                       (name, filename))
232                warn(msg, RuntimeWarning)
233            else:
234                raise ConfigError(msg)
235        parser = ConfiguredDefaultsOptionParser(
236            self.getParser(), self.configSection, file_error=warn_sometimes)
237        return parser.parseArgsAndConfigFiles(argv[1:], cfg_files)
238
239    def configure(self, argv=None, doc=None):
240        """Configure the nose running environment. Execute configure before
241        collecting tests with nose.TestCollector to enable output capture and
242        other features.
243        """
244        env = self.env
245        if argv is None:
246            argv = sys.argv
247
248        cfg_files = getattr(self, 'files', [])
249        options, args = self._parseArgs(argv, cfg_files)
250        # If -c --config has been specified on command line,
251        # load those config files and reparse
252        if getattr(options, 'files', []):
253            options, args = self._parseArgs(argv, options.files)
254
255        self.options = options
256        if args:
257            self.testNames = args
258        if options.testNames is not None:
259            self.testNames.extend(tolist(options.testNames))
260
261        # `where` is an append action, so it can't have a default value
262        # in the parser, or that default will always be in the list
263        if not options.where:
264            options.where = env.get('NOSE_WHERE', None)
265
266        # include and exclude also
267        if not options.include:
268            options.include = env.get('NOSE_INCLUDE', [])
269        if not options.exclude:
270            options.exclude = env.get('NOSE_EXCLUDE', [])
271
272        self.addPaths = options.addPaths
273        self.stopOnError = options.stopOnError
274        self.verbosity = options.verbosity
275        self.includeExe = options.includeExe
276        self.traverseNamespace = options.traverseNamespace
277        self.debug = options.debug
278        self.debugLog = options.debugLog
279        self.loggingConfig = options.loggingConfig
280        self.firstPackageWins = options.firstPackageWins
281        self.configureLogging()
282
283        if options.where is not None:
284            self.configureWhere(options.where)
285       
286        if options.testMatch:
287            self.testMatch = re.compile(options.testMatch)
288               
289        if options.include:
290            self.include = map(re.compile, tolist(options.include))
291            log.info("Including tests matching %s", options.include)
292
293        if options.exclude:
294            self.exclude = map(re.compile, tolist(options.exclude))
295            log.info("Excluding tests matching %s", options.exclude)
296
297        # When listing plugins we don't want to run them
298        if not options.showPlugins:
299            self.plugins.configure(options, self)
300            self.plugins.begin()
301
302    def configureLogging(self):
303        """Configure logging for nose, or optionally other packages. Any logger
304        name may be set with the debug option, and that logger will be set to
305        debug level and be assigned the same handler as the nose loggers, unless
306        it already has a handler.
307        """
308        if self.loggingConfig:
309            from logging.config import fileConfig
310            fileConfig(self.loggingConfig)
311            return
312       
313        format = logging.Formatter('%(name)s: %(levelname)s: %(message)s')
314        if self.debugLog:
315            handler = logging.FileHandler(self.debugLog)
316        else:
317            handler = logging.StreamHandler(self.logStream)
318        handler.setFormatter(format)
319
320        logger = logging.getLogger('nose')
321        logger.propagate = 0
322
323        # only add our default handler if there isn't already one there
324        # this avoids annoying duplicate log messages.
325        if handler not in logger.handlers:
326            logger.addHandler(handler)
327
328        # default level   
329        lvl = logging.WARNING
330        if self.verbosity >= 5:
331            lvl = 0
332        elif self.verbosity >= 4:
333            lvl = logging.DEBUG
334        elif self.verbosity >= 3:
335            lvl = logging.INFO
336        logger.setLevel(lvl)
337
338        # individual overrides
339        if self.debug:
340            # no blanks
341            debug_loggers = [ name for name in self.debug.split(',')
342                              if name ]
343            for logger_name in debug_loggers:
344                l = logging.getLogger(logger_name)
345                l.setLevel(logging.DEBUG)
346                if not l.handlers and not logger_name.startswith('nose'):
347                    l.addHandler(handler)
348
349    def configureWhere(self, where):
350        """Configure the working directory or directories for the test run.
351        """
352        from nose.importer import add_path
353        self.workingDir = None
354        where = tolist(where)
355        warned = False
356        for path in where:
357            if not self.workingDir:
358                abs_path = absdir(path)
359                if abs_path is None:
360                    raise ValueError("Working directory %s not found, or "
361                                     "not a directory" % path)
362                log.info("Set working dir to %s", abs_path)
363                self.workingDir = abs_path
364                if self.addPaths and \
365                       os.path.exists(os.path.join(abs_path, '__init__.py')):
366                    log.info("Working directory %s is a package; "
367                             "adding to sys.path" % abs_path)
368                    add_path(abs_path)
369                continue
370            if not warned:
371                warn("Use of multiple -w arguments is deprecated and "
372                     "support may be removed in a future release. You can "
373                     "get the same behavior by passing directories without "
374                     "the -w argument on the command line, or by using the "
375                     "--tests argument in a configuration file.",
376                     DeprecationWarning)
377            self.testNames.append(path)
378
379    def default(self):
380        """Reset all config values to defaults.
381        """
382        self.__dict__.update(self._default)
383
384    def getParser(self, doc=None):
385        """Get the command line option parser.
386        """
387        if self.parser:
388            return self.parser
389        env = self.env
390        parser = self.parserClass(doc)
391        parser.add_option(
392            "-V","--version", action="store_true",
393            dest="version", default=False,
394            help="Output nose version and exit")
395        parser.add_option(
396            "-p", "--plugins", action="store_true",
397            dest="showPlugins", default=False,
398            help="Output list of available plugins and exit. Combine with "
399            "higher verbosity for greater detail")
400        parser.add_option(
401            "-v", "--verbose",
402            action="count", dest="verbosity",
403            default=self.verbosity,
404            help="Be more verbose. [NOSE_VERBOSE]")
405        parser.add_option(
406            "--verbosity", action="store", dest="verbosity",
407            metavar='VERBOSITY',
408            type="int", help="Set verbosity; --verbosity=2 is "
409            "the same as -v")
410        parser.add_option(
411            "-q", "--quiet", action="store_const", const=0, dest="verbosity",
412            help="Be less verbose")
413        parser.add_option(
414            "-c", "--config", action="append", dest="files",
415            metavar="FILES",
416            help="Load configuration from config file(s). May be specified "
417            "multiple times; in that case, all config files will be "
418            "loaded and combined")
419        parser.add_option(
420            "-w", "--where", action="append", dest="where",
421            metavar="WHERE",
422            help="Look for tests in this directory. "
423            "May be specified multiple times. The first directory passed "
424            "will be used as the working directory, in place of the current "
425            "working directory, which is the default. Others will be added "
426            "to the list of tests to execute. [NOSE_WHERE]"
427            )
428        parser.add_option(
429            "-m", "--match", "--testmatch", action="store",
430            dest="testMatch", metavar="REGEX",
431            help="Files, directories, function names, and class names "
432            "that match this regular expression are considered tests.  "
433            "Default: %s [NOSE_TESTMATCH]" % self.testMatchPat,
434            default=self.testMatchPat)
435        parser.add_option(
436            "--tests", action="store", dest="testNames", default=None,
437            metavar='NAMES',
438            help="Run these tests (comma-separated list). This argument is "
439            "useful mainly from configuration files; on the command line, "
440            "just pass the tests to run as additional arguments with no "
441            "switch.")
442        parser.add_option(
443            "-l", "--debug", action="store",
444            dest="debug", default=self.debug,
445            help="Activate debug logging for one or more systems. "
446            "Available debug loggers: nose, nose.importer, "
447            "nose.inspector, nose.plugins, nose.result and "
448            "nose.selector. Separate multiple names with a comma.")
449        parser.add_option(
450            "--debug-log", dest="debugLog", action="store",
451            default=self.debugLog, metavar="FILE",
452            help="Log debug messages to this file "
453            "(default: sys.stderr)")
454        parser.add_option(
455            "--logging-config", "--log-config",
456            dest="loggingConfig", action="store",
457            default=self.loggingConfig, metavar="FILE",
458            help="Load logging config from this file -- bypasses all other"
459            " logging config settings.")
460        parser.add_option(
461            "-e", "--exclude", action="append", dest="exclude",
462            metavar="REGEX",
463            help="Don't run tests that match regular "
464            "expression [NOSE_EXCLUDE]")
465        parser.add_option(
466            "-i", "--include", action="append", dest="include",
467            metavar="REGEX",
468            help="This regular expression will be applied to files, "
469            "directories, function names, and class names for a chance "
470            "to include additional tests that do not match TESTMATCH.  "
471            "Specify this option multiple times "
472            "to add more regular expressions [NOSE_INCLUDE]")
473        parser.add_option(
474            "-x", "--stop", action="store_true", dest="stopOnError",
475            default=self.stopOnError,
476            help="Stop running tests after the first error or failure")
477        parser.add_option(
478            "-P", "--no-path-adjustment", action="store_false",
479            dest="addPaths",
480            default=self.addPaths,
481            help="Don't make any changes to sys.path when "
482            "loading tests [NOSE_NOPATH]")
483        parser.add_option(
484            "--exe", action="store_true", dest="includeExe",
485            default=self.includeExe,
486            help="Look for tests in python modules that are "
487            "executable. Normal behavior is to exclude executable "
488            "modules, since they may not be import-safe "
489            "[NOSE_INCLUDE_EXE]")
490        parser.add_option(
491            "--noexe", action="store_false", dest="includeExe",
492            help="DO NOT look for tests in python modules that are "
493            "executable. (The default on the windows platform is to "
494            "do so.)")
495        parser.add_option(
496            "--traverse-namespace", action="store_true",
497            default=self.traverseNamespace, dest="traverseNamespace",
498            help="Traverse through all path entries of a namespace package")
499        parser.add_option(
500            "--first-package-wins", "--first-pkg-wins", "--1st-pkg-wins",
501            default=False, dest="firstPackageWins",
502            help="nose's importer will normally evict a package from sys."
503            "modules if it sees a package with the same name in a different "
504            "location. Set this option to disable that behavior.")
505
506        self.plugins.loadPlugins()
507        self.pluginOpts(parser)
508
509        self.parser = parser
510        return parser
511
512    def help(self, doc=None):
513        """Return the generated help message
514        """
515        return self.getParser(doc).format_help()
516
517    def pluginOpts(self, parser):
518        self.plugins.addOptions(parser, self.env)
519
520    def reset(self):
521        self.__dict__.update(self._orig)
522
523    def todict(self):
524        return self.__dict__.copy()
525       
526    def update(self, d):
527        self.__dict__.update(d)
528
529
530class NoOptions(object):
531    """Options container that returns None for all options.
532    """
533    def __getattr__(self, attr):
534        return None
535
536    def __nonzero__(self):
537        return False
538
539
540def user_config_files():
541    """Return path to any existing user config files
542    """
543    return filter(os.path.exists,
544                  map(os.path.expanduser, config_files))
545
546
547def all_config_files():
548    """Return path to any existing user config files, plus any setup.cfg
549    in the current working directory.
550    """
551    user = user_config_files()
552    if os.path.exists('setup.cfg'):
553        return user + ['setup.cfg']
554    return user
555
556
557# used when parsing config files
558def flag(val):
559    """Does the value look like an on/off flag?"""
560    if val == 1:
561        return True
562    elif val == 0:
563        return False
564    val = str(val)
565    if len(val) > 5:
566        return False
567    return val.upper() in ('1', '0', 'F', 'T', 'TRUE', 'FALSE', 'ON', 'OFF')
568
569
570def _bool(val):
571    return str(val).upper() in ('1', 'T', 'TRUE', 'ON')
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。