Skip to content

Commit

Permalink
feat: add rattler-build-conda-compat
Browse files Browse the repository at this point in the history
  • Loading branch information
nichmor committed Apr 10, 2024
0 parents commit c39ead9
Show file tree
Hide file tree
Showing 19 changed files with 7,012 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# GitHub syntax highlighting
pixi.lock linguist-language=YAML

23 changes: 23 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# name: Run updater that will check for conda-forge packages

on: push

jobs:
run_tests:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: prefix-dev/setup-pixi@v0.5.1
with:
pixi-version: "latest"

- name: pixi install
run: |
pixi install
- name: run tests
run: |
pixi run -e test pytest
166 changes: 166 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

mapping/*# pixi environments
.pixi
# pixi environments
.pixi

3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"python.analysis.typeCheckingMode": "basic"
}
15 changes: 15 additions & 0 deletions enviroment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: rattler-build-conda-compat
channels:
- conda-forge
- nodefaults
dependencies:
- python>=3.8
# Development dependencies
- pip
- python-build
- setuptools>=45
- rattler-build
- conda-build
- pytest
- syrupy
- ruff
6,095 changes: 6,095 additions & 0 deletions pixi.lock

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions pixi.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[project]
name = "rattler-build-conda-compat"
version = "0.1.0"
description = "Add a short description here"
authors = ["nichmor <nmorkotilo@gmail.com>"]
channels = ["conda-forge"]
platforms = ["win-64", "linux-64", "osx-64", "osx-arm64"]

[tasks]

[dependencies]
python = ">=3.8"
rattler-build = "*"
conda-build = "*"

[pypi-dependencies]
rattler_build = { path = ".", editable = true}


[feature.test.dependencies]
pytest = "*"
syrupy = "*"
ruff = "*"


[environments]
test = ["test"]
15 changes: 15 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[build-system]
requires = [
"setuptools>=45",
]
build-backend = "setuptools.build_meta"

[project]
name = "rattler-build-conda-compat"
description="A package for exposing rattler-build API for conda-smithy"
readme = "README.md"
authors = [{name = "Nichita Morcotilo", email = "nichita@prefix.dev"}]
license = {file = "LICENSE"}
version = "0.0.1"

requires-python = ">=3.8"
Empty file.
83 changes: 83 additions & 0 deletions src/rattler_build_conda_compat/loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
from contextlib import contextmanager
import yaml
from typing import Any


class RecipeLoader(yaml.BaseLoader):
@classmethod
@contextmanager
def with_namespace(cls, namespace):
try:
cls._namespace = namespace
yield
finally:
del cls._namespace

def construct_sequence(self, node: Any, deep: bool = False) -> Any:
"""deep is True when creating an object/mapping recursively,
in that case want the underlying elements available during construction
"""
# find if then else selectors
for sequence_idx, child_node in enumerate(node.value[:]):
# if then is only present in MappingNode

if isinstance(child_node, yaml.MappingNode):
# iterate to find if there is IF first

the_evaluated_one = None
for idx, (key_node, value_node) in enumerate(child_node.value):
if key_node.value == "if":
# we catch the first one, let's try to find next pair of (then | else)
then_node_key, then_node_value = child_node.value[idx + 1]

if then_node_key.value != "then":
raise ValueError(
"cannot have if without then, please reformat your variant file"
)

try:
_, else_node_value = child_node.value[idx + 2]
except IndexError:
_, else_node_value = None, None

to_be_eval = f"{value_node.value}"

evaled = eval(to_be_eval, self._namespace)
if evaled:
the_evaluated_one = then_node_value
elif else_node_value:
the_evaluated_one = else_node_value

if the_evaluated_one:
node.value.remove(child_node)
node.value.insert(sequence_idx, the_evaluated_one)
else:
# neither the evaluation or else node is present, so we remove this if
node.value.remove(child_node)

if not isinstance(node, yaml.SequenceNode):
raise Exception(
None,
None,
f"expected a sequence node, but found {node.id!s}",
node.start_mark,
)

return [self.construct_object(child, deep=deep) for child in node.value]


def remove_empty_keys(variant_dict):
filtered_dict = {}
for key, value in variant_dict.items():
if isinstance(value, list) and len(value) == 0:
continue
filtered_dict[key] = value

return filtered_dict


def parse_recipe_config_file(path, namespace):
with open(path) as f:
with RecipeLoader.with_namespace(namespace):
content = yaml.load(f, Loader=RecipeLoader)
return remove_empty_keys(content)
Loading

0 comments on commit c39ead9

Please sign in to comment.