Пример #1
0
def _conda_combine_key(spec):
    parsed = conda_api.parse_spec(spec)
    if parsed is None:
        # this is broken but we complain about it in project.py, carry on here
        return spec
    else:
        return parsed.name
Пример #2
0
def test_pip_style_specs():
    cases = [('foo>=1.0', ('foo', None, '>=1.0')), ('foo >=1.0', ('foo', None, '>=1.0')), ('FOO-Bar >=1.0',
                                                                                           ('foo-bar', None, '>=1.0')),
             ('foo >= 1.0', ('foo', None, '>=1.0')), ('foo > 1.0', ('foo', None, '>1.0')),
             ('foo != 1.0', ('foo', None, '!=1.0')), ('foo <1.0', ('foo', None, '<1.0')), ('foo >=1.0 , < 2.0',
                                                                                           ('foo', None, '>=1.0,<2.0'))]
    for case in cases:
        assert conda_api.parse_spec(case[0]) == case[1]
Пример #3
0
    def __init__(self,
                 name,
                 conda_packages,
                 channels,
                 pip_packages=(),
                 description=None,
                 inherit_from_names=(),
                 inherit_from=()):
        """Construct a package set with the given name and packages.

        Args:
            name (str): name of the package set
            conda_packages (list): list of package specs to pass to conda install
            channels (list): list of channel names
            pip_packages (list): list of pip package specs to pass to pip
            description (str or None): one-sentence-ish summary of what this env is
            inherit_from_name (str or None): name of what we inherit from
            inherit_from (EnvSpec or None): pull in packages and channels from
        """
        assert inherit_from_names is not None
        assert inherit_from is not None

        self._name = name
        self._conda_packages = tuple(conda_packages)
        self._channels = tuple(channels)
        self._pip_packages = tuple(pip_packages)
        self._description = description
        self._channels_and_packages_hash = None
        self._inherit_from_names = inherit_from_names
        self._inherit_from = inherit_from

        # inherit_from must be a subset of inherit_from_names
        # except that we can have an anonymous base env spec for
        # the global packages/channels sections; if there was an
        # error that kept us from creating one of the specs we
        # name as a parent, then self._inherit_from would be a
        # subset rather than equal.
        for name in tuple([spec.name for spec in self._inherit_from]):
            assert name is None or name in self._inherit_from_names

        conda_specs_by_name = dict()
        for spec in self.conda_packages:
            # we quietly skip invalid specs here and let them fail
            # somewhere we can more easily report an error message.
            parsed = conda_api.parse_spec(spec)
            if parsed is not None:
                conda_specs_by_name[parsed.name] = spec
        self._conda_specs_by_name = conda_specs_by_name

        pip_specs_by_name = dict()
        for spec in self.pip_packages:
            # we quietly skip invalid specs here and let them fail
            # somewhere we can more easily report an error message.
            parsed = pip_api.parse_spec(spec)
            if parsed is not None:
                pip_specs_by_name[parsed.name] = spec
        self._pip_specs_by_name = pip_specs_by_name
Пример #4
0
        def _parse_packages(parent_dict):
            (deps, pip_dicts) = _parse_string_list_with_special(parent_dict, 'packages', 'package name',
                                                                lambda x: isinstance(x, dict) and ('pip' in x))
            for dep in deps:
                parsed = conda_api.parse_spec(dep)
                if parsed is None:
                    problems.append("%s: invalid package specification: %s" % (project_file.filename, dep))

            # note that multiple "pip:" dicts are allowed
            pip_deps = []
            for pip_dict in pip_dicts:
                pip_list = _parse_string_list(pip_dict, 'pip', 'pip package name')
                pip_deps.extend(pip_list)

            for dep in pip_deps:
                parsed = pip_api.parse_spec(dep)
                if parsed is None:
                    problems.append("%s: invalid pip package specifier: %s" % (project_file.filename, dep))

            return (deps, pip_deps)
Пример #5
0
        def _parse_packages(parent_dict):
            (deps, pip_dicts) = _parse_string_list_with_special(
                parent_dict, 'packages', 'package name',
                lambda x: isinstance(x, dict) and ('pip' in x))
            for dep in deps:
                parsed = conda_api.parse_spec(dep)
                if parsed is None:
                    problems.append("%s: invalid package specification: %s" %
                                    (project_file.filename, dep))

            # note that multiple "pip:" dicts are allowed
            pip_deps = []
            for pip_dict in pip_dicts:
                pip_list = _parse_string_list(pip_dict, 'pip',
                                              'pip package name')
                pip_deps.extend(pip_list)

            for dep in pip_deps:
                parsed = pip_api.parse_spec(dep)
                if parsed is None:
                    problems.append("%s: invalid pip package specifier: %s" %
                                    (project_file.filename, dep))

            return (deps, pip_deps)
Пример #6
0
def test_invalid_specs():
    invalids = ['=', 'foo 1.0', '>']
    for invalid in invalids:
        assert conda_api.parse_spec(invalid) is None
Пример #7
0
 def conda_package_names_set(self):
     """Conda package names that we require, as a Python set."""
     names = set()
     for spec in self.conda_packages:
         names.add(conda_api.parse_spec(spec).name)
     return names
Пример #8
0
 def replace_spec(old):
     name = parse_spec(old).name
     for (replaced_name, new_spec) in updated_specs:
         if replaced_name == name:
             return new_spec
     return old
