コード例 #1
0
ファイル: base.py プロジェクト: edgedb/metapkg
    def __init__(
        self,
        version: str,
        pretty_version: str | None = None,
        *,
        source_version: str | None = None,
        requires: list[poetry_pkg.Package] | None = None,
    ) -> None:

        if self.title is None:
            raise RuntimeError(
                f"{type(self)!r} does not define the required "
                f"title attribute"
            )

        super().__init__(self.name, version, pretty_version=pretty_version)

        if requires is not None:
            reqs = list(requires)
        else:
            reqs = []

        reqs.extend(self.get_requirements())

        if reqs:
            if "default" not in self._dependency_groups:
                self._dependency_groups[
                    "default"
                ] = poetry_depgroup.DependencyGroup("default")
        for req in reqs:
            self._dependency_groups["default"].add_dependency(req)

        self.build_requires = self.get_build_requirements()
        self.description = type(self).description  # type: ignore
        if source_version is None:
            self.source_version = self.pretty_version
        else:
            self.source_version = source_version

        repository.bundle_repo.add_package(self)

        if self.aliases:
            for alias in self.aliases:
                pkg = DummyPackage(name=alias, version=self.version)
                pkg.add_dependency(
                    poetry_dep.Dependency(self.name, self.version)
                )
                repository.bundle_repo.add_package(pkg)
コード例 #2
0
ファイル: __init__.py プロジェクト: edgedb/edgedb-pkg
 def get_build_requirements(self) -> list[poetry_dep.Dependency]:
     reqs = super().get_requirements()
     reqs.append(poetry_dep.Dependency("libffi", "*"))
     return reqs
コード例 #3
0
ファイル: __init__.py プロジェクト: edgedb/edgedb-pkg
 def get_build_requirements(self) -> list[poetry_dep.Dependency]:
     reqs = super().get_requirements()
     reqs.append(poetry_dep.Dependency("openssl", ">=1.1.1"))
     return reqs
コード例 #4
0
ファイル: __init__.py プロジェクト: edgedb/edgedb-pkg
from metapkg import packages
from metapkg import targets
from metapkg.packages import python

from edgedbpkg import postgresql
from edgedbpkg import python as python_bundle
from edgedbpkg import pyentrypoint

if TYPE_CHECKING:
    from cleo.io import io as cleo_io
    from poetry.core.semver import version as poetry_version

python.set_python_runtime_dependency(
    poetry_dep.Dependency(
        name="python-edgedb",
        constraint=">=3.10.0,<=3.11.0",
        allows_prereleases=True,
    ))


