def run(self): prev_syspath = sys.path[:] try: # build release build = self.reinitialize_command('build') self.run_command('build') sys.path.insert(0, build.build_lib) # XXX maybe we could pass the verbose argument of pysetup here logger = logging.getLogger('packaging') verbose = logger.getEffectiveLevel() >= logging.DEBUG verbosity = verbose + 1 # run the tests if self.runner: resolve_name(self.runner)() elif self.suite: runner = unittest.TextTestRunner(verbosity=verbosity) runner.run(resolve_name(self.suite)()) elif self.get_ut_with_discovery(): ut = self.get_ut_with_discovery() test_suite = ut.TestLoader().discover(os.curdir) runner = ut.TextTestRunner(verbosity=verbosity) runner.run(test_suite) finally: sys.path[:] = prev_syspath
def check_hooks_resolvable(self): for options in self.distribution.command_options.values(): for hook_kind in ("pre_hook", "post_hook"): if hook_kind not in options: break for hook_name in options[hook_kind][1].values(): try: resolve_name(hook_name) except ImportError: self.warn('name %r cannot be resolved', hook_name)
def new_compiler(plat=None, compiler=None, dry_run=False, force=False): """Generate an instance of some CCompiler subclass for the supplied platform/compiler combination. 'plat' defaults to 'os.name' (eg. 'posix', 'nt'), and 'compiler' defaults to the default compiler for that platform. Currently only 'posix' and 'nt' are supported, and the default compilers are "traditional Unix interface" (UnixCCompiler class) and Visual C++ (MSVCCompiler class). Note that it's perfectly possible to ask for a Unix compiler object under Windows, and a Microsoft compiler object under Unix -- if you supply a value for 'compiler', 'plat' is ignored. """ if plat is None: plat = os.name try: if compiler is None: compiler = get_default_compiler(plat) cls = _COMPILERS[compiler] except KeyError: msg = "don't know how to compile C/C++ code on platform '%s'" % plat if compiler is not None: msg = msg + " with '%s' compiler" % compiler raise PackagingPlatformError(msg) if isinstance(cls, str): cls = resolve_name(cls) _COMPILERS[compiler] = cls return cls(dry_run, force)
def run_command_hooks(self, cmd_obj, hook_kind): """Run hooks registered for that command and phase. *cmd_obj* is a finalized command object; *hook_kind* is either 'pre_hook' or 'post_hook'. """ if hook_kind not in ('pre_hook', 'post_hook'): raise ValueError('invalid hook kind: %r' % hook_kind) hooks = getattr(cmd_obj, hook_kind, None) if hooks is None: return for hook in hooks.values(): if isinstance(hook, str): try: hook_obj = resolve_name(hook) except ImportError as e: raise PackagingModuleError(e) else: hook_obj = hook if not callable(hook_obj): raise PackagingOptionError('hook %r is not callable' % hook) logger.info('running %s %s for command %s', hook_kind, hook, cmd_obj.get_command_name()) hook_obj(cmd_obj)
def use_command(testcase, fullname): """Register command at *fullname* for the duration of a test.""" set_command(fullname) # XXX maybe set_command should return the class object name = resolve_name(fullname).get_command_name() # XXX maybe we need a public API to remove commands testcase.addCleanup(_COMMANDS.__delitem__, name)
def get_command_class(name): """Return the registered command""" try: cls = _COMMANDS[name] except KeyError: raise PackagingModuleError("Invalid command %s" % name) if isinstance(cls, str): cls = resolve_name(cls) _COMMANDS[name] = cls return cls
def show_compilers(): """Print list of available compilers (used by the "--help-compiler" options to "build", "build_ext", "build_clib"). """ from packaging.fancy_getopt import FancyGetopt compilers = [] for name, cls in _COMPILERS.items(): if isinstance(cls, str): cls = resolve_name(cls) _COMPILERS[name] = cls compilers.append(("compiler=" + name, None, cls.description)) compilers.sort() pretty_printer = FancyGetopt(compilers) pretty_printer.print_help("List of available compilers:")
def finalize_options(self): if self.manifest is None: self.manifest = "MANIFEST" self.ensure_string_list('formats') if self.formats is None: try: self.formats = [self.default_format[os.name]] except KeyError: raise PackagingPlatformError("don't know how to create source " "distributions on platform %s" % os.name) bad_format = self._check_archive_formats(self.formats) if bad_format: raise PackagingOptionError("unknown archive format '%s'" \ % bad_format) if self.dist_dir is None: self.dist_dir = "dist" if self.filelist is None: self.filelist = Manifest() if self.manifest_builders is None: self.manifest_builders = [] else: if isinstance(self.manifest_builders, str): self.manifest_builders = self.manifest_builders.split(',') builders = [] for builder in self.manifest_builders: builder = builder.strip() if builder == '': continue try: builder = resolve_name(builder) except ImportError as e: raise PackagingModuleError(e) builders.append(builder) self.manifest_builders = builders
def set_command(location): cls = resolve_name(location) # XXX we want to do the duck-type checking here _COMMANDS[cls.get_command_name()] = cls
def _read_setup_cfg(self, parser, cfg_filename): cfg_directory = os.path.dirname(os.path.abspath(cfg_filename)) content = {} for section in parser.sections(): content[section] = dict(parser.items(section)) # global setup hooks are called first if 'global' in content: if 'setup_hooks' in content['global']: setup_hooks = split_multiline(content['global']['setup_hooks']) # add project directory to sys.path, to allow hooks to be # distributed with the project sys.path.insert(0, cfg_directory) try: for line in setup_hooks: try: hook = resolve_name(line) except ImportError as e: logger.warning('cannot find setup hook: %s', e.args[0]) else: self.setup_hooks.append(hook) self.run_hooks(content) finally: sys.path.pop(0) metadata = self.dist.metadata # setting the metadata values if 'metadata' in content: for key, value in content['metadata'].items(): key = key.replace('_', '-') if metadata.is_multi_field(key): value = split_multiline(value) if key == 'project-url': value = [(label.strip(), url.strip()) for label, url in [v.split(',') for v in value]] if key == 'description-file': if 'description' in content['metadata']: msg = ("description and description-file' are " "mutually exclusive") raise PackagingOptionError(msg) filenames = value.split() # concatenate all files value = [] for filename in filenames: # will raise if file not found with open(filename) as description_file: value.append(description_file.read().strip()) # add filename as a required file if filename not in metadata.requires_files: metadata.requires_files.append(filename) value = '\n'.join(value).strip() key = 'description' if metadata.is_metadata_field(key): metadata[key] = self._convert_metadata(key, value) if 'files' in content: files = content['files'] self.dist.package_dir = files.pop('packages_root', None) files = dict((key, split_multiline(value)) for key, value in files.items()) self.dist.packages = [] packages = files.get('packages', []) if isinstance(packages, str): packages = [packages] for package in packages: if ':' in package: dir_, package = package.split(':') self.dist.package_dir[package] = dir_ self.dist.packages.append(package) self.dist.py_modules = files.get('modules', []) if isinstance(self.dist.py_modules, str): self.dist.py_modules = [self.dist.py_modules] self.dist.scripts = files.get('scripts', []) if isinstance(self.dist.scripts, str): self.dist.scripts = [self.dist.scripts] self.dist.package_data = {} # bookkeeping for the loop below firstline = True prev = None for line in files.get('package_data', []): if '=' in line: # package name -- file globs or specs key, value = line.split('=') prev = self.dist.package_data[key.strip()] = value.split() elif firstline: # invalid continuation on the first line raise PackagingOptionError( 'malformed package_data first line: %r (misses "=")' % line) else: # continuation, add to last seen package name prev.extend(line.split()) firstline = False self.dist.data_files = [] for data in files.get('data_files', []): data = data.split('=') if len(data) != 2: continue key, value = data values = [v.strip() for v in value.split(',')] self.dist.data_files.append((key, values)) # manifest template self.dist.extra_files = files.get('extra_files', []) resources = [] for rule in files.get('resources', []): glob, destination = rule.split('=', 1) rich_glob = glob.strip().split(' ', 1) if len(rich_glob) == 2: prefix, suffix = rich_glob else: assert len(rich_glob) == 1 prefix = '' suffix = glob if destination == '<exclude>': destination = None resources.append( (prefix.strip(), suffix.strip(), destination.strip())) self.dist.data_files = get_resources_dests( cfg_directory, resources) ext_modules = self.dist.ext_modules for section_key in content: # no str.partition in 2.4 :( labels = section_key.split(':') if len(labels) == 2 and labels[0] == 'extension': values_dct = content[section_key] if 'name' in values_dct: raise PackagingOptionError( 'extension name should be given as [extension: name], ' 'not as key') name = labels[1].strip() _check_name(name, self.dist.packages) ext_modules.append(Extension( name, _pop_values(values_dct, 'sources'), _pop_values(values_dct, 'include_dirs'), _pop_values(values_dct, 'define_macros'), _pop_values(values_dct, 'undef_macros'), _pop_values(values_dct, 'library_dirs'), _pop_values(values_dct, 'libraries'), _pop_values(values_dct, 'runtime_library_dirs'), _pop_values(values_dct, 'extra_objects'), _pop_values(values_dct, 'extra_compile_args'), _pop_values(values_dct, 'extra_link_args'), _pop_values(values_dct, 'export_symbols'), _pop_values(values_dct, 'swig_opts'), _pop_values(values_dct, 'depends'), values_dct.pop('language', None), values_dct.pop('optional', None), **values_dct))
def set_compiler(location): """Add or change a compiler""" cls = resolve_name(location) # XXX we want to check the class here _COMPILERS[cls.name] = cls