Giter VIP home page Giter VIP logo

conda-lock's Introduction

conda-lock

GitHub deployments PyPI Conda pre-commit codecov

Conda lock is a lightweight library that can be used to generate fully reproducible lock files for conda environments.

It does this by performing a conda solve for each platform you desire a lockfile for.

This also has the added benefit of acting as an external pre-solve for conda as the lockfiles it generates results in the conda solver not being invoked when installing the packages from the generated lockfile.

Why?

Conda environment.yml files are very useful for defining desired environments but there are times when we want to be able to EXACTLY reproduce an environment by just installing and downloading the packages needed.

This is particularly handy in the context of a gitops style setup where you use conda to provision environments in various places.

Installation

Use one of the following commands:

pipx install conda-lock
condax install conda-lock
pip install conda-lock
conda install --channel=conda-forge --name=base conda-lock
mamba install --channel=conda-forge --name=base conda-lock

The first two options are recommended since they install conda-lock into an isolated environment. (Otherwise there is a risk of dependency conflicts.)

Contributing

If you would like to contribute to conda-lock, please refer to the Contributing Guide for instructions on how to set up your development environment.

Basic usage

# generate a multi-platform lockfile
conda-lock -f environment.yml -p osx-64 -p linux-64

# optionally, update the previous solution, using the latest version of
# pydantic that is compatible with the source specification
conda-lock --update pydantic

# create an environment from the lockfile
conda-lock install [-p {prefix}|-n {name}]

# alternatively, render a single-platform lockfile and use conda command directly
conda-lock render -p linux-64
conda create -n my-locked-env --file conda-linux-64.lock

Note: If there is an existing lockfile, it is used as constraint when regenerating the lockfile. This can be useful for adding new packages while keeping everything else locked.

Pre 1.0 compatible usage (explicit per platform locks)

If you were making use of conda-lock before the 1.0 release that added unified lockfiles you can still get that behaviour by making use of the explicit output kind.

conda-lock --kind explicit -f environment.yml

Advanced usage

File naming

By default, conda-lock store its output in conda-lock.yml in the current working directory. This file will also be used by default for render, install, and update operations. You can supply a different filename with e.g.

conda-lock --lockfile superspecial.conda-lock.yml

Rendered explicit and env lockfiles will be named as "conda-{platform}.lock" and "conda-{platform}.lock.yml respectively by default.

If you want to override that call conda-lock as follows.

conda-lock -k explicit --filename-template "specific-{platform}.conda.lock"

Compound specification

Conda-lock will build a spec list from several files if requested.

conda-lock -f base.yml -f specific.yml -p linux-64 -k explicit --filename-template "specific-{platform}.lock"

In this case all dependencies are combined, and the ordered union of all channels is used as the final specification.

This works for all supported file types.

channel overrides

You can override the channels that are used by conda-lock in case you need to override the ones specified in an environment.yml

conda-lock -c conda-forge -p linux-64

platform specification

You may specify the platforms you wish to target by default directly in an environment.yml using the (nonstandard) platforms key:

# environment.yml
channels:
  - conda-forge
dependencies:
  - python=3.9
  - pandas
platforms:
  - linux-64
  - osx-64
  - win-64
  - osx-arm64  # For Apple Silicon, e.g. M1/M2
  - linux-aarch64  # aka arm64, use for Docker on Apple Silicon
  - linux-ppc64le

If you specify target platforms on the command line with -p, these will override the values in the environment specification. If neither platforms nor -p are provided, conda-lock will fall back to a default set of platforms.

default category

You can may wish to split your dependencies into separate files for better organization, e.g. a environment.yml for production dependencies and a dev-environment.yml for development dependencies. You can assign all the dependencies parsed from a single file to a category using the (nonstandard) category key.

# dev-environment.yml
channels:
  - conda-forge
dependencies:
  - pytest
  - mypy=0.910
category: dev

The default category is main.

pip support

conda-lock can also lock the dependencies.pip section of environment.yml, using a vendored copy of Poetry's dependency solver.

private pip repositories

Right now conda-lock only supports legacy pypi repos with basic auth. Most self-hosted repositories like Nexus, Artifactory etc. use this. You can configure private pip repositories in a similar way to channels, for example:

channels:
  - conda-forge
pip-repositories:
  - http://$PIP_USER:[email protected]/api/pypi/simple
dependencies:
  - python=3.11
  - requests=2.26
  - pip:
    - fake-private-package==1.0.0

See the related docs for private channels to understand the rules regarding environment variable substitution.

Alternatively, you can use the poetry configuration file format to configure private PyPi repositories. The configuration file should be named config.toml and have the following format:

[repositories.example]
url = "https://username:[email protected]/simple"

The location of this file can be determined with python -c 'from conda_lock._vendor.poetry.locations import CONFIG_DIR; print(CONFIG_DIR)'

Private repositories will be used in addition to pypi.org. For projects using pyproject.toml, it is possible to disable pypi.org entirely.

--dev-dependencies/--no-dev-dependencies

By default conda-lock will include dev dependencies in the specification of the lock (if the files that the lock is being built from support them). This can be disabled easily

conda-lock --no-dev-dependencies -f ./recipe/meta.yaml

--check-input-hash

Under some situation you may want to run conda lock in some kind of automated way (eg as a precommit) and want to not need to regenerate the lockfiles if the underlying input specification for that particular lock as not changed.

conda-lock --check-input-hash -p linux-64

When the input_hash of the input files, channels match those present in a given lockfile, that lockfile will not be regenerated.

--strip-auth, --auth and --auth-file

By default conda-lock will leave basic auth credentials for private conda channels in the lock file. If you wish to strip authentication from the file, provide the --strip-auth argument.

conda-lock --strip-auth -f environment.yml

In order to conda-lock install a lock file with its basic auth credentials stripped, you will need to create an authentication file in .json format like this:

{
  "domain": "username:password"
}

If you have multiple channels that require different authentication within the same domain, you can additionally specify the channel like this:

{
  "domain.org/channel1": "username1:password1",
  "domain.org/channel2": "username2:password2"
}

You can provide the authentication either as string through --auth or as a filepath through --auth-file.

conda-lock install --auth-file auth.json conda-linux-64.lock

--virtual-package-spec

Conda makes use of virtual packages that are available at runtime to gate dependency on system features. Due to these not generally existing on your local execution platform conda-lock will inject them into the solution environment with a reasonable guess at what a default system configuration should be.

If you want to override which virtual packages are injected you can create a file like

# virtual-packages.yml
subdirs:
  linux-64:
    packages:
      __glibc: "2.17"
      __cuda: "11.4"
  win-64:
    packages:
      __cuda: "11.4"

conda-lock will automatically use a virtual-packages.yml it finds in the the current working directory. Alternatively one can be specified explicitly via the flag.

conda lock --virtual-package-spec virtual-packages-cuda.yml -p linux-64

Input hash stability

Virtual packages take part in the input hash so if you build an environment with a different set of virtual packages the input hash will change. Additionally the default set of virtual packages may be augmented in future versions of conda-lock. If you desire very stable input hashes we recommend creating a virtual-packages.yml file to lock down the virtual packages considered.

⚠️ in conjunction with micromamba

Micromamba does not presently support some of the overrides to remove all discovered virtual packages, consequently the set of virtual packages available at solve time may be larger than those specified in your specification.

Supported file sources

Conda lock supports more than just environment.yml specifications!

Additionally conda-lock supports meta.yaml (conda-build) and pyproject.toml ( flit, pdm and poetry based). These do come with some gotchas but are generally good enough for the 90% use-case.

meta.yaml

Conda-lock will attempt to make an educated guess at the desired environment spec in a meta.yaml. This is not guaranteed to work for complex recipes with many selectors and outputs. For multi-output recipes, conda-lock will fuse all the dependencies together. If that doesn't work for your case fall back to specifying the specification as an environment.yml

Since a meta.yaml doesn't contain channel information we make use of the following extra key to specify channels

# meta.yaml

extra:
  channels:
    - conda-forge
    - defaults

pyproject.toml

Since pyproject.toml files are commonly used by python packages it can be desirable to create a lock file directly from those dependencies to single-source a package's dependencies. This makes use of some conda-forge infrastructure (pypi-mapping) to do a lookup of the PyPI package name to a corresponding conda package name (e.g. docker -> docker-py). In cases where there exists no lookup for the package it assumes that the PyPI name, and the conda name are the same.

Channels

# pyproject.toml

[tool.conda-lock]
channels = [
    'conda-forge', 'defaults'
]

Platforms

Like in environment.yml, you can specify default platforms to target:

# pyproject.toml

[tool.conda-lock]
platforms = [
    'osx-arm64', 'linux-64'
]

Extras

If your pyproject.toml file contains optional dependencies/extras these can be referred to by using the --extras flag

# pyproject.toml

[tool.poetry.dependencies]
mandatory = "^1.0"
psycopg2 = { version = "^2.7", optional = true }
mysqlclient = { version = "^1.3", optional = true }

[tool.poetry.extras]
mysql = ["mysqlclient"]
pgsql = ["psycopg2"]

These can be referened as follows

conda-lock --extra mysql --extra pgsql -f pyproject.toml

When generating lockfiles that make use of extras it is recommended to make use of --filename-template covered here.

Filtering extras

By default conda-lock will attempt to solve for ALL extras/categories it discovers in sources. This allows you to render explicit locks with subset of extras, without needing a new solve.

However this does make the assumption that your extras can all be installed in conjunction with each other. If you want extras filtering to happen at the solve stage use the flag --filter-extras

conda-lock --extra incompatiblea --filter-extras -f pyproject.toml

Extra conda dependencies

Since in a pyproject.toml all the definitions are python dependencies if you need to specify some non-python dependencies as well this can be accomplished by adding the following sections to the pyproject.toml

# pyproject.toml

[tool.conda-lock.dependencies]
sqlite = ">=3.34"

pip dependencies

If a dependency refers directly to a URL rather than a package name and version, conda-lock will assume it is pip-installable, e.g.:

# pyproject.toml
[tool.poetry.dependencies]
python = "3.9"
pymage = {url = "https://github.com/MickaelRigault/pymage/archive/v1.0.tar.gz#sha256=11e99c4ea06b76ca7fb5b42d1d35d64139a4fa6f7f163a2f0f9cc3ea0b3c55eb"}

Similarly, if a dependency is explicitly marked with source = "pypi", it will be treated as a pip dependency, e.g.:

[tool.poetry.dependencies]
python = "3.9"
ampel-ztf = {version = "^0.8.0-alpha.2", source = "pypi"}

A dependency will also be treated as a pip dependency if explicitly marked with source = "pypi" in the [tool.conda-lock.dependencies] section, e.g.:

[tool.conda-lock.dependencies]
ampel-ztf = {source = "pypi"}
Defaulting non-conda dependency sources to PyPI

Alternatively, the above behavior is defaulted for all dependencies defined outside of [tool.conda-lock.dependencies], i.e.:

  • Default to pip dependencies for [tool.poetry.dependencies], [project.dependencies], etc.
  • Default to conda dependencies for [tool.conda-lock.dependencies]

by explicitly providing default-non-conda-source = "pip" in the [tool.conda-lock] section, e.g.:

[tool.conda-lock]
default-non-conda-source = "pip"

In all cases, the dependencies of pip-installable packages will also be installed with pip, unless they were already requested by a conda dependency.

Lock only conda-lock dependencies

To lock only dependencies specified under [tool.conda-lock] (i.e. skipping all dependencies specified elsewhere), explicitly provide skip-non-conda-lock = true in the [tool.conda-lock] section, e.g.:

[tool.conda-lock]
skip-non-conda-lock = true

Disabling pypi.org

When using private pip repos, it is possible to disable pypi.org entirely. This can be useful when using conda-lock behind a network proxy that does not allow access to pypi.org.

[tool.conda-lock]
allow-pypi-requests = false

Dockerfile example

In order to use conda-lock in a docker-style context you want to add the lockfile to the docker container. In order to refresh the lock file just run conda-lock again.

Given a file tree like

  Dockerfile
  environment.yaml
* conda-linux-64.lock

