-
Notifications
You must be signed in to change notification settings - Fork 103
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #33 from mariusvniekerk/meta-yaml
- Loading branch information
Showing
8 changed files
with
266 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import hashlib | ||
import json | ||
|
||
from typing import List | ||
|
||
|
||
class LockSpecification: | ||
def __init__(self, specs: List[str], channels: List[str], platform: str): | ||
self.specs = specs | ||
self.channels = channels | ||
self.platform = platform | ||
|
||
def env_hash(self) -> str: | ||
env_spec = json.dumps( | ||
{ | ||
"channels": self.channels, | ||
"platform": self.platform, | ||
"specs": sorted(self.specs), | ||
}, | ||
sort_keys=True, | ||
) | ||
return hashlib.sha256(env_spec.encode("utf-8")).hexdigest() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import pathlib | ||
import sys | ||
|
||
import yaml | ||
|
||
from conda_lock.src_parser import LockSpecification | ||
from conda_lock.src_parser.selectors import filter_platform_selectors | ||
|
||
|
||
def parse_environment_file( | ||
environment_file: pathlib.Path, platform: str | ||
) -> LockSpecification: | ||
if not environment_file.exists(): | ||
raise FileNotFoundError(f"{environment_file} not found") | ||
|
||
with environment_file.open("r") as fo: | ||
filtered_content = "\n".join( | ||
filter_platform_selectors(fo.read(), platform=platform) | ||
) | ||
env_yaml_data = yaml.safe_load(filtered_content) | ||
# TODO: we basically ignore most of the fields for now. | ||
# notable pip deps are just skipped below | ||
specs = env_yaml_data["dependencies"] | ||
channels = env_yaml_data.get("channels", []) | ||
|
||
# Split out any sub spec sections from the dependencies mapping | ||
mapping_specs = [x for x in specs if not isinstance(x, str)] | ||
specs = [x for x in specs if isinstance(x, str)] | ||
|
||
# Print a warning if there are pip specs in the dependencies | ||
for mapping_spec in mapping_specs: | ||
if "pip" in mapping_spec: | ||
print( | ||
( | ||
"Warning, found pip deps not included in the lock file! You'll need to install " | ||
"them separately" | ||
), | ||
file=sys.stderr, | ||
) | ||
|
||
return LockSpecification(specs=specs, channels=channels, platform=platform) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import pathlib | ||
|
||
import jinja2 | ||
import yaml | ||
|
||
from conda_lock.src_parser import LockSpecification | ||
from conda_lock.src_parser.selectors import filter_platform_selectors | ||
|
||
|
||
class NullUndefined(jinja2.Undefined): | ||
def __getattr__(self, key): | ||
return "" | ||
|
||
# Using any of these methods on an Undefined variable | ||
# results in another Undefined variable. | ||
__add__ = ( | ||
__radd__ | ||
) = ( | ||
__mul__ | ||
) = ( | ||
__rmul__ | ||
) = ( | ||
__div__ | ||
) = ( | ||
__rdiv__ | ||
) = ( | ||
__truediv__ | ||
) = ( | ||
__rtruediv__ | ||
) = ( | ||
__floordiv__ | ||
) = ( | ||
__rfloordiv__ | ||
) = ( | ||
__mod__ | ||
) = ( | ||
__rmod__ | ||
) = ( | ||
__pos__ | ||
) = ( | ||
__neg__ | ||
) = ( | ||
__call__ | ||
) = ( | ||
__getitem__ | ||
) = ( | ||
__lt__ | ||
) = ( | ||
__le__ | ||
) = ( | ||
__gt__ | ||
) = ( | ||
__ge__ | ||
) = ( | ||
__complex__ | ||
) = __pow__ = __rpow__ = lambda self, *args, **kwargs: self._return_undefined( | ||
self._undefined_name | ||
) | ||
|
||
def _return_undefined(self, result_name): | ||
# Record that this undefined variable was actually used. | ||
return NullUndefined( | ||
hint=self._undefined_hint, | ||
obj=self._undefined_obj, | ||
name=result_name, | ||
exc=self._undefined_exception, | ||
) | ||
|
||
|
||
def parse_meta_yaml_file( | ||
meta_yaml_file: pathlib.Path, platform: str | ||
) -> LockSpecification: | ||
"""Parse a simple meta-yaml file for dependencies. | ||
* This does not support multi-output files and will ignore all lines with selectors | ||
""" | ||
if not meta_yaml_file.exists(): | ||
raise FileNotFoundError(f"{meta_yaml_file} not found") | ||
|
||
with meta_yaml_file.open("r") as fo: | ||
filtered_recipe = "\n".join( | ||
filter_platform_selectors(fo.read(), platform=platform) | ||
) | ||
t = jinja2.Template(filtered_recipe, undefined=NullUndefined) | ||
rendered = t.render() | ||
meta_yaml_data = yaml.safe_load(rendered) | ||
channels = meta_yaml_data.get("extra", {}).get("channels", []) | ||
specs = [] | ||
|
||
def add_spec(spec): | ||
if spec is None: | ||
return | ||
specs.append(spec) | ||
|
||
for s in meta_yaml_data.get("requirements", {}).get("host", []): | ||
add_spec(s) | ||
for s in meta_yaml_data.get("requirements", {}).get("run", []): | ||
add_spec(s) | ||
for s in meta_yaml_data.get("test", {}).get("requires", []): | ||
add_spec(s) | ||
|
||
return LockSpecification(specs=specs, channels=channels, platform=platform) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import re | ||
|
||
from typing import Iterator | ||
|
||
|
||
def filter_platform_selectors(content: str, platform) -> Iterator[str]: | ||
"""""" | ||
# we support a very limited set of selectors that adhere to platform only | ||
platform_sel = { | ||
"linux-64": {"linux64", "unix", "linux"}, | ||
"linux-aarch64": {"aarch64", "unix", "linux"}, | ||
"linux-ppc64le": {"ppc64le", "unix", "linux"}, | ||
"osx-64": {"osx", "osx64", "unix"}, | ||
"win-64": {"win", "win64"}, | ||
} | ||
|
||
# This code is adapted from conda-build | ||
sel_pat = re.compile(r"(.+?)\s*(#.*)?\[([^\[\]]+)\](?(2)[^\(\)]*)$") | ||
for line in content.splitlines(keepends=False): | ||
if line.lstrip().startswith("#"): | ||
continue | ||
m = sel_pat.match(line) | ||
if m: | ||
cond = m.group(3) | ||
if cond in platform_sel[platform]: | ||
yield line | ||
else: | ||
yield line |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
pyyaml | ||
requests | ||
jinja2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{% set version = "1.0.5" %} | ||
|
||
package: | ||
name: foo | ||
version: {{ version }} | ||
|
||
build: | ||
number: 0 | ||
script: | ||
- export PYTHONUNBUFFERED=1 # [ppc64le] | ||
- {{ PYTHON }} -m pip install --no-deps --ignore-installed . | ||
skip: True # [py2k] | ||
|
||
requirements: | ||
build: | ||
- {{ compiler('c') }} | ||
- {{ compiler('cxx') }} | ||
host: | ||
- python | ||
- pip | ||
- cython >=0.28.2 | ||
- numpy | ||
run: | ||
- python | ||
- {{ pin_compatible('numpy') }} | ||
- python-dateutil >=2.6.1 | ||
- pytz >=2017.2 | ||
- enum34 # [py27] | ||
- zlib # [unix] | ||
|
||
test: | ||
requires: | ||
- pytest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters