File: C:/Users/fred/anaconda3/Lib/site-packages/anaconda_project/project_lock_file.py
# -*- coding: utf-8 -*-
# -----------------------------------------------------------------------------
# Copyright (c) 2016, Anaconda, Inc. All rights reserved.
#
# Licensed under the terms of the BSD 3-Clause License.
# The full license is in the file LICENSE.txt, distributed with this software.
# -----------------------------------------------------------------------------
"""Project lock file loading and manipulation."""
from __future__ import absolute_import
import os
from anaconda_project.yaml_file import YamlFile, _CommentedMap, _block_style_all_nodes
# these are in the order we'll use them if multiple are present
possible_project_lock_file_names = ("anaconda-project-lock.yml", "anaconda-project-lock.yaml")
DEFAULT_PROJECT_LOCK_FILENAME = possible_project_lock_file_names[0]
class ProjectLockFile(YamlFile):
"""Represents the ``anaconda-project-lock.yml`` file which describes locked package versions."""
template = '''
# This is an Anaconda project lock file.
# The lock file locks down exact versions of all your dependencies.
#
# In most cases, this file is automatically maintained by the `anaconda-project` command or GUI tools.
# It's best to keep this file in revision control (such as git or svn).
# The file is in YAML format, please see http://www.yaml.org/start.html for more.
#
#
# Set to false to ignore locked versions.
#
locking_enabled: false
#
# A key goes in here for each env spec.
#
env_specs: {}
'''
@classmethod
def load_for_directory(cls, directory, scan_parents=True):
"""Load the project lock file from the given directory, even if it doesn't exist.
If the directory has no project file, the loaded
``ProjectLockFile`` will be empty. It won't actually be
created on disk unless you call ``save()``.
If the file has syntax problems, this sets the
``corrupted`` and ``corrupted_error_message`` properties,
and attempts to modify the file will raise an
exception. If the project file has semantic problems, they
are not detected by this class but are reported by the
``Project`` class.
Args:
directory (str): path to the project directory
Returns:
a new ``ProjectLockFile``
"""
current_dir = directory
while current_dir != os.path.realpath(os.path.dirname(current_dir)):
for name in possible_project_lock_file_names:
path = os.path.join(current_dir, name)
if os.path.isfile(path):
return ProjectLockFile(path)
if scan_parents:
current_dir = os.path.dirname(os.path.abspath(current_dir))
continue
else:
break
# No file was found, create a new one
return ProjectLockFile(os.path.join(directory, DEFAULT_PROJECT_LOCK_FILENAME))
def __init__(self, filename):
"""Construct a ``ProjectLockFile`` with the given filename.
It's easier to use ``ProjectLockFile.load_for_directory()`` in most cases.
If the file has syntax problems, this sets the
``corrupted`` and ``corrupted_error_message`` properties,
and attempts to modify the file will raise an
exception. If the project file has semantic problems, they
are not detected by this class but are reported by the
``Project`` class.
Args:
filename (str): path to the project file
"""
super(ProjectLockFile, self).__init__(filename)
def _save_default_content(self):
# We don't want to save empty lock files.
return False
def _set_lock_set_hash(self, env_spec_name, env_spec_hash):
"""Library-internal method."""
self.set_value(['env_specs', env_spec_name, 'env_spec_hash'], env_spec_hash)
def _set_lock_set(self, env_spec_name, lock_set, all_names):
"""Library-internal method."""
assert env_spec_name is not None
assert lock_set is not None
assert all_names is not None
assert env_spec_name in all_names
# if all locking is disabled, switch to individually
# disabling each env spec so we can enable the one
# we care about here.
for_all = self.get_value(['locking_enabled'], True)
if not for_all:
self.set_value(['locking_enabled'], True)
new_env_specs = self.get_value(['env_specs'], None)
if new_env_specs is None:
new_env_specs = _CommentedMap()
_block_style_all_nodes(new_env_specs)
self.set_value(['env_specs'], new_env_specs)
for name in all_names:
if name == env_spec_name:
continue
single_env = new_env_specs.get(name, None)
if single_env is None:
single_env = _CommentedMap()
_block_style_all_nodes(single_env)
new_env_specs[name] = single_env
single_env['locked'] = False
# now set up the one env
as_json = lock_set.to_json()
self.set_value(['env_specs', env_spec_name], as_json)
def _add_pip_packages(self, env_spec_name, pip_packages):
self.set_value(['env_specs', env_spec_name, 'packages', 'pip'], pip_packages)
def _disable_locking(self, env_spec_name):
"""Library-internal method."""
if env_spec_name is None:
self.set_value(['locking_enabled'], False)
self.unset_value(['env_specs'])
else:
self.set_value(['env_specs', env_spec_name, 'locked'], False)
self.unset_value(['env_specs', env_spec_name, 'packages'])
self.unset_value(['env_specs', env_spec_name, 'platforms'])