Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions pynixify/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ async def source(self, extra_args=[]) -> Path:
def attr(self) -> str:
raise NotImplementedError()

async def metadata(self) -> PackageMetadata:
async def metadata(self, interpreter) -> PackageMetadata:
from pynixify.package_requirements import run_nix_build, NixBuildError
source = await self.source()
if source.name.endswith('.whl'):
Expand All @@ -56,7 +56,10 @@ async def metadata(self) -> PackageMetadata:
'--no-build-output',
'--arg',
'file',
str(source.resolve())
str(source.resolve()),
'--arg',
'python',
"(import <nixpkgs> { }).%s" % interpreter
)
if (nix_store_path / 'failed').exists():
print(f'Error parsing metadata of {source}. Assuming it has no metadata.')
Expand Down
21 changes: 16 additions & 5 deletions pynixify/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,15 @@ def main():
"executed by pynixify. If it isn't specified, it will be set to "
"the number of CPUs in the system."
))
parser.add_argument(
"-p",
"--py",
default="python3",
help=(
"Name of the nixpkgs python interpreter package to install in the "
"generated shell.nix. Defaults to 'python3'."
),
)
args = parser.parse_args()

asyncio.run(_main_async(
Expand All @@ -166,6 +175,7 @@ def main():
ignore_test_requirements_for=args.ignore_tests.split(',') if args.ignore_tests else [],
max_jobs=args.max_jobs,
generate_only_overlay=args.overlay_only,
interpreter=args.py,
))

async def _main_async(
Expand All @@ -178,7 +188,8 @@ async def _main_async(
ignore_test_requirements_for: List[str],
load_all_test_requirements: bool,
max_jobs: Optional[int],
generate_only_overlay:bool):
generate_only_overlay: bool,
interpreter: str):

if nixpkgs is not None:
pynixify.nixpkgs_sources.NIXPKGS_URL = nixpkgs
Expand All @@ -203,7 +214,7 @@ async def _main_async(
all_requirements.append(Requirement(req_))

await asyncio.gather(*(
version_chooser.require(req)
version_chooser.require(req, interpreter)
for req in all_requirements
))

Expand All @@ -218,13 +229,13 @@ async def _main_async(
async def write_package_expression(package: PyPIPackage):
reqs: ChosenPackageRequirements
reqs = ChosenPackageRequirements.from_package_requirements(
await evaluate_package_requirements(package),
await evaluate_package_requirements(package, extra_args=[interpreter]),
version_chooser=version_chooser,
load_tests=version_chooser.should_load_tests(package.pypi_name),
)

sha256 = await get_path_hash(await package.source())
meta = await package.metadata()
meta = await package.metadata(interpreter)
version = await load_nixpkgs_version()
try:
(pname, ext) = await get_pypi_data(
Expand Down Expand Up @@ -277,7 +288,7 @@ async def write_package_expression(package: PyPIPackage):
packages.append(p)

with (base_path / 'shell.nix').open('w') as fp:
expr = build_shell_nix_expression(packages)
expr = build_shell_nix_expression(packages, interpreter)
fp.write(await nixfmt(expr))


Expand Down
5 changes: 3 additions & 2 deletions pynixify/data/parse_setuppy_data.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{ file, stdenv ? (import <nixpkgs> { }).stdenv, lib ? (import <nixpkgs> { }).lib
, unzip ? (import <nixpkgs> { }).unzip, python ? (import <nixpkgs> { }).python3
{ file, python, stdenv ? (import <nixpkgs> { }).stdenv, lib ? (import <nixpkgs> { }).lib
, unzip ? (import <nixpkgs> { }).unzip, git ? (import <nixpkgs> { }).git
, fetchFromGitLab ? (import <nixpkgs> { }).fetchFromGitLab
}:

let
Expand Down
6 changes: 3 additions & 3 deletions pynixify/expression_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
""")

shell_nix_template = Template("""${DISCLAIMER}
{ python ? "python3" }:
{ python ? ${interpreter | nix} }:
let
pkgs = import ./nixpkgs.nix {};
pythonPkg = builtins.getAttr python pkgs;
Expand Down Expand Up @@ -206,8 +206,8 @@ def build_overlayed_nixpkgs(
return overlayed_nixpkgs_template.render(DISCLAIMER=DISCLAIMER, **locals())


def build_shell_nix_expression(packages: List[Package]) -> str:
return shell_nix_template.render(DISCLAIMER=DISCLAIMER, packages=packages)
def build_shell_nix_expression(packages: List[Package], interpreter: str) -> str:
return shell_nix_template.render(DISCLAIMER=DISCLAIMER, packages=packages, interpreter=interpreter, nix=escape_string)


async def nixfmt(expr: str) -> str:
Expand Down
7 changes: 5 additions & 2 deletions pynixify/package_requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def from_result_path(cls, result_path: Path):
return cls(**kwargs)


async def eval_path_requirements(path: Path) -> PackageRequirements:
async def eval_path_requirements(path: Path, interpreter: str) -> PackageRequirements:
nix_expression_path = Path(__file__).parent / "data" / "parse_setuppy_data.nix"
if path.name.endswith('.whl'):
# Some nixpkgs packages use a wheel as source, which don't have a
Expand All @@ -64,7 +64,10 @@ async def eval_path_requirements(path: Path) -> PackageRequirements:
'--no-build-output',
'--arg',
'file',
str(path.resolve())
str(path.resolve()),
'--arg',
'python',
"(import <nixpkgs> { }).%s" % interpreter
)
if (nix_store_path / 'failed').exists():
print(f'Error parsing requirements of {path}. Assuming it has no dependencies.')
Expand Down
9 changes: 5 additions & 4 deletions pynixify/version_chooser.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def __init__(self, nixpkgs_data: NixpkgsData, pypi_data: PyPIData,
self.evaluate_requirements = req_evaluate
self.should_load_tests = should_load_tests

async def require(self, r: Requirement, coming_from: Optional[Package]=None):
async def require(self, r: Requirement, interpreter: str, coming_from: Optional[Package]=None):
pkg: Package

if r.marker and not r.marker.evaluate():
Expand Down Expand Up @@ -119,14 +119,14 @@ async def require(self, r: Requirement, coming_from: Optional[Package]=None):

pkg = max(pkgs, key=operator.attrgetter('version'))
self._choosed_packages[canonicalize_name(r.name)] = (pkg, r.specifier)
reqs: PackageRequirements = await self.evaluate_requirements(pkg)
reqs: PackageRequirements = await self.evaluate_requirements(pkg, extra_args=[interpreter])

if isinstance(pkg, NixPackage) or (
not self.should_load_tests(canonicalize_name(r.name))):
reqs.test_requirements = []

await asyncio.gather(*(
self.require(req, coming_from=pkg)
self.require(req, interpreter, coming_from=pkg)
for req in (reqs.runtime_requirements + reqs.test_requirements +
reqs.build_requirements)
))
Expand Down Expand Up @@ -160,8 +160,9 @@ def all_pypi_packages(self) -> List[PyPIPackage]:

async def evaluate_package_requirements(
pkg: Package, extra_args=[]) -> PackageRequirements:
interpreter = extra_args.pop()
src = await pkg.source(extra_args)
return await eval_path_requirements(src)
return await eval_path_requirements(src, interpreter)


@dataclass
Expand Down