Пример #9
0
def _update_env_spec(project, name, packages, channels, create):
    failed = project.problems_status()
    if failed is not None:
        return failed

    if packages is None:
        packages = []
    if channels is None:
        channels = []

    if not create and (name is not None):
        if name not in project.env_specs:
            problem = "Environment spec {} doesn't exist.".format(name)
            return SimpleStatus(success=False, description=problem)

    if name is None:
        env_dict = project.project_file.root
    else:
        env_dict = project.project_file.get_value(['env_specs', name])
        if env_dict is None:
            env_dict = dict()
            project.project_file.set_value(['env_specs', name], env_dict)

    # packages may be a "CommentedSeq" and we don't want to lose the comments,
    # so don't convert this thing to a regular list.
    old_packages = env_dict.get('packages', [])
    old_packages_set = set(parse_spec(dep).name for dep in old_packages)
    bad_specs = []
    updated_specs = []
    new_specs = []
    for dep in packages:
        if dep in old_packages:
            # no-op adding the EXACT same thing (don't move it around)
            continue
        parsed = parse_spec(dep)
        if parsed is None:
            bad_specs.append(dep)
        else:
            if parsed.name in old_packages_set:
                updated_specs.append((parsed.name, dep))
            else:
                new_specs.append(dep)

    if len(bad_specs) > 0:
        bad_specs_string = ", ".join(bad_specs)
        return SimpleStatus(success=False,
                            description="Could not add packages.",
                            errors=[("Bad package specifications: %s." %
                                     bad_specs_string)])

    # remove everything that we are changing the spec for
    def replace_spec(old):
        name = parse_spec(old).name
        for (replaced_name, new_spec) in updated_specs:
            if replaced_name == name:
                return new_spec
        return old

    _map_inplace(replace_spec, old_packages)
    # add all the new ones
    for added in new_specs:
        old_packages.append(added)

    env_dict['packages'] = old_packages

    # channels may be a "CommentedSeq" and we don't want to lose the comments,
    # so don't convert this thing to a regular list.
    new_channels = env_dict.get('channels', [])
    old_channels_set = set(new_channels)
    for channel in channels:
        if channel not in old_channels_set:
            new_channels.append(channel)
    env_dict['channels'] = new_channels

    status = _commit_requirement_if_it_works(project,
                                             CondaEnvRequirement,
                                             env_spec_name=name)

    return status
Пример #10
0
def test_conda_style_specs():
    cases = [('foo', ('foo', None, None)), ('foo=1.0', ('foo', '=1.0', None)), ('foo=1.0*', ('foo', '=1.0*', None)),
             ('foo=1.0|1.2', ('foo', '=1.0|1.2', None)), ('foo=1.0=2', ('foo', '=1.0=2', None))]
    for case in cases:
        assert conda_api.parse_spec(case[0]) == case[1]
Пример #11
0
def test_invalid_specs():
    invalids = ['=', 'foo 1.0', '>']
    for invalid in invalids:
        assert conda_api.parse_spec(invalid) is None
Пример #12
0
 def replace_spec(old):
     name = parse_spec(old).name
     for (replaced_name, new_spec) in updated_specs:
         if replaced_name == name:
             return new_spec
     return old
Пример #13
0
def _update_env_spec(project, name, packages, channels, create):
    failed = project.problems_status()
    if failed is not None:
        return failed

    if packages is None:
        packages = []
    if channels is None:
        channels = []

    if not create and (name is not None):
        if name not in project.env_specs:
            problem = "Environment spec {} doesn't exist.".format(name)
            return SimpleStatus(success=False, description=problem)

    if name is None:
        env_dict = project.project_file.root
    else:
        env_dict = project.project_file.get_value(['env_specs', name])
        if env_dict is None:
            env_dict = dict()
            project.project_file.set_value(['env_specs', name], env_dict)

    # packages may be a "CommentedSeq" and we don't want to lose the comments,
    # so don't convert this thing to a regular list.
    old_packages = env_dict.get('packages', [])
    old_packages_set = set(parse_spec(dep).name for dep in old_packages)
    bad_specs = []
    updated_specs = []
    new_specs = []
    for dep in packages:
        if dep in old_packages:
            # no-op adding the EXACT same thing (don't move it around)
            continue
        parsed = parse_spec(dep)
        if parsed is None:
            bad_specs.append(dep)
        else:
            if parsed.name in old_packages_set:
                updated_specs.append((parsed.name, dep))
            else:
                new_specs.append(dep)

    if len(bad_specs) > 0:
        bad_specs_string = ", ".join(bad_specs)
        return SimpleStatus(success=False,
                            description="Could not add packages.",
                            errors=[("Bad package specifications: %s." % bad_specs_string)])

    # remove everything that we are changing the spec for
    def replace_spec(old):
        name = parse_spec(old).name
        for (replaced_name, new_spec) in updated_specs:
            if replaced_name == name:
                return new_spec
        return old

    _map_inplace(replace_spec, old_packages)
    # add all the new ones
    for added in new_specs:
        old_packages.append(added)

    env_dict['packages'] = old_packages

    # channels may be a "CommentedSeq" and we don't want to lose the comments,
    # so don't convert this thing to a regular list.
    new_channels = env_dict.get('channels', [])
    old_channels_set = set(new_channels)
    for channel in channels:
        if channel not in old_channels_set:
            new_channels.append(channel)
    env_dict['channels'] = new_channels

    status = _commit_requirement_if_it_works(project, CondaEnvRequirement, env_spec_name=name)

    return status