You want a dockerfile that is structured something similar to this

# Dockerfile

# Build container
FROM continuumio/miniconda:latest as conda

ADD conda-linux-64.lock /locks/conda-linux-64.lock
RUN conda create -p /opt/env --copy --file /locks/conda-linux-64.lock

# Primary container

FROM gcr.io/distroless/base-debian10

COPY --from=conda /opt/env /opt/env

conda-lock's People

Contributors

basnijholt avatar bollwyvl avatar dbast avatar ericdill avatar jacksmith15 avatar janjagusch avatar jonashaag avatar jvansanten avatar leroyvn avatar lesteve avatar marcelotrevisani avatar maresb avatar mariusvniekerk avatar matthewwardrop avatar mfisher87 avatar minrk avatar munali avatar natproach avatar ocefpaf avatar pep-sanwer avatar pre-commit-ci[bot] avatar renovate[bot] avatar riccardoporreca avatar romain-intel avatar scopatz avatar sebastian-luna-valero avatar sfinkens avatar shopigarner avatar srilman avatar tadeu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

conda-lock's Issues

excessive terminal output with conda-lock from pypi 0.2.1

running 0.2.1 from pypi by default I'm seeing a ton of output that should probably not be printed out. here is an excerpt:
conda-lock -f environment.yml -p linux-64

  {'arch': None,
   'build': 'py_0',
   'build_number': 0,
   'channel': 'https://conda.anaconda.org/conda-forge/noarch',
   'constrains': [],
   'depends': ['python'],
   'fn': 'toolz-0.10.0-py_0.tar.bz2',
   'license': 'BSD 3-Clause',
   'md5': '9b38c091d24a308daf386f1e82d9d3a9',
   'name': 'toolz',
   'noarch': 'python',
   'package_type': 'noarch_python',
   'platform': None,
   'sha256': '70a39ffae5f25a1dc03ecde8546fb69ad7ad4c4a16aaffd54dabb392bc026215',
   'size': 47341,
   'subdir': 'noarch',
   'timestamp': 1562969375652,
   'url': 'https://conda.anaconda.org/conda-forge/noarch/toolz-0.10.0-py_0.tar.bz2',
   'version': '0.10.0'}])
To use the generated lock files create a new environment:

     conda create --name YOURENV --file conda-linux-64.lock

Pinning subset requirements

When developing, we will install much more dependencies at runtime. We still would like to pin the runtime and the development/CI dependencies to the exact same versions. This should result in two lockfiles where one is a subset of the other.

Given the following environment.yml:

name: nyc-taxi-fare-prediction-deployment-example
channels:
  - conda-forge
  - nodefaults
dependencies:
  - click
  - jupyterlab  # [dev]

and the following command: conda-lock -f environment.yml --subset "core|dev=0"

I would expect two files conda-linux-64.lock and conda-linux-64-core.lock where in the latter jupyterlab and its dependencies are omitted but all other packages are the same version.

Does this sound like a reasonable proposal? If so, I would start working on this.

KeyError: 'ca-certificates-2019.11.28-hecc5488_0'

The following environment.yml fails to lock:

name: pangeo
channels:
  - conda-forge
dependencies:
  - python
  - bokeh
  - cartopy
  - cython
  - dask
  - dask-cloudprovider
  - erddapy
  - numpy
  - python-blosc
  - hvplot
  - h5py
  - h5netcdf
  - ipykernel
  - ipywidgets
  - geoviews
  - holoviews
  - lz4
  - datashader
  - panel
  - metpy
  - netcdf4
  - xarray
  - s3fs
  - gcsfs
  - fsspec
  - utide
  - zarr
  - earthsim
sh-4.2$ conda-lock -f pangeo_env.yml -p linux-64
generating lockfile for linux-64
Traceback (most recent call last):
  File "/home/ec2-user/anaconda3/bin/conda-lock", line 8, in <module>
    sys.exit(main())
  File "/home/ec2-user/anaconda3/lib/python3.6/site-packages/conda_lock/conda_lock.py", line 124, in main
    platforms=args.platform or DEFAULT_PLATFORMS,
  File "/home/ec2-user/anaconda3/lib/python3.6/site-packages/conda_lock/conda_lock.py", line 84, in make_lock_files
    url = urls[pkg["dist_name"]]
KeyError: 'ca-certificates-2019.11.28-hecc5488_0'
sh-4.2$

Error - missing -c / --channel flag

conda-lock calls conda which generates the exception "At least one -c / --channel flag must be supplied when using --override-channels." More output is attached.

I'm running on MacOS Catalina (10.15.5) and miniconda 4.8.3.

Am I doing something wrong? Or is this a bug?

conda-lock

generating lockfile for osx-64
Could not lock the environment for platform osx-64
At least one -c / --channel flag must be supplied when using --override-channels.

    Command: [PosixPath('/usr/local/miniconda3/condabin/conda'), 'create', '--prefix', PosixPath('/var/folders/5t/pbt36_pd4gj809tc251v987r0000gn/T/tmpct7gii0w/prefix'), '--override-channels', '--dry-run', '--json', 'python=2.7', 'enum34', 'numpy', 'business_calendar', 'oktopuss_core>=0.5']
    STDOUT:
{
  "caused_by": "None",
  "command": "/usr/local/miniconda3/condabin/conda create --prefix /var/folders/5t/pbt36_pd4gj809tc251v987r0000gn/T/tmpct7gii0w/prefix --override-channels --dry-run --json python=2.7 enum34 numpy business_calendar oktopuss_core>=0.5",
  "error": "CommandArgumentError: At least one -c / --channel flag must be supplied when using --override-channels.\n",
  "exception_name": "CommandArgumentError",
  "exception_type": "<class 'conda.exceptions.CommandArgumentError'>",
  "message": "At least one -c / --channel flag must be supplied when using --override-channels.\n"
}

conda info

         conda version : 4.8.3
    conda-build version : 3.18.11
         python version : 3.7.7.final.0
       virtual packages : __osx=10.15.5

[Bug] Fix error handling for mamba install

I noticed that the error handling breaks sometimes when using --mamba.
For example, here I am using a lock file that has its basic auth stripped. So I expect a 401 Unauthorized error to occur.

The error is raised correctly without the --mamba argument

Failed to parse json, Extra data: line 2 column 1 (char 76)
Could not perform conda install using /var/folders/mj/2sx68gpn1bldjjpwtbqs8gfr0000gn/T/tmpt60id44_ lock file into None
    Command: ['/usr/local/Caskroom/miniforge/base/bin/conda', 'create', '--file', '/var/folders/mj/2sx68gpn1bldjjpwtbqs8gfr0000gn/T/tmpt60id44_', '--yes', '--json', '--name', 'test']
    STDOUT:
{"fetch":"qc_drg_grouper_binar | ","finished":true,"maxval":1,"progress":1}
{
  "error": "Multiple Errors Encountered.",
  "errors": [
    {
      "caused_by": "HTTPError('401 Client Error: Unauthorized for url: <url to package>')",
      "elapsed_time": "00:00.127258",
      "error": "CondaHTTPError: HTTP 401 UNAUTHORIZED for url <<url to package>>\nElapsed: 00:00.127258\n\nAn HTTP error occurred when trying to retrieve this URL.\nHTTP errors are often intermittent, and a simple retry will get you on your way.\n",
      "exception_name": "CondaHTTPError",
      "exception_type": "<class 'conda.exceptions.CondaHTTPError'>",
      "message": "HTTP 401 UNAUTHORIZED for url <<url to package>>\nElapsed: 00:00.127258\n\nAn HTTP error occurred when trying to retrieve this URL.\nHTTP errors are often intermittent, and a simple retry will get you on your way.\n",
      "reason": "UNAUTHORIZED",
      "response_details": "",
      "status_code": 401,
      "url": "<url to package>"
    }
  ],
  "exception_name": "CondaMultiError",
  "exception_type": "<class 'conda.CondaMultiError'>"
}

But once I add the --mamba argument, the error handling fails with KeyError: 'message'

