Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/4.4.x' into conda-shell-cmd.exe-2
Browse files Browse the repository at this point in the history
  • Loading branch information
kalefranz committed Jun 1, 2017
2 parents e4a929a + 4eff84e commit 805355a
Show file tree
Hide file tree
Showing 105 changed files with 5,900 additions and 1,918 deletions.
4 changes: 2 additions & 2 deletions .codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ ignore:
- conda/console.py
- conda/cli/activate.py
- conda/cli/main_package.py
- conda/gateways/adapters/ftp.py
- conda/gateways/adapters/s3.py
- conda/gateways/connection/adapters/ftp.py
- conda/gateways/connection/adapters/s3.py
- tests/.*

comment: off
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ matrix:
packages:
- dash
- zsh
- env: PYTHON_VERSION=3.6 CONDA_BUILD=2.1.10
- env: PYTHON_VERSION=3.6 CONDA_BUILD=2.1.15
sudo: false
language: generic
os: linux
- env: PYTHON_VERSION=3.6 CONDA_BUILD=3.0.0beta1
- env: PYTHON_VERSION=3.6 CONDA_BUILD=3.0.0rc1
sudo: false
language: generic
os: linux
Expand All @@ -56,7 +56,7 @@ matrix:
os: osx
allow_failures:
- os: osx
- env: PYTHON_VERSION=3.6 CONDA_BUILD=3.0.0beta1
- env: PYTHON_VERSION=3.6 CONDA_BUILD=3.0.0rc1