class EdgeDB(packages.BundledPythonPackage):

    title = "EdgeDB"
    name = "edgedb-server"
    description = "Next generation object-relational database"
    license = "ASL 2.0"
    group = "Applications/Databases"
    identifier = "com.edgedb.edgedb-server"
    url = "https://edgedb.com/"

    sources = (
コード例 #5
0
ファイル: build.py プロジェクト: edgedb/metapkg
    def handle(self) -> int:
        pkgname = self.argument("name")
        keepwork = self.option("keepwork")
        destination = self.option("dest")
        generic = self.option("generic")
        libc = self.option("libc")
        build_source = self.option("build-source")
        build_debug = self.option("build-debug")
        src_ref = self.option("source-ref")
        version = self.option("pkg-version")
        revision = self.option("pkg-revision")
        subdist = self.option("pkg-subdist")
        is_release = self.option("release")
        extra_opt = self.option("extra-optimizations")
        jobs = self.option("jobs")

        target = targets.detect_target(self.io, portable=generic, libc=libc)
        target.prepare()

        modname, _, clsname = pkgname.rpartition(":")

        mod = importlib.import_module(modname)
        pkgcls = getattr(mod, clsname)
        if src_ref:
            if "extras" not in pkgcls.sources[0]:
                pkgcls.sources[0]["extras"] = {}
            pkgcls.sources[0]["extras"]["version"] = src_ref
        root_pkg = pkgcls.resolve(
            self.io,
            version=version,
            revision=revision,
            is_release=is_release,
            target=target,
        )

        sources = root_pkg.get_sources()

        if len(sources) != 1:
            self.error("Only single-source git packages are supported")
            return 1

        source = sources[0]
        if not isinstance(source, af_sources.GitSource):
            self.error("Only single-source git packages are supported")
            return 1

        root = project_package.ProjectPackage("__root__", "1")
        root.python_versions = af_python.python_dependency.pretty_constraint
        root.add_dependency(
            poetry_dep.Dependency(root_pkg.name, root_pkg.version))
        af_repo.bundle_repo.add_package(root)

        target_capabilities = target.get_capabilities()
        extras = [f"capability-{c}" for c in target_capabilities]

        repo_pool = af_repo.Pool()
        repo_pool.add_repository(target.get_package_repository())
        repo_pool.add_repository(af_repo.bundle_repo, secondary=True)

        item_repo = root_pkg.get_package_repository(target, io=self.io)
        if item_repo is not None:
            repo_pool.add_repository(item_repo, secondary=True)

        provider = af_repo.Provider(root, repo_pool, self.io, extras=extras)
        resolution = poetry_solver.resolve_version(root, provider)

        env = poetry_env.SystemEnv(pathlib.Path(sys.executable))
        pkg_map = {}
        graph = {}
        for dep_package in resolution.packages:
            pkg_map[dep_package.name] = dep_package.package
            package = dep_package.package
            if env.is_valid_for_marker(dep_package.dependency.marker):
                deps = {
                    req.name
                    for req in package.requires
                    if env.is_valid_for_marker(req.marker)
                }
                graph[package.name] = deps
        sorter = graphlib.TopologicalSorter(graph)
        packages = [pkg_map[pn] for pn in sorter.static_order()]

        # Build a separate package list for build deps.
        build_root = project_package.ProjectPackage("__build_root__", "1")
        build_root.python_versions = (
            af_python.python_dependency.pretty_constraint)
        build_root.add_dependency(
            poetry_dep.Dependency(root_pkg.name, root_pkg.version))
        build_root.build_requires = []
        provider = af_repo.Provider(build_root,
                                    repo_pool,
                                    self.io,
                                    include_build_reqs=True)
        resolution = poetry_solver.resolve_version(build_root, provider)

        pkg_map = {}
        graph = {}
        for dep_package in resolution.packages:
            pkg_map[dep_package.name] = dep_package.package
            package = dep_package.package
            if env.is_valid_for_marker(dep_package.dependency.marker):
                reqs = set(package.requires) | set(
                    getattr(package, "build_requires", []))
                deps = {
                    req.name
                    for req in reqs if req.is_activated()
                    and env.is_valid_for_marker(req.marker)
                }
                graph[package.name] = deps

        # Workaround cycles in build/runtime dependencies between
        # packages.  This requires the depending package to explicitly
        # declare its cyclic runtime dependencies in get_cyclic_runtime_deps()
        # and then the cyclic dependency must take care to inject itself
        # into the dependent's context to build itself (e.g. by manipulating
        # PYTHONPATH at build time.)  An example of such cycle is
        # flit-core -> tomli -> flit-core.
        cyclic_runtime_deps = collections.defaultdict(list)
        last_cycle = None
        current_cycle = None
        while True:
            sorter = graphlib.TopologicalSorter(graph)

            try:
                build_pkgs = [pkg_map[pn] for pn in sorter.static_order()]
            except graphlib.CycleError as e:
                cycle = e.args[1]
                if len(cycle) > 3 or cycle == last_cycle:
                    raise

                dep = pkg_map[cycle[-1]]
                pkg_with_dep = pkg_map[cycle[-2]]
                if dep.name not in pkg_with_dep.get_cyclic_runtime_deps():
                    dep, pkg_with_dep = pkg_with_dep, dep
                    if dep.name not in pkg_with_dep.get_cyclic_runtime_deps():
                        raise

                last_cycle = current_cycle
                current_cycle = cycle
                cyclic_runtime_deps[pkg_with_dep].append(dep)
                graph[pkg_with_dep.name].remove(dep.name)
            else:
                break

        for pkg_with_cr_deps, cr_deps in cyclic_runtime_deps.items():
            for i, build_pkg in enumerate(build_pkgs):
                if build_pkg == pkg_with_cr_deps:
                    build_pkgs[i + 1:i + 1] = cr_deps
                    break

        if keepwork:
            workdir = tempfile.mkdtemp(prefix="metapkg.")
        else:
            tempdir = tempfile.TemporaryDirectory(prefix="metapkg.")
            workdir = tempdir.name

        os.chmod(workdir, 0o755)

        try:
            target.build(
                targets.BuildRequest(
                    io=self.io,
                    env=env,
                    root_pkg=root_pkg,
                    deps=packages,
                    build_deps=build_pkgs,
                    workdir=workdir,
                    outputdir=destination,
                    build_source=build_source,
                    build_debug=build_debug,
                    revision=revision or "1",
                    subdist=subdist,
                    extra_opt=extra_opt,
                    jobs=jobs or 0,
                ), )
        finally:
            if not keepwork:
                tempdir.cleanup()

        return 0
コード例 #6
0
ファイル: python.py プロジェクト: edgedb/metapkg
from poetry.core.semver import version as poetry_version
from poetry.repositories import pypi_repository

from metapkg import packages as mpkg
from metapkg import tools
from metapkg import targets

from . import base
from . import repository as af_repository
from . import sources as af_sources
from .utils import python_dependency_from_pep_508

if TYPE_CHECKING:
    from cleo.io import io as cleo_io

python_dependency = poetry_dep.Dependency(name="python", constraint=">=3.7")
wheel_dependency = poetry_dep.Dependency(name="pypkg-wheel", constraint="*")


def set_python_runtime_dependency(dep: poetry_dep.Dependency) -> None:
    global python_dependency
    python_dependency = dep


class PyPiRepository(pypi_repository.PyPiRepository):  # type: ignore
    def __init__(self, io: cleo_io.IO) -> None:
        super().__init__()
        self._io = io
        self._pkg_impls: dict[str, type[PythonPackage]] = {
            "flit-core": FlitCore,
            "tomli": Tomli,