Traceback (most recent call last):
  File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/conda_lock/conda_lock.py", line 163, in do_conda_install
    proc.check_returncode()
  File "/usr/local/Caskroom/miniforge/base/lib/python3.8/subprocess.py", line 444, in check_returncode
    raise CalledProcessError(self.returncode, self.args, self.stdout,
subprocess.CalledProcessError: Command '['/usr/local/Caskroom/miniforge/base/bin/mamba', 'create', '--file', '/var/folders/mj/2sx68gpn1bldjjpwtbqs8gfr0000gn/T/tmpat1dqpf7', '--yes', '--json', '--name', 'test']' returned non-zero exit status 1.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "./bin/conda-lock-no-auth", line 228, in <module>
    main()
  File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/click/core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/click/core.py", line 1259, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "./bin/conda-lock-no-auth", line 224, in install
    do_conda_install(conda=_conda_exe, prefix=prefix, name=name, file=lock_file, auth=auth)
  File "./bin/conda-lock-no-auth", line 112, in do_conda_install
    _do_conda_install(conda=conda, prefix=prefix, name=name, file=file)
  File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/conda_lock/conda_lock.py", line 168, in do_conda_install
    message = err_json["message"]
KeyError: 'message'

This is the format of the mamba err_json:

{
    "error": "Multiple Errors Encountered.",
    "errors": [
        {
            "caused_by": "HTTPError("401 Client Error: Unauthorized for url: <url to package>")",
            "elapsed_time": "00: 00.182042",
            "error": "CondaHTTPError: HTTP 401 UNAUTHORIZED for url <<url to package>>\nElapsed: 00: 00.182042\n\nAn HTTP error occurred when trying to retrieve this URL.\nHTTP errors are often intermittent, and a simple retry will get you on your way.\n",
            "exception_name": "CondaHTTPError",
            "exception_type": "<class "conda.exceptions.CondaHTTPError">",
            "message": "HTTP 401 UNAUTHORIZED for url <<url to package>>\nElapsed: 00: 00.182042\n\nAn HTTP error occurred when trying to retrieve this URL.\nHTTP errors are often intermittent, and a simple retry will get you on your way.\n",
            "reason": "UNAUTHORIZED",
            "response_details": "",
            "status_code": 401,
            "url": "<url to package>"
        }
    ],
    "exception_name": "CondaMultiError",
    "exception_type": "<class "conda.CondaMultiError">"
}

My suggestion is to also handle the KeyError and print err_json in that case.

Note: I replaced the actual url with <url to package> in all examples.

KeyError when doing `conda-lock`

$ conda-lock -p linux-64
generating lockfile for linux-64

Traceback (most recent call last):
  File "/home/itamarst/.local/bin/conda-lock", line 8, in <module>
    sys.exit(main())
  File "/home/itamarst/.local/lib/python3.9/site-packages/conda_lock/conda_lock.py", line 400, in main
    run_lock(
  File "/home/itamarst/.local/lib/python3.9/site-packages/conda_lock/conda_lock.py", line 389, in run_lock
    make_lock_files(
  File "/home/itamarst/.local/lib/python3.9/site-packages/conda_lock/conda_lock.py", line 200, in make_lock_files
    lockfile_contents = create_lockfile_from_spec(
  File "/home/itamarst/.local/lib/python3.9/site-packages/conda_lock/conda_lock.py", line 251, in create_lockfile_from_spec
    url = fetch_by_dist_name[pkg["dist_name"]]["url"]
KeyError: '_libgcc_mutex-0.1-conda_forge'

Happens with both install via pip and install via conda install; should be latest version in both cases (0.7.2).

environment.yml:

name: example
channels:
  - conda-forge
dependencies:
  - python=3.8
  - pandas=1.0

.condarc:

channel_priority: strict

I also tried with Docker mode, but... that didn't seem to run a Docker container, to my confusion (#66) so can't tell if that'd fix it.

Deleting .condarc had no effect. --no-mamba had no effect. -p mac-64 fails with a different package.

Regression: Multiple platforms not processed correctly

Fix has been submitted as #107. Regression was introduced in 9aa90dc and present in release 0.11.2.

If multiple platforms are specified, only the first is processed and the log incorrectly reports the platform name as value of sys.platform. See example output below.

Example output:

> python -m conda_lock lock --kind explicit -p win-64 -p linux-64 -f "tmp/optimon-requirements.yml" --filename-template "devops/requirements/optimon-{platform}.lock"
Generating lockfile(s) for win32...
 - Install lock using : conda create --name YOURENV --file devops/requirements/optimon-linux-64.lock

[Feature] Lock and install without basic auth credentials

Hi, thanks for maintaining this package! 🚀

We're using conda-lock at work and it has proven super useful to us. One issue we're facing is that the generated lock files can contain basic auth credentials for private conda channels. This makes it very easy to accidentally commit secrets to version control. At the same time you can't install lock file without basic auth credentials, because conda doesn't offer a way to pass them to the install (conda/conda#6969).

So my feature proposal is:

  • Add a --no-auth flag to conda-lock lock to stip basic auth credentials from the lock file.
  • Add an --auth argument to conda-lock install to provide basic auth credentials separate from the lock file (even though you could argue this is something that should be introduced upstream).

I was wondering what you think about this feature request and whether you consider it "in scope" for conda-lock? If you like the idea, I'd happily open a PR against it. 👍

We've dealt with this problem on our end so far by adding a bit of regex to the run_lock and do_conda_install functions. You can find more details about the implementation in the collapsible below. Obviously the change would be much smaller if we introduced it to the internals of conda-lock.

Details
  #!/usr/bin/env python

  import os
  import pathlib
  import re
  from contextlib import contextmanager
  from tempfile import NamedTemporaryFile, TemporaryDirectory
  from typing import Dict, Iterable, List, Optional, Sequence

  import click
  from conda_lock.conda_lock import PathLike, determine_conda_executable
  from conda_lock.conda_lock import do_conda_install as _do_conda_install
  from conda_lock.conda_lock import main
  from conda_lock.conda_lock import run_lock as _run_lock

  # Captures basic auth credentials, if they exists, in the second capture group.
  # Can handle https and http. Test on regex101.com with the following examples:
  # https://conda.mychannel.cloud/mypackage
  # https://user:[email protected]/mypackage
  # http://conda.mychannel.cloud/mypackage
  # http://user:[email protected]/mypackage
  BASIC_AUTH_PATTERN = re.compile(r"^(https?:\/\/)(.*:.*@)?(.*)")

  # Captures the domain in the second group.
  # Can handle https and http. Test on regex101.com with the following examples:
  # https://conda.mychannel.cloud/mypackage
  # http://conda.mychannel.cloud/mypackage
  DOMAIN_PATTERN = re.compile(r"^(https?:\/\/)?([^\/]+)(.*)")


  def _remove_basic_auth_line(line: str) -> str:
      return BASIC_AUTH_PATTERN.sub(r"\1\3", line)


  def _read_lockfile(filepath: str) -> Iterable[str]:
      with open(filepath, mode="r") as fp:
          return (line.strip() for line in fp.read().split("\n") if line)


  def _write_lockfile(lockfile: Iterable[str], filepath: str) -> None:
      with open(filepath, mode="w") as fp:
          fp.write(
              "# This is a specific lockfile with its basic auth credentials stripped.\n"
          )
          for line in lockfile:
              fp.write(f"{line}\n")


  def _remove_basic_auth(from_file: str, to_file: str) -> None:
      lockfile = _read_lockfile(from_file)
      lockfile = tuple(
          _remove_basic_auth_line(line) if line[0] not in ("#", "@") else line for line in lockfile
      )
      _write_lockfile(lockfile, to_file)


  def run_lock(
      environment_files: List[pathlib.Path],
      conda_exe: Optional[str],
      platforms: Optional[List[str]] = None,
      mamba: bool = False,
      micromamba: bool = False,
      include_dev_dependencies: bool = True,
      channel_overrides: Optional[Sequence[str]] = None,
      filename_template: Optional[str] = None,
  ):
      with TemporaryDirectory() as tempdir:
          filename_template_temp = f"{tempdir}/{filename_template.split('/')[-1]}"
          _run_lock(
              environment_files=environment_files,
              conda_exe=conda_exe,
              platforms=platforms,
              mamba=mamba,
              micromamba=micromamba,
              include_dev_dependencies=include_dev_dependencies,
              channel_overrides=channel_overrides,
              filename_template=filename_template_temp,
          )
          filename_template_dir = "/".join(filename_template.split("/")[:-1])
          for file in os.listdir(tempdir):
              _remove_basic_auth(
                  os.path.join(tempdir, file), os.path.join(filename_template_dir, file)
              )


  def _add_auth_line(line: str, auth):
      search = DOMAIN_PATTERN.search(line)
      if search.group(2) in auth:
          return f"{search.group(1)}{auth[search.group(2)]}@{search.group(2)}{search.group(3)}"
      return line


  def _add_auth(from_file: str, to_file: str, auth) -> None:
      lockfile = _read_lockfile(from_file)
      lockfile = tuple(
          _add_auth_line(line, auth) if line[0] not in ("#", "@") else line for line in lockfile
      )
      _write_lockfile(lockfile, to_file)


  @contextmanager
  def add_auth(filepath, auth):
      with NamedTemporaryFile() as tempfile:
          _add_auth(filepath, tempfile.name, auth)
          yield tempfile.name


  def do_conda_install(
      conda: PathLike, prefix: str, name: str, file: str, auth: Dict[str, str]
  ) -> None:
      with add_auth(file, auth) as file:
          _do_conda_install(conda=conda, prefix=prefix, name=name, file=file)


  def _parse_auth(auth: str) -> Dict[str, str]:
      if auth:
          return dict((val.split("=") for val in auth.split(",")))
      return {}


  @main.command("lock")
  @click.option("--conda", default=None, help="path (or name) of the conda/mamba executable to use.")
  @click.option("--mamba/--no-mamba", default=False, help="don't attempt to use or install mamba.")
  @click.option(
      "--micromamba/--no-micromamba",
      default=False,
      help="don't attempt to use or install micromamba.",
  )
  @click.option(
      "-p",
      "--platform",
      multiple=True,
      help="generate lock files for the following platforms",
  )
  @click.option(
      "-c",
      "--channel",
      "channel_overrides",
      multiple=True,
      help="""Override the channels to use when solving the environment. These will replace the channels as listed in the various source files.""",
  )
  @click.option(
      "--dev-dependencies/--no-dev-dependencies",
      is_flag=True,
      default=True,
      help="include dev dependencies in the lockfile (where applicable)",
  )
  @click.option(
      "-f",
      "--file",
      "files",
      default=["environment.yml"],
      type=click.Path(),
      multiple=True,
      help="path to a conda environment specification(s)",
  )
  @click.option(
      "--filename-template",
      default="conda-{platform}.lock",
      help="Template for the lock file names. Must include {platform} token. For a full list and description of available tokens, see the command help text.",
  )
  @click.option(
      "--auth/--no-auth",
      is_flag=True,
      default=False,
      help="include basic auth credentials in the lockfile (where applicable)",
  )
  def lock(
      conda,
      mamba,
      micromamba,
      platform,
      channel_overrides,
      dev_dependencies,
      files,
      filename_template,
      auth,
  ):
      """Generate fully reproducible lock files for conda environments.
      By default, the lock files are written to conda-{platform}.lock. These filenames can be customized using the
      --filename-template argument. The following tokens are available:
      \b
          platform: The platform this lock file was generated for (conda subdir).
          dev-dependencies: Whether or not dev dependencies are included in this lock file.
          spec-hash: A sha256 hash of the lock file spec.
          version: The version of conda-lock used to generate this lock file.
          timestamp: The approximate timestamp of the output file in ISO8601 basic format.
      """
      files = [pathlib.Path(file) for file in files]
      func = _run_lock if auth else run_lock
      func(
          environment_files=files,
          conda_exe=conda,
          platforms=platform,
          mamba=mamba,
          micromamba=micromamba,
          include_dev_dependencies=dev_dependencies,
          channel_overrides=channel_overrides,
          filename_template=filename_template,
      )


  @main.command("install")
  @click.option("--conda", default=None, help="path (or name) of the conda/mamba executable to use.")
  @click.option("--mamba/--no-mamba", default=False, help="don't attempt to use or install mamba.")
  @click.option(
      "--micromamba/--no-micromamba",
      default=False,
      help="don't attempt to use or install micromamba.",
  )
  @click.option("-p", "--prefix", help="Full path to environment location (i.e. prefix).")
  @click.option("-n", "--name", help="Name of environment.")
  @click.option(
      "-a",
      "--auth",
      help="Comma separated list of `<domain>=<username:password>` mappings.",
      default="",
  )
  @click.argument("lock-file")
  def install(conda, mamba, micromamba, prefix, name, auth, lock_file):
      """Perform a conda install"""
      auth = _parse_auth(auth)
      _conda_exe = determine_conda_executable(conda, mamba=mamba, micromamba=micromamba)
      do_conda_install(conda=_conda_exe, prefix=prefix, name=name, file=lock_file, auth=auth)


  if __name__ == "__main__":
      main()

Unable to create lock with cuda package(s) from a Mac

This environment can generate a valid lock on a linux machine but not on a mac. I'm not exactly sure if this is a conda-lock or mamba/conda issue related to virtual packages and cuda support, but did find it surprising not to be able to generate the linux lock from a mac in this case (one of the really nice features of conda-lock).

Linux:

cat cuda-constrained.yaml
name: cuda
channels:
  - conda-forge
dependencies:
  - cudatoolkit =11.0
  - cudnn =8.0

conda-lock lock --mamba -f cuda-constrained.yaml -p linux-64 --filename-template 'cuda-constrained.lock'

cat cuda-constrained.lock
# platform: linux-64
# env_hash: 231edd623703d47e04a863c039244ba0f9e29e4dcd36589dd12e3052e58bb6c7
@EXPLICIT
https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2#d7c89558ba9fa0495403155b64376d81
https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-11.1.0-h56837e0_6.tar.bz2#a7420de095361151e2a4d2687ad39292
https://conda.anaconda.org/conda-forge/linux-64/libgomp-11.1.0-hc902ee8_6.tar.bz2#4643448d355a09dd587ffd8838acf8e3
https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-1_gnu.tar.bz2#561e277319a41d4f24f5c05a9ef63c04
https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-11.1.0-hc902ee8_6.tar.bz2#3dbb18ea1f6e616bc59d7b51640d2af1
https://conda.anaconda.org/conda-forge/linux-64/cudatoolkit-11.0.3-h15472ef_8.tar.bz2#afed8db569f6974fdcd5e9f362985bf2
https://conda.anaconda.org/conda-forge/linux-64/cudnn-8.0.5.39-ha5ca753_1.tar.bz2#8a89f290d4175f8f11c5ddba81fd16d6

Mac:

Mac OS

conda-lock lock --mamba -f cuda-constrained.yaml -p linux-64 --filename-template 'cuda-constrained.lock'
generating lockfile for linux-64
Could not solve for lock
    Command: ['mamba', 'create', '--prefix', '/var/folders/m0/7xmfqfjn1l9btlt1m971ldz80000gp/T/tmpk511_yer/prefix', '--dry-run', '--json', '--override-channels', '--channel', 'conda-forge', 'cudnn =8.0', 'cudatoolkit =11.0']
    STDOUT:
Encountered problems while solving.
Problem: nothing provides __glibc >=2.17,<3.0.a0 needed by cudnn-8.0.5.39-h01f27c4_1
Problem: nothing provides __glibc >=2.17,<3.0.a0 needed by cudatoolkit-11.0.3-h15472ef_6

If I unconstrain the cudnn and cudatoolkit versions, it can solve on mac, but only for old versions:

cat cuda-unconstrained.yaml
name: cuda
channels:
  - conda-forge
dependencies:
  - cudatoolkit
  - cudnn

conda-lock lock --mamba -f cuda-unconstrained.yaml -p linux-64 --filename-template 'cuda-unconstrained.lock'

cat cuda-unconstrained.lock
# platform: linux-64
# env_hash: 9dff44ba64e18168663ddb810849ebe8ea25f234505d51f4c27183f6b8d297a6
@EXPLICIT
https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2#d7c89558ba9fa0495403155b64376d81
https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-11.1.0-h56837e0_6.tar.bz2#a7420de095361151e2a4d2687ad39292
https://conda.anaconda.org/conda-forge/linux-64/libgomp-11.1.0-hc902ee8_6.tar.bz2#4643448d355a09dd587ffd8838acf8e3
https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-1_gnu.tar.bz2#561e277319a41d4f24f5c05a9ef63c04
https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-11.1.0-hc902ee8_6.tar.bz2#3dbb18ea1f6e616bc59d7b51640d2af1
https://conda.anaconda.org/conda-forge/linux-64/cudatoolkit-10.2.89-h8f6ccaa_8.tar.bz2#fbfd851ae18bd2e0f84c9de59df7a514
https://conda.anaconda.org/conda-forge/linux-64/cudnn-7.6.5.32-h01f27c4_1.tar.bz2#298362896ec792e4a73d59dea331c999

Conda-lock Pytorch GPU Different Behavior

We're trying to be able to generate lockfiles with pytorch 1.8 and cuda 11.1 for linux, but have been running into issues generating it on osx.

conda 4.9.2
conda-lock 0.7.2

Given an environment file such as:

channels:
 - pytorch
 - conda-forge
 - defaults
dependencies:
 - pytorch=1.8.0
 - cudatoolkit==11.1.1

On linux:
conda-lock --no-mamba -f torch.yml -p linux-64

This is what we want

❯❯ cat conda-linux-64.lock 
# platform: linux-64
# env_hash: 69363a5aaf573ec3d86f9d579ac7b215710b92b68d1f39a8c542fbf8716ebdaf
@EXPLICIT
https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2#d7c89558ba9fa0495403155b64376d81
https://repo.anaconda.com/pkgs/main/linux-64/blas-1.0-mkl.conda#9a7a051e9bd41da46523acb017d8a517
https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2020.12.5-ha878542_0.tar.bz2#7eb5d4ffeee663caa1635cd67071bc1b
https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.35.1-hea4e1c9_2.tar.bz2#83610dba766a186bdc7a116053b782a4
https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-9.3.0-h6de172a_18.tar.bz2#2f03cd1e5c966d4af5822c7ae089ab03
https://conda.anaconda.org/conda-forge/linux-64/llvm-openmp-11.0.1-h4bd325d_0.tar.bz2#8cf85a6eeaee28674a6124298e4f94b2
https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-1_llvm.tar.bz2#fa8d764c883a53d22ce622bea830c818
https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-9.3.0-h2828fa1_18.tar.bz2#5a9490c49a3505a6d19bda012cde6ad3
https://conda.anaconda.org/conda-forge/linux-64/mkl-2020.4-h726a3e6_304.tar.bz2#b9b35a50e5377b19da6ec0709ae77fc3
https://conda.anaconda.org/conda-forge/linux-64/cudatoolkit-11.1.1-h6406543_8.tar.bz2#4851e7f19b684e517dc8e6b5b375dda0
https://conda.anaconda.org/conda-forge/linux-64/libffi-3.3-h58526e2_2.tar.bz2#665369991d8dd290ac5ee92fce3e6bf5
https://conda.anaconda.org/conda-forge/linux-64/libuv-1.41.0-h7f98852_0.tar.bz2#808b41ebae1d9bd4aa8ffbc365d468c6
https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.2-h58526e2_4.tar.bz2#509f2a21c4a09214cd737a480dfd80c9
https://conda.anaconda.org/conda-forge/linux-64/ninja-1.10.2-h4bd325d_0.tar.bz2#15aa96cc0ff141127a8da4c5bb6486d7
https://conda.anaconda.org/conda-forge/linux-64/openssl-1.1.1j-h7f98852_0.tar.bz2#f91545bee2ac8cf86f1dc53e55a7bb2b
https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.5-h516909a_1.tar.bz2#33f601066901f3e1a85af3522a8113f9
https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.11-h516909a_1010.tar.bz2#339cc5584e6d26bc73a875ba900028c3
https://conda.anaconda.org/conda-forge/linux-64/readline-8.0-he28a2e2_2.tar.bz2#4d0ae8d473f863696088f76800ef9d38
https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.10-h21135ba_1.tar.bz2#c647f70aa7e3d4cc4e029cc1c9a99953
https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.34.0-h74cdb3f_0.tar.bz2#0a83e21e8c1929cc9a1e21ebb2459fc5
https://conda.anaconda.org/conda-forge/linux-64/python-3.8.8-hffdb5ce_0_cpython.tar.bz2#da5f00968a732f5da324fff565909a05
https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.8-1_cp38.tar.bz2#8d05152d6fb3012b27a0e6fbcc14bea1
https://conda.anaconda.org/conda-forge/noarch/six-1.15.0-pyh9f0ad1d_0.tar.bz2#1eec421f0f1f39e579e44e4a5ce646a2
https://conda.anaconda.org/conda-forge/noarch/typing_extensions-3.7.4.3-py_0.tar.bz2#12b96e382730541a4b332420227055ae
https://conda.anaconda.org/conda-forge/linux-64/mkl-service-2.3.0-py38h1e0a361_2.tar.bz2#7fbe577a8215f1b422534a7d03979e1b
https://repo.anaconda.com/pkgs/main/linux-64/numpy-base-1.19.2-py38hfa32c7d_0.conda#96e71076ea262302106ebb2f823a6670
https://conda.anaconda.org/conda-forge/linux-64/mkl_fft-1.3.0-py38h5c078b8_1.tar.bz2#deef06457fa7c41305ae678d98baa028
https://conda.anaconda.org/conda-forge/linux-64/mkl_random-1.2.0-py38hc5bc63f_1.tar.bz2#c8551fa553153a0ffc10b211a625f658
https://repo.anaconda.com/pkgs/main/linux-64/numpy-1.19.2-py38h54aff64_0.conda#f63dfd30b7bbac33e0c9ee4924ffefda
https://conda.anaconda.org/pytorch/linux-64/pytorch-1.8.0-py3.8_cuda11.1_cudnn8.0.5_0.tar.bz2#b004015b61f8a1a7cf35f65a71615eaa

On OSX:

conda-lock --no-mamba -f torch.yml -p linux-64
generating lockfile for linux-64
Could not lock the environment for platform linux-64
The following specifications were found to be incompatible with each other:

Output in format: Requested package -> Available versions

Package cudatoolkit conflicts for:
pytorch=1.8.0 -> cudatoolkit[version='>=10.1,<10.2|>=11.1,<11.2|>=10.2,<10.3']
cudatoolkit==11.1.1
    Command: ['/Users/kevzheng/conda/bin/conda', 'create', '--prefix', '/var/folders/md/x005k2x90f3_l7z0jytkc5040000gn/T/tmp6v7v1hhb/prefix', '--dry-run', '--json', '--override-channels', '--channel', 'pytorch', '--channel', 'conda-forge', '--channel', 'defaults', 'pytorch=1.8.0', 'cudatoolkit==11.1.1']
    STDOUT:
{
  "caused_by": "None",
  "error": "UnsatisfiableError: The following specifications were found to be incompatible with each other:\n\nOutput in format: Requested package -> Available versions\n\nPackage cudatoolkit conflicts for:\npytorch=1.8.0 -> cudatoolkit[version='>=10.1,<10.2|>=11.1,<11.2|>=10.2,<10.3']\ncudatoolkit==11.1.1",
  "exception_name": "UnsatisfiableError",
  "exception_type": "<class 'conda.exceptions.UnsatisfiableError'>",
  "message": "The following specifications were found to be incompatible with each other:\n\nOutput in format: Requested package -> Available versions\n\nPackage cudatoolkit conflicts for:\npytorch=1.8.0 -> cudatoolkit[version='>=10.1,<10.2|>=11.1,<11.2|>=10.2,<10.3']\ncudatoolkit==11.1.1"
}

It looks like even though the linux-64 subdir is set on mac, the solver doesn't seem to find the pytorch binary compiled with cuda 11.1.

If I explicitly set the pytorch version:

channels:
 - pytorch
 - conda-forge
 - defaults
dependencies:
 - pytorch=1.8.0=py3.6_cuda11.1_cudnn8.0.5_0
 - cudatoolkit==11.1.1
conda-lock --no-mamba -f torch.yml -p linux-64
generating lockfile for linux-64
Could not lock the environment for platform linux-64
The following specifications were found to be incompatible with each other:

Output in format: Requested package -> Available versions

Package cudatoolkit conflicts for:
cudatoolkit==11.1.1
pytorch==1.8.0=py3.6_cuda11.1_cudnn8.0.5_0 -> cudatoolkit[version='>=11.1,<11.2']The following specifications were found to be incompatible with your system:

  - cudatoolkit==11.1.1 -> __glibc[version='>=2.17,<3.0.a0']

Your installed version is: not available

    Command: ['/Users/kevzheng/conda/bin/conda', 'create', '--prefix', '/var/folders/md/x005k2x90f3_l7z0jytkc5040000gn/T/tmpen271mhd/prefix', '--dry-run', '--json', '--override-channels', '--channel', 'pytorch', '--channel', 'conda-forge', '--channel', 'defaults', 'pytorch=1.8.0=py3.6_cuda11.1_cudnn8.0.5_0', 'cudatoolkit==11.1.1']
    STDOUT:
{
  "caused_by": "None",
  "error": "UnsatisfiableError: The following specifications were found to be incompatible with each other:\n\nOutput in format: Requested package -> Available versions\n\nPackage cudatoolkit conflicts for:\ncudatoolkit==11.1.1\npytorch==1.8.0=py3.6_cuda11.1_cudnn8.0.5_0 -> cudatoolkit[version='>=11.1,<11.2']The following specifications were found to be incompatible with your system:\n\n  - cudatoolkit==11.1.1 -> __glibc[version='>=2.17,<3.0.a0']\n\nYour installed version is: not available\n",
  "exception_name": "UnsatisfiableError",
  "exception_type": "<class 'conda.exceptions.UnsatisfiableError'>",
  "message": "The following specifications were found to be incompatible with each other:\n\nOutput in format: Requested package -> Available versions\n\nPackage cudatoolkit conflicts for:\ncudatoolkit==11.1.1\npytorch==1.8.0=py3.6_cuda11.1_cudnn8.0.5_0 -> cudatoolkit[version='>=11.1,<11.2']The following specifications were found to be incompatible with your system:\n\n  - cudatoolkit==11.1.1 -> __glibc[version='>=2.17,<3.0.a0']\n\nYour installed version is: not available\n"
}

I suppose something osx-specific is causing an incompatibility?

Performance relative to conda update yaml

We'd like to take advantage of fully reproducible lockfiles for our conda environments, but are experiencing 2-4 minute performance regressions depending on our machine. Is this expected behavior / are other users experiencing this issue with conda update via lockfile versus environment yaml file?

Discrepancy between conda-lock and conda env create

Hi !

I have been hitting a wall for the last two days, and cannot explain the following behaviour. Any help to understand what is going on would be much appreciated.

Here below is a .yml file with my environment requirements. Using conda-lock on this file resolves (among other packages) to:

  • python=3.9
  • pdal=2.2.0
  • python-pdal=2.4.2
    the last two of which are incompatible.

Using conda env create -n geo-env -f geo-env.yml installs pdal=2.3.0, which works.

Finally, adding pdal=2.3.0 as a requirement in the .yml file and using conda-lock on it leads to a working solution, but it is stuck at python=3.7.

Using mamba in my base environment vastly reduces the time it takes to resolve the environment, without changing the behaviour above.

For information, I am using conda 4.10.3 and mamba 0.15.3.

Here is the content of my geo-env.yml file:

name: geo-env
channels:
 - conda-forge
dependencies:
 - python
 - python-dotenv
 - geoalchemy2
 - opencv
 - Pyro5
 - descartes
 - beautifulsoup4
 - black 
 - boto3
 - celery
 - conda-lock
 - coverage
 - dask
 - python-dotenv
 - fasteners
 - flake8
 - flask
 - flask-bcrypt
 - flask-cors
 - flask-mail
 - flask-oauthlib
# - flask-security
 - flask-sqlalchemy
 - flower
 - folium
 - fuzzywuzzy
 - geopandas
 - geopy
 - gspread-pandas
 - gunicorn
 - hdbscan
 - ipyleaflet
 - ipyvolume
 - ipympl
 - jupyter
 - jupyterlab
 - keras
 - lxml
 - mysql-connector-python
 - nbdime
 - nbstripout
 - nodejs
 - numpy
 - openapi-spec-validator
 - openpyxl
 - pandas
 - paramiko
 - patsy
 - passlib
 - pyarrow
 - pylint
 - python-levenshtein
 - python-pdal
 - python-json-logger
 - plotly
 - psycopg2
 - pylint
 - pytest
 - pythreejs
 - py-xgboost
 - rasterio
 - redis-py
 - scikit-learn
 - scikit-image
 - seaborn
 - sentry-sdk
 - tqdm
 - ua-parser
 - unidecode
 - xlrd
 - xlsxwriter
 - pip

Add datetime filter?

Is it at all feasible to add a "publish_date ≤" filter so that conda-lock would effectively invoke the solver as if it were running on a date in the past?

It's a common problem that beginners forget to conda-lock or pip freeze their requirements, and their code no longer runs with up-to-date versions. In such situations, such a filter would be extremely useful.

`<TOKEN>` in private repo package urls

Hi, first of all many thanks for this great utility!

I'm trying to use it to lock an environment that contains a couple of package published on my private conda repository (quetz);
in my machine I can install them my first adding the channel with the /t/my-token/ before the channel endpoint;

conda config --add channels https://my-repo,com/t/my-token/channels/stable

I also have an environment.yaml with the channel and the token specified, until conda#10018 is solved, and i can create the environment with it.

creating a lock file from this environment.yml, the urls for the packages in my repo are like https://my-repo.com/t/<TOKEN>/channels/stable/noarch/my-package, and if I try to create an environment from it I obviously get a 401 unauthorized error.

Is this somewhat intended? should I use some env var to set the token?
Or is it that the case of private repos is not handled?

Issue with 'encoding' argument

Hi, I'm hitting an error with running this script. I'm on macOS Mojave 64 bit and have created the environment.yml.

I've chmod 755 the conda-lock.py file and added the interpreter location at the top of the script via #! /Users/.../bin/python (using which python)

However, I'm running into an issue I can't solve with error message:

216, in check_output
    process = Popen(stdout=PIPE, *popenargs, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'encoding'

Is there any advice you can provide? Thank you so much for your time.

Using requirements.txt rather than environment.yml as input?

Would it make sense to support plain text requirements.txt files as used with conda install --file requirements.txt as an input to conda-lock?

It currently does not work, e.g.:

$ pip list | grep conda-lock
conda-lock                    0.11.1
$ conda-lock lock -f requirements.txt -f requirements-ext.txt 
...
TypeError: string indices must be integers

Cross reference: https://github.com/conda-incubator/conda-lock/blob/v0.11.1/conda_lock/src_parser/pyproject_toml.py#L136 which has some relevant code.

micromamba produces alphabetical output

I think this is a micromamba issue (cc @wolfv), but I think it's worth knowing here that using conda-lock lock --micromamba produces different results. Specifically, instead of topographical ordering, packages are alphabetical:

environment.yml:

channels:
  - conda-forge
dependencies:
  - python=3.8
conda-lock -f environment.yml -p osx-64 --filename-template=conda.{platform}.lock
# platform: osx-64
# env_hash: bde40cd20f11db3eb54d7185ef738d2fbab6a8f5b689622fc7a8800c80f090a2
@EXPLICIT
https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2020.12.5-h033912b_0.tar.bz2#4483d8ea13bd57b52e3539e741501a7d
https://conda.anaconda.org/conda-forge/osx-64/libcxx-11.0.1-habf9029_0.tar.bz2#51c221f12b7975d60dae27cd8280efac
https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.2-h2e338ed_4.tar.bz2#9cef1910395d1543527583e73dba30f1
https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.5-haf1e3a3_1.tar.bz2#41116deb499e9bc58048c297d6403ce6
https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.11-h7795811_1010.tar.bz2#7d39e47e16ed0107f37c7224d5b5be8b
https://conda.anaconda.org/conda-forge/osx-64/libffi-3.3-h046ec9c_2.tar.bz2#c7a196accaf92d40985d5c9b4d14f9cb
https://conda.anaconda.org/conda-forge/osx-64/openssl-1.1.1j-hbcf498f_0.tar.bz2#09a02162d159d2f7ebe8749ae6960667
https://conda.anaconda.org/conda-forge/osx-64/readline-8.0-h0678c8f_2.tar.bz2#8f69d684fce8e73328995d7efb77816a
https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.10-h0419947_1.tar.bz2#9a79a432473acddd936ff8bab8b86145
https://conda.anaconda.org/conda-forge/osx-64/sqlite-3.34.0-h17101e1_0.tar.bz2#9e9694f119bb1a2362a0cc0249651835
https://conda.anaconda.org/conda-forge/osx-64/python-3.8.8-h4e93d89_0_cpython.tar.bz2#fd8260be7af83c005bbf0767361da91d
conda-lock --mamba -f environment.yml -p osx-64 --filename-template=mamba.{platform}.lock
# platform: osx-64
# env_hash: bde40cd20f11db3eb54d7185ef738d2fbab6a8f5b689622fc7a8800c80f090a2
@EXPLICIT
https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2020.12.5-h033912b_0.tar.bz2#4483d8ea13bd57b52e3539e741501a7d
https://conda.anaconda.org/conda-forge/osx-64/libcxx-11.0.1-habf9029_0.tar.bz2#51c221f12b7975d60dae27cd8280efac
https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.2-h2e338ed_4.tar.bz2#9cef1910395d1543527583e73dba30f1
https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.5-haf1e3a3_1.tar.bz2#41116deb499e9bc58048c297d6403ce6
https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.11-h7795811_1010.tar.bz2#7d39e47e16ed0107f37c7224d5b5be8b
https://conda.anaconda.org/conda-forge/osx-64/libffi-3.3-h046ec9c_2.tar.bz2#c7a196accaf92d40985d5c9b4d14f9cb
https://conda.anaconda.org/conda-forge/osx-64/openssl-1.1.1j-hbcf498f_0.tar.bz2#09a02162d159d2f7ebe8749ae6960667
https://conda.anaconda.org/conda-forge/osx-64/readline-8.0-h0678c8f_2.tar.bz2#8f69d684fce8e73328995d7efb77816a
https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.10-hb0a8c7a_1.tar.bz2#f7477bf81dcfc7b4dddc7b3790a99a0c
https://conda.anaconda.org/conda-forge/osx-64/sqlite-3.34.0-h17101e1_0.tar.bz2#9e9694f119bb1a2362a0cc0249651835
https://conda.anaconda.org/conda-forge/osx-64/python-3.8.8-h4e93d89_0_cpython.tar.bz2#fd8260be7af83c005bbf0767361da91d
conda-lock --micromamba -f environment.yml -p osx-64 --filename-template=micromamba.{platform}.lock
# platform: osx-64
# env_hash: bde40cd20f11db3eb54d7185ef738d2fbab6a8f5b689622fc7a8800c80f090a2
@EXPLICIT
https://conda.anaconda.org/conda-forge/osx-64/ca-certificates-2020.12.5-h033912b_0.tar.bz2#4483d8ea13bd57b52e3539e741501a7d
https://conda.anaconda.org/conda-forge/osx-64/certifi-2020.12.5-py38h50d1736_1.tar.bz2#fe528d606027dc2848f5a3577ab9b4eb
https://conda.anaconda.org/conda-forge/osx-64/libcxx-11.0.1-habf9029_0.tar.bz2#51c221f12b7975d60dae27cd8280efac
https://conda.anaconda.org/conda-forge/osx-64/libffi-3.3-h046ec9c_2.tar.bz2#c7a196accaf92d40985d5c9b4d14f9cb
https://conda.anaconda.org/conda-forge/osx-64/ncurses-6.2-h2e338ed_4.tar.bz2#9cef1910395d1543527583e73dba30f1
https://conda.anaconda.org/conda-forge/osx-64/openssl-1.1.1j-hbcf498f_0.tar.bz2#09a02162d159d2f7ebe8749ae6960667
https://conda.anaconda.org/conda-forge/noarch/pip-21.0.1-pyhd8ed1ab_0.tar.bz2#849477e10d78cbc283c78fd53bfbb567
https://conda.anaconda.org/conda-forge/osx-64/python-3.8.8-h4e93d89_0_cpython.tar.bz2#fd8260be7af83c005bbf0767361da91d
https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.8-1_cp38.tar.bz2#5fe7757fd743e1c2d14d6170d4f53365
https://conda.anaconda.org/conda-forge/osx-64/readline-8.0-h0678c8f_2.tar.bz2#8f69d684fce8e73328995d7efb77816a
https://conda.anaconda.org/conda-forge/osx-64/setuptools-49.6.0-py38h50d1736_3.tar.bz2#af8a81ee7c2c09fc2884c800a044b616
https://conda.anaconda.org/conda-forge/osx-64/sqlite-3.34.0-h17101e1_0.tar.bz2#9e9694f119bb1a2362a0cc0249651835
https://conda.anaconda.org/conda-forge/osx-64/tk-8.6.10-hb0a8c7a_1.tar.bz2#f7477bf81dcfc7b4dddc7b3790a99a0c
https://conda.anaconda.org/conda-forge/noarch/wheel-0.36.2-pyhd3deb0d_0.tar.bz2#768bfbe026426d0e76b377997d1f2b98
https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.5-haf1e3a3_1.tar.bz2#41116deb499e9bc58048c297d6403ce6
https://conda.anaconda.org/conda-forge/osx-64/zlib-1.2.11-h7795811_1010.tar.bz2#7d39e47e16ed0107f37c7224d5b5be8b

Conda and mamba produce identical results.

Fail early when platform is incompatible

I encountered a strange problem today when trying to install a lockfile. After a while I realised I tried to install a linux-64 lockfile on an osx-64 system.

Considering that we have the platform information in the lockfile itself, we could test at the very beginning whether they are compatible and, if not, fail with a more meaningful error. What do you think?


For completeness, here's the error I got:

ERROR:root:# >>>>>>>>>>>>>>>>>>>>>> ERROR REPORT <<<<<<<<<<<<<<<<<<<<<<
ERROR:root:
ERROR:root:    Traceback (most recent call last):
ERROR:root:      File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/conda/exceptions.py", line 1079, in __call__
ERROR:root:        return func(*args, **kwargs)
ERROR:root:      File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/conda/cli/main.py", line 84, in _main
ERROR:root:        exit_code = do_call(args, p)
ERROR:root:      File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/conda/cli/conda_argparse.py", line 83, in do_call
ERROR:root:        return getattr(module, func_name)(args, parser)
ERROR:root:      File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/conda/cli/main_create.py", line 41, in execute
ERROR:root:        install(args, parser, 'create')
ERROR:root:      File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/conda/cli/install.py", line 195, in install
ERROR:root:        explicit(specs, prefix, verbose=not context.quiet, index_args=index_args)
ERROR:root:      File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/conda/misc.py", line 110, in explicit
ERROR:root:        txn.execute()
ERROR:root:      File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/conda/core/link.py", line 244, in execute
ERROR:root:        self.verify()
ERROR:root:      File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/conda/common/io.py", line 88, in decorated
ERROR:root:        return f(*args, **kwds)
ERROR:root:      File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/conda/core/link.py", line 231, in verify
ERROR:root:        exceptions = self._verify(self.prefix_setups, self.prefix_action_groups)
ERROR:root:      File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/conda/core/link.py", line 590, in _verify
ERROR:root:        for exc in self.verify_executor.map(UnlinkLinkTransaction._verify_individual_level,
ERROR:root:      File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/conda/common/io.py", line 525, in map
ERROR:root:        yield func(thing)
ERROR:root:      File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/conda/core/link.py", line 411, in _verify_individual_level
ERROR:root:        error_result = axn.verify()
ERROR:root:      File "/usr/local/Caskroom/miniforge/base/lib/python3.8/site-packages/conda/core/path_actions.py", line 323, in verify
ERROR:root:        source_size_in_bytes = getsize(self.source_full_path)
ERROR:root:      File "/usr/local/Caskroom/miniforge/base/lib/python3.8/genericpath.py", line 50, in getsize
ERROR:root:        return os.stat(filename).st_size
ERROR:root:    OSError: [Errno 62] Too many levels of symbolic links: '/usr/local/Caskroom/miniforge/base/pkgs/ncurses-6.2-h58526e2_4/share/terminfo/N/NCR260VT300WPP'

How does this relate to conda export --explicit?

Hi Marius,
This seems pretty interesting as we are also trying to explicitly specify a reproducible environment. One of the key aims is to ensure that the environment deployed to prod is exactly the same as was used when running the tests.

Is the lock file generated by conda-lock the same as created by conda list --explicit?

environment.yaml not detected due to "yaml" extension instead of "yml"

I just encountered this error FileNotFoundError: environment.yml not found which I was able to fix by renaming my environment.yaml file to environment.yml. Alternatively using the -f environment.yaml option also works.

The internet seems to be split on which version is the correct extension, but ignoring this discussion it would be really nice to just support both yaml and yml out of the box.

Random oscillation between two solutions

When using conda-lock --mamba with libsolv=0.7.19=h780b84a_2, I find that my package versions, and especially my Python version, keeps oscillating at random between two solutions, each of which appears with a probability of about 50%.

I can reproduce it in Docker as follows.

Setup:

docker run --rm -it condaforge/mambaforge:4.10.2-0

mamba install -y conda-lock=0.10.0=pyhd8ed1ab_0 libsolv=0.7.19=h780b84a_2

cat > environment.yml <<EOF
name: base
channels:
    - conda-forge
dependencies:
    - psycopg2
    - black
    - pre-commit
EOF

Test commands:

conda-lock --mamba -p linux-64 -f environment.yml
grep python-3 conda-linux-64.lock
cat conda-linux-64.lock

The above test commands result in one of two solutions, either with Python 3.9.5 or Python 3.7.2:

With Python 3.9.5
# platform: linux-64
# env_hash: 341b64e935b64805bab2db78155807eb7149017880c4e897c9592f2b28c536b5
@EXPLICIT
https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2#d7c89558ba9fa0495403155b64376d81
https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2021.5.30-ha878542_0.tar.bz2#6a777890e94194dc94a29a76d2a7e721
https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.36.1-hea4e1c9_0.tar.bz2#7bdb75ebbbebe76d76cc6b04b05b3d7a
https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-9.3.0-h6de172a_19.tar.bz2#cd9a24a8dde03ec0cf0e603b0bea85a1
https://conda.anaconda.org/conda-forge/noarch/tzdata-2021a-he74cb21_0.tar.bz2#6f36861f102249fc54861ff9343c3fdd
https://conda.anaconda.org/conda-forge/linux-64/libgomp-9.3.0-h2828fa1_19.tar.bz2#ab0a307912033126da02507b59e79ec9
https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-1_gnu.tar.bz2#561e277319a41d4f24f5c05a9ef63c04
https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-9.3.0-h2828fa1_19.tar.bz2#9d5cdfc51476ee4dcdd96ed2dca3f943
https://conda.anaconda.org/conda-forge/linux-64/libffi-3.3-h58526e2_2.tar.bz2#665369991d8dd290ac5ee92fce3e6bf5
https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.2-h58526e2_4.tar.bz2#509f2a21c4a09214cd737a480dfd80c9
https://conda.anaconda.org/conda-forge/linux-64/openssl-1.1.1k-h7f98852_0.tar.bz2#07fae2cb088379c8441e0f3ffa1f4025
https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.5-h516909a_1.tar.bz2#33f601066901f3e1a85af3522a8113f9
https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h516909a_0.tar.bz2#03a530e925414902547cf48da7756db8
https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.11-h516909a_1010.tar.bz2#339cc5584e6d26bc73a875ba900028c3
https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20191231-he28a2e2_2.tar.bz2#4d331e44109e3f0e19b4cb8f9b82f3e1
https://conda.anaconda.org/conda-forge/linux-64/readline-8.1-h46c0cb4_0.tar.bz2#5788de3c8d7a7d64ac56c784c4ef48e6
https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.10-h21135ba_1.tar.bz2#c647f70aa7e3d4cc4e029cc1c9a99953
https://conda.anaconda.org/conda-forge/linux-64/krb5-1.19.1-hcc1bbae_0.tar.bz2#59b0695a515a6c54d45463dbf208ae38
https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.36.0-h9cd32fc_0.tar.bz2#d5bbac924cbda57469f43448d5236a50
https://conda.anaconda.org/conda-forge/linux-64/libpq-13.3-hd57d9b9_0.tar.bz2#66ef2cacc483205b7d303f7b02601c3b
https://conda.anaconda.org/conda-forge/linux-64/python-3.9.5-h49503c6_0_cpython.tar.bz2#2139a8f9a7f5d1cbec3dc657be58a2ad
https://conda.anaconda.org/conda-forge/noarch/appdirs-1.4.4-pyh9f0ad1d_0.tar.bz2#5f095bc6454094e96f146491fd03633b
https://conda.anaconda.org/conda-forge/noarch/dataclasses-0.8-pyhc8e2a94_1.tar.bz2#28e0de0ecba81334619a777fdc00febc
https://conda.anaconda.org/conda-forge/noarch/distlib-0.3.2-pyhd8ed1ab_0.tar.bz2#ae8b866c376568b0342ae2c9b68f1e65
https://conda.anaconda.org/conda-forge/noarch/filelock-3.0.12-pyh9f0ad1d_0.tar.bz2#7544ed05bbbe9bb687bc9bcbe4d6cb46
https://conda.anaconda.org/conda-forge/noarch/pathspec-0.8.1-pyhd3deb0d_0.tar.bz2#fcd2fbb062b55d14a77e664c89ee17a6
https://conda.anaconda.org/conda-forge/noarch/pycparser-2.20-pyh9f0ad1d_2.tar.bz2#aa798d50ffd182a0f6f31478c7f434f6
https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.9-2_cp39.tar.bz2#39adde4247484de2bb4000122fdcf665
https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2#e5f25f8dbc060e9a8d912e432202afc2
https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhd8ed1ab_0.tar.bz2#f832c45a477c78bebd107098db465095
https://conda.anaconda.org/conda-forge/noarch/typing_extensions-3.10.0.0-pyha770c72_0.tar.bz2#67c0cba6533b641f28946d7c16f361c8
https://conda.anaconda.org/conda-forge/linux-64/certifi-2021.5.30-py39hf3d152e_0.tar.bz2#7bbfaa3b8363bf8505d7f65e4e2e8a90
https://conda.anaconda.org/conda-forge/linux-64/cffi-1.14.5-py39he32792d_0.tar.bz2#b561e1fad1fc8bb343064bd5497444bb
https://conda.anaconda.org/conda-forge/noarch/cfgv-3.3.0-pyhd8ed1ab_0.tar.bz2#a739adbf102868f675bf70601e0af7ea
https://conda.anaconda.org/conda-forge/linux-64/click-8.0.1-py39hf3d152e_0.tar.bz2#ab32c487b1b91d783fb68388c49bb254
https://conda.anaconda.org/conda-forge/linux-64/mypy_extensions-0.4.3-py39hf3d152e_3.tar.bz2#fcab473c122479c0a4b1a14f716b7f1d
https://conda.anaconda.org/conda-forge/linux-64/psycopg2-2.9.1-py39h3811e60_0.tar.bz2#4f9d0dad6fc928389980dd5f28be7e29
https://conda.anaconda.org/conda-forge/linux-64/pyyaml-5.4.1-py39h3811e60_0.tar.bz2#6451ed66b3b438134626894c821dc5fa
https://conda.anaconda.org/conda-forge/linux-64/regex-2021.7.1-py39h3811e60_0.tar.bz2#a0334332fb720588186b8fd7a3e85ea6
https://conda.anaconda.org/conda-forge/linux-64/typed-ast-1.4.3-py39h3811e60_0.tar.bz2#a25ce1f6fa278ccfaffb6dd35720b8be
https://conda.anaconda.org/conda-forge/linux-64/virtualenv-20.4.7-py39hf3d152e_0.tar.bz2#4d71a79ffa38875eabf760f15c9454a8
https://conda.anaconda.org/conda-forge/noarch/black-21.5b2-pyhd8ed1ab_0.tar.bz2#919be0b3435cbe8e803c6bd738231f69
https://conda.anaconda.org/conda-forge/linux-64/editdistance-s-1.0.0-py39h1a9c180_1.tar.bz2#d9c1794506d677cf3e8f981f1c5a25d1
https://conda.anaconda.org/conda-forge/linux-64/setuptools-49.6.0-py39hf3d152e_3.tar.bz2#4397280abb201d7adff59099e12e7ddd
https://conda.anaconda.org/conda-forge/noarch/identify-2.2.10-pyhd8ed1ab_0.tar.bz2#1f9cd027f471e98e21d9740472b18096
https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.6.0-pyhd8ed1ab_0.tar.bz2#0941325bf48969e2b3b19d0951740950
https://conda.anaconda.org/conda-forge/linux-64/pre-commit-2.13.0-py39hf3d152e_0.tar.bz2#8cd635f3b86932c913b9350d5f53e080
With Python 3.7.2
# platform: linux-64
# env_hash: 341b64e935b64805bab2db78155807eb7149017880c4e897c9592f2b28c536b5
@EXPLICIT
https://conda.anaconda.org/conda-forge/linux-64/_libgcc_mutex-0.1-conda_forge.tar.bz2#d7c89558ba9fa0495403155b64376d81
https://conda.anaconda.org/conda-forge/linux-64/ca-certificates-2021.5.30-ha878542_0.tar.bz2#6a777890e94194dc94a29a76d2a7e721
https://conda.anaconda.org/conda-forge/linux-64/ld_impl_linux-64-2.36.1-hea4e1c9_0.tar.bz2#7bdb75ebbbebe76d76cc6b04b05b3d7a
https://conda.anaconda.org/conda-forge/linux-64/libstdcxx-ng-9.3.0-h6de172a_19.tar.bz2#cd9a24a8dde03ec0cf0e603b0bea85a1
https://conda.anaconda.org/conda-forge/linux-64/libgomp-9.3.0-h2828fa1_19.tar.bz2#ab0a307912033126da02507b59e79ec9
https://conda.anaconda.org/conda-forge/linux-64/_openmp_mutex-4.5-1_gnu.tar.bz2#561e277319a41d4f24f5c05a9ef63c04
https://conda.anaconda.org/conda-forge/linux-64/libgcc-ng-9.3.0-h2828fa1_19.tar.bz2#9d5cdfc51476ee4dcdd96ed2dca3f943
https://conda.anaconda.org/conda-forge/linux-64/libffi-3.3-h58526e2_2.tar.bz2#665369991d8dd290ac5ee92fce3e6bf5
https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.2-h58526e2_4.tar.bz2#509f2a21c4a09214cd737a480dfd80c9
https://conda.anaconda.org/conda-forge/linux-64/openssl-1.1.1k-h7f98852_0.tar.bz2#07fae2cb088379c8441e0f3ffa1f4025
https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.5-h516909a_1.tar.bz2#33f601066901f3e1a85af3522a8113f9
https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h516909a_0.tar.bz2#03a530e925414902547cf48da7756db8
https://conda.anaconda.org/conda-forge/linux-64/zlib-1.2.11-h516909a_1010.tar.bz2#339cc5584e6d26bc73a875ba900028c3
https://conda.anaconda.org/conda-forge/linux-64/libedit-3.1.20191231-he28a2e2_2.tar.bz2#4d331e44109e3f0e19b4cb8f9b82f3e1
https://conda.anaconda.org/conda-forge/linux-64/readline-8.1-h46c0cb4_0.tar.bz2#5788de3c8d7a7d64ac56c784c4ef48e6
https://conda.anaconda.org/conda-forge/linux-64/tk-8.6.10-h21135ba_1.tar.bz2#c647f70aa7e3d4cc4e029cc1c9a99953
https://conda.anaconda.org/conda-forge/linux-64/krb5-1.19.1-hcc1bbae_0.tar.bz2#59b0695a515a6c54d45463dbf208ae38
https://conda.anaconda.org/conda-forge/linux-64/sqlite-3.36.0-h9cd32fc_0.tar.bz2#d5bbac924cbda57469f43448d5236a50
https://conda.anaconda.org/conda-forge/linux-64/libpq-13.3-hd57d9b9_0.tar.bz2#66ef2cacc483205b7d303f7b02601c3b
https://conda.anaconda.org/conda-forge/linux-64/python-3.7.10-hffdb5ce_100_cpython.tar.bz2#7425fffa658971915f595e9110163c3c
https://conda.anaconda.org/conda-forge/noarch/appdirs-1.4.4-pyh9f0ad1d_0.tar.bz2#5f095bc6454094e96f146491fd03633b
https://conda.anaconda.org/conda-forge/noarch/dataclasses-0.8-pyhc8e2a94_1.tar.bz2#28e0de0ecba81334619a777fdc00febc
https://conda.anaconda.org/conda-forge/noarch/distlib-0.3.2-pyhd8ed1ab_0.tar.bz2#ae8b866c376568b0342ae2c9b68f1e65
https://conda.anaconda.org/conda-forge/noarch/filelock-3.0.12-pyh9f0ad1d_0.tar.bz2#7544ed05bbbe9bb687bc9bcbe4d6cb46
https://conda.anaconda.org/conda-forge/noarch/pathspec-0.8.1-pyhd3deb0d_0.tar.bz2#fcd2fbb062b55d14a77e664c89ee17a6
https://conda.anaconda.org/conda-forge/noarch/pycparser-2.20-pyh9f0ad1d_2.tar.bz2#aa798d50ffd182a0f6f31478c7f434f6
https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.7-2_cp37m.tar.bz2#afff88bf9a7048da740c70aeb8cdbb82
https://conda.anaconda.org/conda-forge/noarch/six-1.16.0-pyh6c4a22f_0.tar.bz2#e5f25f8dbc060e9a8d912e432202afc2
https://conda.anaconda.org/conda-forge/noarch/toml-0.10.2-pyhd8ed1ab_0.tar.bz2#f832c45a477c78bebd107098db465095
https://conda.anaconda.org/conda-forge/noarch/typing_extensions-3.10.0.0-pyha770c72_0.tar.bz2#67c0cba6533b641f28946d7c16f361c8
https://conda.anaconda.org/conda-forge/noarch/zipp-3.5.0-pyhd8ed1ab_0.tar.bz2#f9dd05a5ed6b81c91f097e3739107a74
https://conda.anaconda.org/conda-forge/linux-64/certifi-2021.5.30-py37h89c1867_0.tar.bz2#105f18ae8597a5f4d4e3188bcb06c796
https://conda.anaconda.org/conda-forge/linux-64/cffi-1.14.5-py37hc58025e_0.tar.bz2#e05f1fad0c52c21b6b92778d31f89cd0
https://conda.anaconda.org/conda-forge/noarch/cfgv-3.3.0-pyhd8ed1ab_0.tar.bz2#a739adbf102868f675bf70601e0af7ea
https://conda.anaconda.org/conda-forge/linux-64/importlib-metadata-4.6.1-py37h89c1867_0.tar.bz2#30ed682e2aa91a4a491ec805b501321e
https://conda.anaconda.org/conda-forge/linux-64/mypy_extensions-0.4.3-py37h89c1867_3.tar.bz2#b604f0897a7a207bddd7d05bf3284752
https://conda.anaconda.org/conda-forge/linux-64/psycopg2-2.9.1-py37h5e8e339_0.tar.bz2#8ffbd8675bb44c947b26138f2d44dc62
https://conda.anaconda.org/conda-forge/linux-64/pyyaml-5.4.1-py37h5e8e339_0.tar.bz2#090550b9425fe9a87dc1ec7fde201633
https://conda.anaconda.org/conda-forge/linux-64/regex-2021.7.1-py37h5e8e339_0.tar.bz2#16ff1fd8e4d4c60f85e47423f0d7a4f4
https://conda.anaconda.org/conda-forge/linux-64/typed-ast-1.4.3-py37h5e8e339_0.tar.bz2#0e8dc105f8cf0a2a6456f7a18f34a712
https://conda.anaconda.org/conda-forge/linux-64/click-8.0.1-py37h89c1867_0.tar.bz2#bb1ad97b5d8626f662b753f620c3c913
https://conda.anaconda.org/conda-forge/linux-64/editdistance-s-1.0.0-py37h2527ec5_1.tar.bz2#100918f43247cedad74f2cf8dcbda5bc
https://conda.anaconda.org/conda-forge/noarch/importlib_metadata-4.6.1-hd8ed1ab_0.tar.bz2#d5ff9abb27ab799d4a730e86aa0c5aeb
https://conda.anaconda.org/conda-forge/linux-64/setuptools-49.6.0-py37h89c1867_3.tar.bz2#928c178bf6805b8ab71fabaa620e0234
https://conda.anaconda.org/conda-forge/linux-64/virtualenv-20.4.7-py37h89c1867_0.tar.bz2#50087f16f1a71581a0327956c80debc2
https://conda.anaconda.org/conda-forge/noarch/black-21.5b2-pyhd8ed1ab_0.tar.bz2#919be0b3435cbe8e803c6bd738231f69
https://conda.anaconda.org/conda-forge/noarch/identify-2.2.10-pyhd8ed1ab_0.tar.bz2#1f9cd027f471e98e21d9740472b18096
https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.6.0-pyhd8ed1ab_0.tar.bz2#0941325bf48969e2b3b19d0951740950
https://conda.anaconda.org/conda-forge/linux-64/pre-commit-2.13.0-py37h89c1867_0.tar.bz2#a2ddf76626c4e7481f106fa08d5d77c5

I can't seem to reproduce the issue with mamba itself. I consistently get:

mamba env create --dry-run --name=x -f environment.yml
Collecting package metadata (repodata.json): done
Solving environment: done
name: base
channels:
  - conda-forge
dependencies:
  - conda-forge/linux-64::_libgcc_mutex==0.1=conda_forge
  - conda-forge/linux-64::ca-certificates==2021.5.30=ha878542_0
  - conda-forge/linux-64::ld_impl_linux-64==2.36.1=hea4e1c9_0
  - conda-forge/linux-64::libstdcxx-ng==9.3.0=h6de172a_19
  - conda-forge/noarch::tzdata==2021a=he74cb21_0
  - conda-forge/linux-64::libgomp==9.3.0=h2828fa1_19
  - conda-forge/linux-64::_openmp_mutex==4.5=1_gnu
  - conda-forge/linux-64::libgcc-ng==9.3.0=h2828fa1_19
  - conda-forge/linux-64::libffi==3.3=h58526e2_2
  - conda-forge/linux-64::ncurses==6.2=h58526e2_4
  - conda-forge/linux-64::openssl==1.1.1k=h7f98852_0
  - conda-forge/linux-64::xz==5.2.5=h516909a_1
  - conda-forge/linux-64::yaml==0.2.5=h516909a_0
  - conda-forge/linux-64::zlib==1.2.11=h516909a_1010
  - conda-forge/linux-64::libedit==3.1.20191231=he28a2e2_2
  - conda-forge/linux-64::readline==8.1=h46c0cb4_0
  - conda-forge/linux-64::tk==8.6.10=h21135ba_1
  - conda-forge/linux-64::krb5==1.19.1=hcc1bbae_0
  - conda-forge/linux-64::sqlite==3.36.0=h9cd32fc_0
  - conda-forge/linux-64::libpq==13.3=hd57d9b9_0
  - conda-forge/linux-64::python==3.9.5=h49503c6_0_cpython
  - conda-forge/noarch::appdirs==1.4.4=pyh9f0ad1d_0
  - conda-forge/noarch::dataclasses==0.8=pyhc8e2a94_1
  - conda-forge/noarch::distlib==0.3.2=pyhd8ed1ab_0
  - conda-forge/noarch::filelock==3.0.12=pyh9f0ad1d_0
  - conda-forge/noarch::pathspec==0.8.1=pyhd3deb0d_0
  - conda-forge/noarch::pycparser==2.20=pyh9f0ad1d_2
  - conda-forge/linux-64::python_abi==3.9=2_cp39
  - conda-forge/noarch::six==1.16.0=pyh6c4a22f_0
  - conda-forge/noarch::toml==0.10.2=pyhd8ed1ab_0
  - conda-forge/noarch::typing_extensions==3.10.0.0=pyha770c72_0
  - conda-forge/noarch::wheel==0.36.2=pyhd3deb0d_0
  - conda-forge/linux-64::certifi==2021.5.30=py39hf3d152e_0
  - conda-forge/linux-64::cffi==1.14.5=py39he32792d_0
  - conda-forge/noarch::cfgv==3.3.0=pyhd8ed1ab_0
  - conda-forge/linux-64::click==8.0.1=py39hf3d152e_0
  - conda-forge/linux-64::mypy_extensions==0.4.3=py39hf3d152e_3
  - conda-forge/linux-64::psycopg2==2.9.1=py39h3811e60_0
  - conda-forge/linux-64::pyyaml==5.4.1=py39h3811e60_0
  - conda-forge/linux-64::regex==2021.7.1=py39h3811e60_0
  - conda-forge/linux-64::typed-ast==1.4.3=py39h3811e60_0
  - conda-forge/linux-64::virtualenv==20.4.7=py39hf3d152e_0
  - conda-forge/noarch::black==21.5b2=pyhd8ed1ab_0
  - conda-forge/linux-64::editdistance-s==1.0.0=py39h1a9c180_1
  - conda-forge/linux-64::setuptools==49.6.0=py39hf3d152e_3
  - conda-forge/noarch::identify==2.2.10=pyhd8ed1ab_0
  - conda-forge/noarch::nodeenv==1.6.0=pyhd8ed1ab_0
  - conda-forge/noarch::pip==21.1.3=pyhd8ed1ab_0
  - conda-forge/linux-64::pre-commit==2.13.0=py39hf3d152e_0

Downgrading to libsolv=0.7.18=h780b84a_0 seems to yield deterministic results.

Error with -p argument?

I've made several attempts to create the lock methods using the repository you've so kindly recommended. However, I must be making a mistake somewhere in my logic; I'm doing the following on Linux:

  1. placing the conda_lock.py file on my local system
  2. adding the path to my python interpreter at the top of this script via #! /Users/.../bin/python (taken from which python)
  3. making the script executable via chmod 755 conda_lock.py
  4. activating the environment that I'm interested in locking via conda activate FOO and creating a .yml file for it via conda env export > environment.yml (which now resides in the same directory as conda_lock.py... then deactivating environment
  5. pip install pathlib on the conda base (the script will fuss if not)
  6. in this directory, using ./conda-lock.py -f environment.yml -p osx-64 -p linux-64 as directed in the readme

At this point, I'm getting the error:

TypeError: expected str, bytes or os.PathLike object, not dict
ees2192@midway:~/conda-lock-master> ./conda_lock.py -f environment.yml
generating lockfile for osx-64
Traceback (most recent call last):
  File "./conda_lock.py", line 107, in <module>
    platforms=args.platform or DEFAULT_PLATFORMS,
  File "./conda_lock.py", line 64, in make_lock_files
    platform=platform, channels=channels, specs=specs
  File "./conda_lock.py", line 37, in solve_specs_for_arch
    json_output = subprocess.check_output(args, encoding="utf-8", env=env)
  File "/home/ees2192/anaconda3/lib/python3.6/subprocess.py", line 336, in check_output
    **kwargs).stdout
  File "/home/ees2192/anaconda3/lib/python3.6/subprocess.py", line 403, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/home/ees2192/anaconda3/lib/python3.6/subprocess.py", line 709, in __init__
    restore_signals, start_new_session)
  File "/home/ees2192/anaconda3/lib/python3.6/subprocess.py", line 1275, in _execute_child
    restore_signals, start_new_session, preexec_fn)
TypeError: expected str, bytes or os.PathLike object, not dict

I should note that this happens in different flavors when I remove one of the -p arguments or all of them from ./conda-lock.py -f environment.yml -p osx-64 -p linux-64.

[Bug] `msys2` channel packages not included w/ `defaults` channel

Right now, if I use the following environment YAML:

channels:
  - conda-forge
  - defaults
dependencies:
  - make==4.3

Then calling conda-lock -p win-64 environment.yml on a Linux box fails with:

The following packages are not available from current channels:

  - m2w64-gcc-libs

Current channels:

  - https://conda.anaconda.org/conda-forge/win-64
  - https://conda.anaconda.org/conda-forge/noarch
  - https://repo.anaconda.com/pkgs/main/win-64
  - https://repo.anaconda.com/pkgs/main/noarch
  - https://repo.anaconda.com/pkgs/r/win-64
  - https://repo.anaconda.com/pkgs/r/noarch

To search for alternate channels that may provide the conda package you're
looking for, navigate to

    https://anaconda.org

and use the search bar at the top of the page.

I believe this is because defaults only includes the msys2 package on Windows, so running the solver on Linux removes this channel and causes this failure.

[Feature] Detect up-to-date vs stale lock files

One feature that it'd be great to supprt would be fore conda-lock to detect when the environment.yml has/hasn't changed compared to the generated .lockfiles. That way, for instance, we can cheaply check that the .lock file is up-to-date without having to invoke the conda SAT solver again.

One way to do this would be to embed the hash of environment.yml into the lock file (it looks like the lock file supports comments, so we could probably do something there) -- that way, either conda-lock (or an external program) could just check the environment.yml against the hash to see there's been a change.

If that sounds good, I'd be happy to implement adding the hash to the .lock files as a comment, although I'm not sure what the best UI for this feature would be.

Rename default branch do main

Hi folks,
Should we rename the default branch to be main instead of master?
It seems to be pretty easy now to change it on Github :)

[Bug] --strip-auth in environment without private channel produces empty line

If no channel in your environment file requires basic auth, --strip-auth will produce an empty line.

# The following domains require authentication:

# platform: linux-64

This then causes the installation to fail, when --auth-file is provided.

File "/opt/conda/lib/python3.8/site-packages/conda_lock/conda_lock.py", line 534, in <genexpr>
_add_auth_to_line(line, auth) if line[0] not in ("#", "@") else line
IndexError: string index out of range

I'll fix this tomorrow. 😅

Confusing error message when conda-lock fails to parse meta.yaml

I'm pretty sure my meta.yaml is too complex for conda-lock to process. I'm fine with this. However, the error message is very confusing because it comes from inside jinja2:

$ conda-lock lock -p linux-64  -f conda_recipe/meta.yaml 
[...]
TypeError: no loader for this environment specified
Full error message
$ conda-lock lock -p linux-64  -f conda_recipe/meta.yaml 
generating lockfile for linux-64
Traceback (most recent call last):
  File "/home/amp/LocalInstalls/conda/miniconda3/envs/katana-dev/bin/conda-lock", line 10, in <module>
    sys.exit(main())
  File "/home/amp/LocalInstalls/conda/miniconda3/envs/katana-dev/lib/python3.8/site-packages/click/core.py", line 829, in __call__
    return self.main(*args, **kwargs)
  File "/home/amp/LocalInstalls/conda/miniconda3/envs/katana-dev/lib/python3.8/site-packages/click/core.py", line 782, in main
    rv = self.invoke(ctx)
  File "/home/amp/LocalInstalls/conda/miniconda3/envs/katana-dev/lib/python3.8/site-packages/click/core.py", line 1259, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/amp/LocalInstalls/conda/miniconda3/envs/katana-dev/lib/python3.8/site-packages/click/core.py", line 1066, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/amp/LocalInstalls/conda/miniconda3/envs/katana-dev/lib/python3.8/site-packages/click/core.py", line 610, in invoke
    return callback(*args, **kwargs)
  File "/home/amp/LocalInstalls/conda/miniconda3/envs/katana-dev/lib/python3.8/site-packages/conda_lock/conda_lock.py", line 598, in lock
    run_lock(
  File "/home/amp/LocalInstalls/conda/miniconda3/envs/katana-dev/lib/python3.8/site-packages/conda_lock/conda_lock.py", line 504, in run_lock
    make_lock_files(
  File "/home/amp/LocalInstalls/conda/miniconda3/envs/katana-dev/lib/python3.8/site-packages/conda_lock/conda_lock.py", line 274, in make_lock_files
    lock_specs = parse_source_files(
  File "/home/amp/LocalInstalls/conda/miniconda3/envs/katana-dev/lib/python3.8/site-packages/conda_lock/conda_lock.py", line 420, in parse_source_files
    parse_meta_yaml_file(src_file, platform, include_dev_dependencies)
  File "/home/amp/LocalInstalls/conda/miniconda3/envs/katana-dev/lib/python3.8/site-packages/conda_lock/src_parser/meta_yaml.py", line 99, in parse_meta_yaml_file
    rendered = t.render()
  File "/home/amp/.local/lib/python3.8/site-packages/jinja2/environment.py", line 1090, in render
    self.environment.handle_exception()
  File "/home/amp/.local/lib/python3.8/site-packages/jinja2/environment.py", line 832, in handle_exception
    reraise(*rewrite_traceback_stack(source=source))
  File "/home/amp/.local/lib/python3.8/site-packages/jinja2/_compat.py", line 28, in reraise
    raise value.with_traceback(tb)
  File "<template>", line 1, in top-level template code
TypeError: no loader for this environment specified

The meta.yaml file involved is: https://github.com/KatanaGraph/katana/blob/9a63b012a09b5261ec5b12b06c51f3f576713df4/conda_recipe/meta.yaml

The error is the same with conda-lock versions (the message above is from 0.8.0):

  • conda-lock 0.8.0 pyhd8ed1ab_0 conda-forge
  • conda-lock 0.8.1.dev2+g2702768 pypi_0 pypi (installed with pip install .)

mamba support

Using mamba can be a huge time saver - it would be great if conda-lock could optionally use mamba for the solve

Support outputting enriched environment.yml locks

Greetings!

This is a really cool project... and it's almost exactly what I need. I was wondering if you would be open to patches that allow the output format to be an enriched environment.yml file (vs. a list of explicit package urls). There are two main reasons that this would be useful to me (and perhaps others):

  1. We want users to be able to "upgrade" existing environments to a fixed set of packages, but allow them to maintain local modifications that would be re-resolved by the package solver (something that is not crazy now that we have mamba). [We use this functionality quite a bit in our deployment].
  2. (and to a lesser extent) I've had some issues in the past with locked packages disappearing from the package archive and breaking my lock files.

If I were to submit a patch that adds a flag that allows users to output an enriched environment.yml file rather than a lock file, would that be something that you would consider merging?

For example, if your input environment.yml file was:

channels:
 - conda-forge
dependencies:
  - python=3.9
  - pandas

then the desired output (for linux-64 here) would be something like:

channels:
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=conda_forge
  - _openmp_mutex=4.5=1_gnu
  - ca-certificates=2021.7.5=h06a4308_1
  - certifi=2021.5.30=py39hf3d152e_0
  - ld_impl_linux-64=2.36.1=hea4e1c9_1
  - libblas=3.9.0=9_openblas
  - libcblas=3.9.0=9_openblas
  - libffi=3.3=h58526e2_2
  - libgcc-ng=9.3.0=h2828fa1_19
  - libgfortran-ng=9.3.0=hff62375_19
  - libgfortran5=9.3.0=hff62375_19
  - libgomp=9.3.0=h2828fa1_19
  - liblapack=3.9.0=9_openblas
  - libopenblas=0.3.15=pthreads_h8fe5266_1
  - libstdcxx-ng=9.3.0=h6de172a_19
  - ncurses=6.2=h58526e2_4
  - numpy=1.21.0=py39hdbf815f_0
  - openssl=1.1.1k=h7f98852_0
  - pandas=1.3.0=py39hde0f152_0
  - pip=21.1.3=pyhd8ed1ab_0
  - python=3.9.6=h49503c6_0_cpython
  - python-dateutil=2.8.1=py_0
  - python_abi=3.9=2_cp39
  - pytz=2021.1=pyhd8ed1ab_0
  - readline=8.1=h46c0cb4_0
  - setuptools=52.0.0=py39h06a4308_0
  - six=1.16.0=pyh6c4a22f_0
  - sqlite=3.36.0=h9cd32fc_0
  - tk=8.6.10=hed695b0_1
  - tzdata=2021a=he74cb21_1
  - wheel=0.36.2=pyhd3deb0d_0
  - xz=5.2.5=h516909a_1
  - zlib=1.2.11=h516909a_1010

Provide efficient installation rather than delegating to conda

Hi -- Thanks for conda-lock, it is great.

Currently conda-lock delegates installation to conda. However, conda does not do 'minimal work' when running e.g. conda create -n foo --file f.lock in an already existent environment foo. See this issue conda/conda#10384

This causes a large amount of re-indexing for IDE's such as pycharm each time the environment is updated.

While solving this upstream in conda is ideal, it is possible that this could be solved within conda-lock install. It could determine the minimal changelist and perform it directly.

Is there interest in pursuing this here rather than upstream?

cheers, nehal

`-m docker` doesn't seem to use Docker

Docker mode doesn't seem to work; this is Linux, Fedora 33, with conda-lock 0.7.2.

$ conda-lock -p linux-64 -m docker &
[1] 172664
$ generating lockfile for linux-64

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
$ docker ps -a
# ... a bunch of dead containers, but none from today ...

Add more diagnostic output

Conda-lock has a few phases. It would be helpful for users if at those various phases it could show some kind of progress

Support lock generation from 1..* files

Thanks for conda-lock! Starting to using it in anger!

A use case I'm currently working on solving with jinja, but would consider PRing (eventually, free time, yadda yadda): generating locks based on multiple "inherited" environment files. Consider:

# env-base.yml
channels:
  - conda-forge
dependencies:
  - python =3.7
  # a cast of thousands...
# env-cpu.yml
channels:
  - conda-forge
dependencies:
  - pytorch-cpu
# env-gpu.yml
channels:
  - pytorch
  - conda-forge
dependencies:
  - pytorch

then be able to:

conda-lock -f env-cpu.yml -f env-base.yml -p osx-64 -p linux-64 --prefix cpu-
conda-lock -f env-gpu.yml -f env-base.yml -p osx-64 -p linux-64 --prefix gpu-

... and get

cpu-conda-linux-64.lock
cpu-conda-osx-64.lock
gpu-conda-linux-64.lock
gpu-conda-osx-64.lock

of course, it gets freakier with env-specific yml, etc. as well as extending this to other environment sources, e.g. #39, #40, #41...

Output options: file name, standard out?

Thanks again for conda-lock!

Two use cases:

  • I keep finding myself generating a lock file in a temporary directory and then renaming it.
  • I also occasionally want a single lockfile, not even on disk e.g. verify that a particular channel is not used.

The potentially-multi-platform output of course complicates both of these use cases... practically, I just about always end up with extra windows packages/channels, so would be totally fine with --output or --stdout being mutually exclusive with multi-platform outputs.

Something that could work with multiple outputs would be a prefix: looking through the code, there's a spot where the filename is generated from f"conda-{platform}.lock"... and knowing the name of the platform is of course pretty important! But perhaps being able to specify a prefix, e.g. f"{output_prefix}conda-{platform}.lock" would keep things consistent. If anything, I'd almost prefer a composite extension, e.g. .conda.lock, but probably that ship has sailed.

Supporting e.g. --stdout, even for the single case, is a bit more challenging, as there is a fair amount of print stuff, but this could be overcome with click.echo(..., err=True), which does some nice stuff.

Anyhow, architecturally, this might mean reworking make_lock_files a bit.

Happy to work up a PR if this doesn't sound like crazy talk!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.