install:
- source utils/functions.sh && run_setup
Expand Down
59 changes: 58 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@
* resolve #3763, #4378 allow pip requirements.txt syntax in environment files (#3969)
* resolve #5147 add 'config files' to conda info (#5269)
* use --format=json to parse list of pip packages (#5205)
* resolve #1427 remove startswith '.' environment name constraint (#5284)
* link packages from extracted tarballs when tarball is gone (#5289)
* resolve #2511 accept config information from stdin (#5309)
* resolve #4302 add ability to set map parameters with conda config (#5310)
* resolve #5256 enable conda config --get for all primitive parameters (#5312)
* resolve #1992 add short flag -C for --use-index-cache (#5314)
* resolve #2173 add --quiet option to conda clean (#5313)
* resolve #5358 conda should exec to subcommands, not subprocess (#5359)
* resolve #5411 add 'conda config --write-default' (#5412)
* resolve #5081 make pinned packages optional dependencies (#5414)

### Bug Fixes
* fix some conda-build compatibility issues (#5089)
Expand All @@ -32,6 +42,11 @@
* fix #4987 conda update --all no longer displays full list of packages (#5228)
* fix #3489 don't error on remove --all if environment doesn't exist (#5231)
* fix #1509 bash doesn't need full path for pre/post link/unlink scripts on unix (#5252)
* fix #462 add regression test (#5286)
* fix #5288 confirmation prompt doesn't accept no (#5291)
* fix #1713 'conda package -w' is case dependent on Windows (#5308)
* fix #5371 try falling back to pip's vendored requests if no requests available (#5372)
* fix #5356 skip root logger configuration (#5380)

### Non-User-Facing Changes
* eliminate index modification in Resolve.__init__ (#4333)
Expand All @@ -43,17 +58,59 @@
* extra config command tests (#5185)
* add coverage for confirm (#5203)
* clean up FileNotFoundError and DirectoryNotFoundError (#5237)
* add assertion that a path only has a single hard link before rewriting prefixes (#5305)
* remove pycrypto as requirement on windows (#5326)


## 4.3.19 (unreleased)
## 4.3.21 (2017-05-25)

### Bug Fixes
* fix #5420 conda-env update error (#5421)
* fix #5425 is admin on win int not callable (#5426)


## 4.3.20 (2017-05-23)

### Improvements
* resolve #5217 skip user confirm in python_api, force always_yes (#5404)

### Bug Fixes
* fix #5367 conda info always shows 'unknown' for admin indicator on Windows (#5368)
* fix #5248 drop plan description information that might not alwasy be accurate (#5373)
* fix #5378 duplicate log messages (#5379)
* fix #5298 record has 'build', not 'build_string' (#5382)
* fix #5384 silence logging info to avoid interfering with JSON output (#5393)
* fix #5356 skip root/conda logger init for cli.python_api (#5405)

### Non-User-Facing Changes
* avoid persistent state after channel priority test (#5392)
* resolve #5402 add regression test for #5384 (#5403)
* clean up inner function definition inside for loop (#5406)


## 4.3.19 (2017-05-18)

### Improvements
* resolve #3689 better error messaging for missing anaconda-client (#5276)
* resolve #4795 conda env export lacks -p flag (#5275)
* resolve #5315 add alias verify_ssl for ssl_verify (#5316)
* resolve #3399 add netrc existence/location to 'conda info' (#5333)
* resolve #3810 add --prefix to conda env update (#5335)

### Bug Fixes
* fix #5272 conda env export ugliness under python2 (#5273)
* fix #4596 warning message from pip on conda env export (#5274)
* fix #4986 --yes not functioning for conda clean (#5311)
* fix #5329 unicode errors on Windows (#5328, #5357)
* fix sys_prefix_unfollowed for Python 3 (#5334)
* fix #5341 --json flag with conda-env (#5342)
* fix 5321 ensure variable PROMPT is set in activate.bat (#5351)

### Non-User-Facing Changes
* test conda 4.3 with requests 2.14.2 (#5281)
* remove pycrypto as requirement on windows (#5325)
* fix typo avaialble -> available (#5345)
* fix test failures related to menuinst update (#5344, #5362)


## 4.3.18 (2017-05-09)
Expand Down
2 changes: 1 addition & 1 deletion conda/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def dump_map(self):


class CondaExitZero(CondaError):
pass
return_code = 0


ACTIVE_SUBPROCESSES = set()
Expand Down
63 changes: 42 additions & 21 deletions conda/_vendor/auxlib/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@
from .compat import (integer_types, iteritems, itervalues, odict, string_types, text_type,
with_metaclass, isiterable)
from .exceptions import Raise, ValidationError
from .ish import find_or_none
from .ish import find_or_none, find_or_raise
from .logz import DumpEncoder
from .type_coercion import maybecall

Expand Down Expand Up @@ -369,12 +369,13 @@ class Field(object):
_order_helper = 0

def __init__(self, default=None, required=True, validation=None,
in_dump=True, nullable=False, immutable=False):
in_dump=True, nullable=False, immutable=False, aliases=()):
self._required = required
self._validation = validation
self._in_dump = in_dump
self._nullable = nullable
self._immutable = immutable
self._aliases = aliases
self._default = default if callable(default) else self.box(None, default)
if default is not None:
self.validate(None, self.box(None, maybecall(default)))
Expand Down Expand Up @@ -535,12 +536,12 @@ def dump(self, val):
class EnumField(Field):

def __init__(self, enum_class, default=None, required=True, validation=None,
in_dump=True, nullable=False, immutable=False):
in_dump=True, nullable=False, immutable=False, aliases=()):
if not issubclass(enum_class, Enum):
raise ValidationError(None, msg="enum_class must be an instance of Enum")
self._type = enum_class
super(EnumField, self).__init__(default, required, validation,
in_dump, nullable, immutable)
in_dump, nullable, immutable, aliases)

def box(self, instance, val):
if val is None:
Expand All @@ -564,10 +565,10 @@ class ListField(Field):
_type = tuple

def __init__(self, element_type, default=None, required=True, validation=None,
in_dump=True, nullable=False, immutable=False):
in_dump=True, nullable=False, immutable=False, aliases=()):
self._element_type = element_type
super(ListField, self).__init__(default, required, validation,
in_dump, nullable, immutable)
in_dump, nullable, immutable, aliases)

def box(self, instance, val):
if val is None:
Expand Down Expand Up @@ -615,8 +616,9 @@ class MapField(Field):
_type = frozendict

def __init__(self, default=None, required=True, validation=None,
in_dump=True, nullable=False):
super(MapField, self).__init__(default, required, validation, in_dump, nullable, True)
in_dump=True, nullable=False, aliases=()):
super(MapField, self).__init__(default, required, validation, in_dump, nullable, True,
aliases)

def box(self, instance, val):
# TODO: really need to make this recursive to make any lists or maps immutable
Expand All @@ -633,14 +635,13 @@ def box(self, instance, val):
"{0}".format(self.name))



class ComposableField(Field):

def __init__(self, field_class, default=None, required=True, validation=None,
in_dump=True, nullable=False, immutable=False):
in_dump=True, nullable=False, immutable=False, aliases=()):
self._type = field_class
super(ComposableField, self).__init__(default, required, validation,
in_dump, nullable, immutable)
in_dump, nullable, immutable, aliases)

def box(self, instance, val):
if val is None:
Expand All @@ -655,7 +656,14 @@ def box(self, instance, val):
val['slf'] = val.pop('self')
except KeyError:
pass # no key of 'self', so no worries
return val if isinstance(val, self._type) else self._type(**val)
if isinstance(val, self._type):
return val if isinstance(val, self._type) else self._type(**val)
elif isinstance(val, Mapping):
return self._type(**val)
elif isinstance(val, Sequence) and not isinstance(val, string_types):
return self._type(*val)
else:
return self._type(val)

def dump(self, val):
return None if val is None else val.dump()
Expand Down Expand Up @@ -689,11 +697,15 @@ def __new__(mcs, name, bases, dct):

def __init__(cls, name, bases, attr):
super(EntityType, cls).__init__(name, bases, attr)
fields = odict(cls.__fields__) if hasattr(cls, '__fields__') else odict()
fields.update(sorted(((name, field.set_name(name))
for name, field in iteritems(cls.__dict__)
if isinstance(field, Field)),
key=lambda item: item[1]._order_helper))

fields = odict()
_field_sort_key = lambda x: x[1]._order_helper
for clz in reversed(type.mro(cls)):
clz_fields = ((name, field.set_name(name))
for name, field in iteritems(clz.__dict__)
if isinstance(field, Field))
fields.update(sorted(clz_fields, key=_field_sort_key))

cls.__fields__ = frozendict(fields)
if hasattr(cls, '__register__'):
cls.__register__()
Expand All @@ -718,8 +730,11 @@ def __init__(self, **kwargs):
try:
setattr(self, key, kwargs[key])
except KeyError:
# handle the case of fields inherited from subclass but overrode on class object
if key in getattr(self, KEY_OVERRIDES_MAP):
alias = next((ls for ls in field._aliases if ls in kwargs), None)
if alias is not None:
setattr(self, key, kwargs[alias])
elif key in getattr(self, KEY_OVERRIDES_MAP):
# handle the case of fields inherited from subclass but overrode on class object
setattr(self, key, getattr(self, KEY_OVERRIDES_MAP)[key])
elif field.required and field.default is None:
raise ValidationError(key, msg="{0} requires a {1} field. Instantiated with "
Expand All @@ -736,8 +751,12 @@ def from_objects(cls, *objects, **override_fields):
init_vars = dict()
search_maps = tuple(AttrDict(o) if isinstance(o, dict) else o
for o in ((override_fields,) + objects))
for key in cls.__fields__:
init_vars[key] = find_or_none(key, search_maps)
for key, field in iteritems(cls.__fields__):
try:
init_vars[key] = find_or_raise(key, search_maps, field._aliases)
except AttributeError:
pass

return cls(**init_vars)

@classmethod
Expand Down Expand Up @@ -765,6 +784,8 @@ def _valid(key):
# TODO: re-enable once aliases are implemented
# if key.startswith('_'):
# return False
if '__' in key:
return False
try:
getattr(self, key)
return True
Expand Down
35 changes: 30 additions & 5 deletions conda/_vendor/auxlib/ish.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,20 @@ def dals(string):
return dedent(string).lstrip()


def find_or_none(key, search_maps, _map_index=0):
def _get_attr(obj, attr_name, aliases=()):
try:
return getattr(obj, attr_name)
except AttributeError:
for alias in aliases:
try:
return getattr(obj, alias)
except AttributeError:
continue
else:
raise


def find_or_none(key, search_maps, aliases=(), _map_index=0):
"""Return the value of the first key found in the list of search_maps,
otherwise return None.
Expand All @@ -32,11 +45,23 @@ def find_or_none(key, search_maps, _map_index=0):
"""
try:
attr = getattr(search_maps[_map_index], key)
return attr if attr is not None else find_or_none(key, search_maps[1:])
attr = _get_attr(search_maps[_map_index], key, aliases)
return attr if attr is not None else find_or_none(key, search_maps[1:], aliases)
except AttributeError:
# not found in first map object, so go to next
return find_or_none(key, search_maps, _map_index+1)
# not found in current map object, so go to next
return find_or_none(key, search_maps, aliases, _map_index+1)
except IndexError:
# ran out of map objects to search
return None


def find_or_raise(key, search_maps, aliases=(), _map_index=0):
try:
attr = _get_attr(search_maps[_map_index], key, aliases)
return attr if attr is not None else find_or_raise(key, search_maps[1:], aliases)
except AttributeError:
# not found in current map object, so go to next
return find_or_raise(key, search_maps, aliases, _map_index+1)
except IndexError:
# ran out of map objects to search
raise AttributeError()
Loading

0 comments on commit 805355a

Please sign in to comment.