def test_pretty_docs(self): for target in self.currying_targets: for func in (passthrough, documented): assert currying.pretty_docs(target(func), 'new doc').__doc__ == 'new doc' assert currying.pretty_docs( target(func)).__doc__ is func.__doc__
class uninstall_op(ebd, format.uninstall): """phase operations and steps for uninstall execution""" def __init__(self, domain, pkg, observer): format.uninstall.__init__(self, domain, pkg, observer) ebd.__init__(self, pkg, observer=observer, initial_env=domain.settings, env_data_source=pkg.environment, clean=False, tmp_offset="unmerge") prerm = pretty_docs( observer.decorate_build_method("prerm")(post_curry( ebd._generic_phase, "prerm", False, False, False)), "run the prerm phase") postrm = pretty_docs( observer.decorate_build_method("postrm")(post_curry( ebd._generic_phase, "postrm", False, False, False, failure_allowed=True)), "run the postrm phase") def add_triggers(self, domain_op, engine): self.old_pkg.add_format_triggers(domain_op, self, engine) def finish(self): self.cleanup() return format.uninstall.finish(self)
def _single_thread_allowed(functor): def _inner(*args, **kwds): _acquire_global_ebp_lock() try: return functor(*args, **kwds) finally: _release_global_ebp_lock() _inner.func = functor pretty_docs(_inner, name=functor.__name__) return _inner
def test_pretty_docs(self): for target in self.currying_targets: for func in (passthrough, documented): self.assertEqual( currying.pretty_docs( target(func), 'new doc').__doc__, 'new doc') self.assertIdentical( currying.pretty_docs(target(func)).__doc__, func.__doc__)
def _single_thread_allowed(functor): """Decorator that forces method to run under single thread.""" def _inner(*args, **kwargs): _acquire_global_ebp_lock() try: return functor(*args, **kwargs) finally: _release_global_ebp_lock() _inner.func = functor pretty_docs(_inner, name=functor.__name__) return _inner
def test_module_magic(self): for target in self.currying_targets: assert currying.pretty_docs(target(passthrough)).__module__ is \ passthrough.__module__ # test is kinda useless if they are identical without pretty_docs assert getattr(target(passthrough), '__module__', None) is not \ passthrough.__module__
def mk_check(name): return pretty_docs( post_curry(getattr, 'is_' + name, False), extradocs=( "return True if obj is an instance of :obj:`%s`, else False" % name), name=("is" + name))
def test_module_magic(self): for target in self.currying_targets: self.assertIdentical( currying.pretty_docs(target(passthrough)).__module__, passthrough.__module__) # test is kinda useless if they are identical without pretty_docs self.assertNotIdentical( getattr(target(passthrough), '__module__', None), passthrough.__module__)
class install_op(ebd, format.install): """phase operations and steps for install execution""" def __init__(self, domain, pkg, observer): format.install.__init__(self, domain, pkg, observer) ebd.__init__( self, pkg, observer=observer, initial_env=domain.settings, env_data_source=pkg.environment, clean=False) preinst = pretty_docs( observer.decorate_build_method("preinst")( post_curry(ebd._generic_phase, "preinst", False, False)), "run the postinst phase") postinst = pretty_docs( observer.decorate_build_method("postinst")( post_curry(ebd._generic_phase, "postinst", False, False)), "run the postinst phase") def add_triggers(self, domain_op, engine): self.new_pkg.add_format_triggers(domain_op, self, engine)
def curry_node_type(klass, node_type, extradoc=None): """Helper function for creating restrictions of a certain type. This uses :obj:`partial` to pass a node_type to the wrapped class, and extends the docstring. :param klass: callable (usually a class) that is wrapped. :param node_type: value passed as node_type. :param extradoc: addition to the docstring. Defaults to "Automatically set to %s type." % node_type :return: a wrapped callable. """ if extradoc is None: extradoc = "Automatically set to %s type." % (node_type,) doc = klass.__doc__ result = partial(klass, node_type=node_type) if doc is None: doc = '' else: # do this so indentation on pydoc __doc__ is sane doc = "\n".join(line.lstrip() for line in doc.split("\n")) + "\n" doc += extradoc return pretty_docs(result, doc)
def curry_node_type(klass, node_type, extradoc=None): """Helper function for creating restrictions of a certain type. This uses :obj:`partial` to pass a node_type to the wrapped class, and extends the docstring. :param klass: callable (usually a class) that is wrapped. :param node_type: value passed as node_type. :param extradoc: addition to the docstring. Defaults to "Automatically set to %s type." % node_type :return: a wrapped callable. """ if extradoc is None: extradoc = "Automatically set to %s type." % (node_type, ) doc = klass.__doc__ result = partial(klass, node_type=node_type) if doc is None: doc = '' else: # do this so indentation on pydoc __doc__ is sane doc = "\n".join(line.lstrip() for line in doc.split("\n")) + "\n" doc += extradoc return pretty_docs(result, doc)
def _mk_pretty_derived_func(func, name_base, name, *args, **kwds): if name: name = '_' + name return pretty_docs(partial(func, *args, **kwds), name='%s%s' % (name_base, name))
def unpack(self): """execute the unpack phase""" if self.setup_is_for_src: self.setup_distfiles() if self.userpriv: try: os.chown(self.env["WORKDIR"], portage_uid, -1) except OSError as oe: raise_from( format.GenericBuildError( "failed forcing %i uid for WORKDIR: %s" % (portage_uid, str(oe)))) return self._generic_phase("unpack", True, True, False) compile = pretty_docs( observer.decorate_build_method("compile")(post_curry( ebd._generic_phase, "compile", True, True, False)), "run the compile phase (maps to src_compile)") @observer.decorate_build_method("install") def install(self): """run the install phase (maps to src_install)""" if self.fakeroot: return self._generic_phase("install", True, False, True) else: return self._generic_phase("install", False, True, False) @observer.decorate_build_method("test") def test(self): """run the test phase (if enabled), maps to src_test""" if not self.run_test: return True
def mk_check(name): return pretty_docs(post_curry(getattr, 'is_' + name, False), extradocs=("return True if obj is an instance of :obj:`%s`, else False" % name), name=("is" +name) )
def _wrap_exception(self, functor, name): f = currying.partial( self._recast_exception_decorator, self.__casting_exception__, name, functor) return currying.pretty_docs(f)
def unpack(self): """execute the unpack phase""" if self.setup_is_for_src: self.setup_distfiles() if self.userpriv: try: os.chown(self.env["WORKDIR"], portage_uid, -1) except OSError as oe: raise_from(format.GenericBuildError( "failed forcing %i uid for WORKDIR: %s" % (portage_uid, str(oe)))) return self._generic_phase("unpack", True, True, False) compile = pretty_docs( observer.decorate_build_method("compile")( post_curry( ebd._generic_phase, "compile", True, True, False)), "run the compile phase (maps to src_compile)") @observer.decorate_build_method("install") def install(self): """run the install phase (maps to src_install)""" if self.fakeroot: return self._generic_phase("install", True, False, True) else: return self._generic_phase("install", False, True, False) @observer.decorate_build_method("test") def test(self): """run the test phase (if enabled), maps to src_test""" if not self.run_test:
def test_pretty_docs(self): for target in self.currying_targets: for func in (passthrough, documented): assert currying.pretty_docs(target(func), 'new doc').__doc__ == 'new doc' assert currying.pretty_docs(target(func)).__doc__ is func.__doc__
class buildable(ebd, setup_mixin, format.build): """Generic build operation.""" # XXX this is unclean- should be handing in strictly what is build # env, rather then dumping domain settings as env. def __init__(self, domain, pkg, verified_files, eclass_cache, observer=None, force_test=False, **kwargs): """ :param pkg: :obj:`pkgcore.ebuild.ebuild_src.package` instance we'll be building :param eclass_cache: the :class:`pkgcore.ebuild.eclass_cache` we'll be using :param verified_files: mapping of fetchables mapped to their disk location """ self._built_class = ebuild_built.fresh_built_package format.build.__init__(self, domain, pkg, verified_files, observer) domain_settings = self.domain.settings ebd.__init__(self, pkg, initial_env=domain_settings, **kwargs) self.env["FILESDIR"] = pjoin(os.path.dirname(pkg.ebuild.path), "files") self.eclass_cache = eclass_cache self.run_test = force_test or self.feat_or_bool("test", domain_settings) self.allow_failed_test = self.feat_or_bool("test-fail-continue", domain_settings) if "test" in self.restrict: self.run_test = False elif not force_test and "test" not in pkg.use: if self.run_test: logger.warning(f"disabling test for {pkg} due to test use flag being disabled") self.run_test = False # XXX minor hack path = self.env["PATH"].split(os.pathsep) for s, default in (("DISTCC", ".distcc"), ("CCACHE", "ccache")): b = (self.feat_or_bool(s, domain_settings) and s not in self.restrict) setattr(self, s.lower(), b) if b: # looks weird I realize, but # pjoin("/foor/bar", "/barr/foo") == "/barr/foo" # and pjoin("/foo/bar", ".asdf") == "/foo/bar/.asdf" self.env.setdefault(s + "_DIR", pjoin(self.domain.tmpdir, default)) # gentoo bug 355283 libdir = self.env.get("ABI") if libdir is not None: libdir = self.env.get(f"LIBDIR_{libdir}") if libdir is not None: libdir = self.env.get(libdir) if libdir is None: libdir = "lib" path.insert(0, f"/usr/{libdir}/{s.lower()}/bin") else: for y in ("_PATH", "_DIR"): if s + y in self.env: del self.env[s+y] self.env["PATH"] = os.pathsep.join(path) # ordering must match appearance order in SRC_URI per PMS self.env["A"] = ' '.join(iter_stable_unique(pkg.distfiles)) if self.eapi.options.has_AA: pkg = self.pkg while hasattr(pkg, '_raw_pkg'): pkg = getattr(pkg, '_raw_pkg') self.env["AA"] = ' '.join(set(iflatten_instance(pkg.distfiles))) if self.eapi.options.has_KV: self.env["KV"] = domain.KV if self.eapi.options.has_merge_type: self.env["MERGE_TYPE"] = "source" if self.eapi.options.has_portdir: self.env["PORTDIR"] = pkg.repo.location self.env["ECLASSDIR"] = eclass_cache.eclassdir if self.setup_is_for_src: self._init_distfiles_env() def _init_distfiles_env(self): # TODO: PORTAGE_ACTUAL_DISTDIR usage by vcs eclasses needs to be killed off distdir_write = self.domain.fetcher.get_storage_path() if distdir_write is None: raise format.GenericBuildError( "no usable distdir was found " f"for PORTAGE_ACTUAL_DISTDIR from fetcher {self.domain.fetcher}") self.env["PORTAGE_ACTUAL_DISTDIR"] = distdir_write self.env["DISTDIR"] = normpath( pjoin(self.builddir, "distdir")) for x in ("PORTAGE_ACTUAL_DISTDIR", "DISTDIR"): self.env[x] = os.path.realpath(self.env[x]).rstrip(os.sep) + os.sep def _setup_distfiles(self): if not self.verified_files and self.allow_fetching: ops = self.domain.pkg_operations(self.pkg, observer=self.observer) if not ops.fetch(): raise format.GenericBuildError("failed fetching required distfiles") self.verified_files = ops._fetch_op.verified_files if self.verified_files: try: if os.path.exists(self.env["DISTDIR"]): if (os.path.isdir(self.env["DISTDIR"]) and not os.path.islink(self.env["DISTDIR"])): shutil.rmtree(self.env["DISTDIR"]) else: os.unlink(self.env["DISTDIR"]) except EnvironmentError as e: raise format.FailedDirectory( self.env["DISTDIR"], f"failed removing existing file/dir/link: {e}") from e if not ensure_dirs(self.env["DISTDIR"], mode=0o770, gid=portage_gid): raise format.FailedDirectory( self.env["DISTDIR"], "failed creating distdir symlink directory") try: for src, dest in [ (k, pjoin(self.env["DISTDIR"], v.filename)) for (k, v) in self.verified_files.items()]: os.symlink(src, dest) except EnvironmentError as e: raise format.GenericBuildError( f"Failed symlinking in distfiles for src {src} -> {dest}: {e}") from e @observer.decorate_build_method("setup") def setup(self): """Execute the setup phase, mapping out to pkg_setup in the ebuild. Necessarily dirs are created as required, and build env is initialized at this point. """ if self.distcc: for p in ("", "/lock", "/state"): if not ensure_dirs(pjoin(self.env["DISTCC_DIR"], p), mode=0o2775, gid=portage_gid): raise format.FailedDirectory( pjoin(self.env["DISTCC_DIR"], p), "failed creating needed distcc directory") if self.ccache: # yuck. st = None try: st = os.stat(self.env["CCACHE_DIR"]) except OSError as e: st = None if not ensure_dirs(self.env["CCACHE_DIR"], mode=0o2775, gid=portage_gid): raise format.FailedDirectory( self.env["CCACHE_DIR"], "failed creation of ccache dir") from e # XXX this is more then mildly stupid. st = os.stat(self.env["CCACHE_DIR"]) try: if st.st_gid != portage_gid or (st.st_mode & 0o2775) != 0o2775: try: cwd = os.getcwd() except OSError: cwd = "/" with chdir(cwd): # crap. os.chmod(self.env["CCACHE_DIR"], 0o2775) os.chown(self.env["CCACHE_DIR"], -1, portage_gid) if 0 != spawn( ["chgrp", "-R", str(portage_gid), self.env["CCACHE_DIR"]]): raise format.FailedDirectory( self.env["CCACHE_DIR"], "failed changing ownership for CCACHE_DIR") if 0 != spawn_bash( "find '%s' -type d -print0 | %s --null chmod 02775" % (self.env["CCACHE_DIR"], xargs)): raise format.FailedDirectory( self.env["CCACHE_DIR"], "failed correcting perms for CCACHE_DIR") if 0 != spawn_bash( "find '%s' -type f -print0 | %s --null chmod 0775" % (self.env["CCACHE_DIR"], xargs)): raise format.FailedDirectory( self.env["CCACHE_DIR"], "failed correcting perms for CCACHE_DIR") except OSError as e: raise format.FailedDirectory( self.env["CCACHE_DIR"], "failed ensuring perms/group owner for CCACHE_DIR") from e return setup_mixin.setup(self) def configure(self): """Execute the configure phase. Does nothing if the pkg's EAPI is less than 2 (that spec lacks a separated configure phase). """ if "configure" in self.eapi.phases: return self._generic_phase("configure", True, True) return True def prepare(self): """Execute a source preparation phase. does nothing if the pkg's EAPI is less than 2 """ ret = True if "prepare" in self.eapi.phases: ret = self._generic_phase("prepare", True, True) if (self.eapi.options.user_patches and not os.path.exists(pjoin(self.env['T'], '.user_patches_applied'))): self.observer.error( 'eapply_user (or default) must be called in src_prepare()') raise format.GenericBuildError('missing eapply_user call') return ret def nofetch(self): """Execute the nofetch phase. We need the same prerequisites as setup, so reuse that. """ ensure_dirs(self.env["T"], mode=0o770, gid=portage_gid, minimal=True) return setup_mixin.setup(self, "nofetch") def unpack(self): """Execute the unpack phase.""" if self.setup_is_for_src: self._setup_distfiles() if self.userpriv: try: os.chown(self.env["WORKDIR"], portage_uid, -1) except OSError as e: raise format.GenericBuildError( "failed forcing %i uid for WORKDIR: %s" % (portage_uid, e)) from e return self._generic_phase("unpack", True, True) compile = pretty_docs( observer.decorate_build_method("compile")( post_curry(ebd._generic_phase, "compile", True, True)), "Run the compile phase (maps to src_compile).") @observer.decorate_build_method("install") def install(self): """Run the install phase (maps to src_install).""" # TODO: replace print() usage with observer print(f">>> Install {self.env['PF']} into {self.ED!r} category {self.env['CATEGORY']}") ret = self._generic_phase("install", False, True) print(f">>> Completed installing {self.env['PF']} into {self.ED!r}") return ret @observer.decorate_build_method("test") def test(self): """Run the test phase (if enabled), maps to src_test.""" if not self.run_test: return True return self._generic_phase( "test", True, True, failure_allowed=self.allow_failed_test) def finalize(self): """Finalize the operation. This yields a built package, but the packages metadata/contents are bound to the workdir. In other words, install the package somewhere prior to executing clean if you intend on installing it. :return: :obj:`pkgcore.ebuild.ebuild_built.package` instance """ factory = ebuild_built.fake_package_factory(self._built_class) return factory.new_package( self.pkg, self.env["D"], pjoin(self.env["T"], "environment"))
:return: major,minor tuple of ints """ return ( stat_inst.st_rdev >> 8 ) & 0xff, stat_inst.st_rdev & 0xff class fsFifo(fsBase): """fifo class (socket objects)""" __slots__ = () is_fifo = True def __repr__(self): return "fifo:%s" % self.location def mk_check(name): return pretty_docs(post_curry(getattr, 'is_' + name, False), extradocs=("return True if obj is an instance of :obj:`%s`, else False" % name), name=("is" +name) ) isdir = mk_check('dir') isreg = mk_check('reg') issym = mk_check('sym') isfifo = mk_check('fifo') isdev = mk_check('dev') isfs_obj = pretty_docs(post_curry(isinstance, fsBase), name='isfs_obj', extradocs='return True if obj is an fsBase derived object') del gen_doc_additions, mk_check
class fsFifo(fsBase): """fifo class (socket objects)""" __slots__ = () is_fifo = True def __repr__(self): return f"fifo:{self.location}" def mk_check(name): return pretty_docs( post_curry(getattr, 'is_' + name, False), extradocs=( "return True if obj is an instance of :obj:`%s`, else False" % name), name=("is" + name)) isdir = mk_check('dir') isreg = mk_check('reg') issym = mk_check('sym') isfifo = mk_check('fifo') isdev = mk_check('dev') isfs_obj = pretty_docs( post_curry(isinstance, fsBase), name='isfs_obj', extradocs='return True if obj is an fsBase derived object') del gen_doc_additions, mk_check
def _wrap_exception(self, functor, name): f = partial( self._recast_exception_decorator, self.__casting_exception__, name, functor) return pretty_docs(f)