assertpy
Advanced tools
+132
-50
@@ -43,3 +43,3 @@ # Copyright (c) 2015-2018, Activision Publishing, Inc. | ||
| __version__ = '0.13' | ||
| __version__ = '0.14' | ||
@@ -165,4 +165,4 @@ __tracebackhide__ = True # clean tracebacks via py.test integration | ||
| if self._check_dict_like(self.val, check_values=False, return_as_bool=True) and self._check_dict_like(other, check_values=False, return_as_bool=True): | ||
| if self._dict_not_equal(self.val, other, ignore=kwargs.get('ignore')): | ||
| self._dict_err(self.val, other, ignore=kwargs.get('ignore')) | ||
| if self._dict_not_equal(self.val, other, ignore=kwargs.get('ignore'), include=kwargs.get('include')): | ||
| self._dict_err(self.val, other, ignore=kwargs.get('ignore'), include=kwargs.get('include')) | ||
| else: | ||
@@ -508,25 +508,7 @@ if self.val != other: | ||
| """Asserts that val is numeric and is between low and high.""" | ||
| self_type = type(self.val) | ||
| low_type = type(low) | ||
| high_type = type(high) | ||
| val_type = type(self.val) | ||
| self._validate_between_args(val_type, low, high) | ||
| if self_type in self.NON_COMPAREABLE_TYPES: | ||
| raise TypeError('ordering is not defined for type <%s>' % self_type.__name__) | ||
| if self_type in self.COMPAREABLE_TYPES: | ||
| if low_type is not self_type: | ||
| raise TypeError('given low arg must be <%s>, but was <%s>' % (self_type.__name__, low_type.__name__)) | ||
| if high_type is not self_type: | ||
| raise TypeError('given high arg must be <%s>, but was <%s>' % (self_type.__name__, low_type.__name__)) | ||
| elif isinstance(self.val, numbers.Number): | ||
| if isinstance(low, numbers.Number) is False: | ||
| raise TypeError('given low arg must be numeric, but was <%s>' % low_type.__name__) | ||
| if isinstance(high, numbers.Number) is False: | ||
| raise TypeError('given high arg must be numeric, but was <%s>' % high_type.__name__) | ||
| else: | ||
| raise TypeError('ordering is not defined for type <%s>' % self_type.__name__) | ||
| if low > high: | ||
| raise ValueError('given low arg must be less than given high arg') | ||
| if self.val < low or self.val > high: | ||
| if self_type is datetime.datetime: | ||
| if val_type is datetime.datetime: | ||
| self._err('Expected <%s> to be between <%s> and <%s>, but was not.' % (self.val.strftime('%Y-%m-%d %H:%M:%S'), low.strftime('%Y-%m-%d %H:%M:%S'), high.strftime('%Y-%m-%d %H:%M:%S'))) | ||
@@ -537,20 +519,18 @@ else: | ||
| def is_not_between(self, low, high): | ||
| """Asserts that val is numeric and is between low and high.""" | ||
| val_type = type(self.val) | ||
| self._validate_between_args(val_type, low, high) | ||
| if self.val >= low and self.val <= high: | ||
| if val_type is datetime.datetime: | ||
| self._err('Expected <%s> to not be between <%s> and <%s>, but was.' % (self.val.strftime('%Y-%m-%d %H:%M:%S'), low.strftime('%Y-%m-%d %H:%M:%S'), high.strftime('%Y-%m-%d %H:%M:%S'))) | ||
| else: | ||
| self._err('Expected <%s> to not be between <%s> and <%s>, but was.' % (self.val, low, high)) | ||
| return self | ||
| def is_close_to(self, other, tolerance): | ||
| """Asserts that val is numeric and is close to other within tolerance.""" | ||
| if type(self.val) is complex or type(other) is complex or type(tolerance) is complex: | ||
| raise TypeError('ordering is not defined for complex numbers') | ||
| if isinstance(self.val, numbers.Number) is False and type(self.val) is not datetime.datetime: | ||
| raise TypeError('val is not numeric or datetime') | ||
| if type(self.val) is datetime.datetime: | ||
| if type(other) is not datetime.datetime: | ||
| raise TypeError('given arg must be datetime, but was <%s>' % type(other).__name__) | ||
| if type(tolerance) is not datetime.timedelta: | ||
| raise TypeError('given tolerance arg must be timedelta, but was <%s>' % type(tolerance).__name__) | ||
| else: | ||
| if isinstance(other, numbers.Number) is False: | ||
| raise TypeError('given arg must be numeric') | ||
| if isinstance(tolerance, numbers.Number) is False: | ||
| raise TypeError('given tolerance arg must be numeric') | ||
| if tolerance < 0: | ||
| raise ValueError('given tolerance arg must be positive') | ||
| self._validate_close_to_args(self.val, other, tolerance) | ||
| if self.val < (other-tolerance) or self.val > (other+tolerance): | ||
@@ -566,2 +546,16 @@ if type(self.val) is datetime.datetime: | ||
| def is_not_close_to(self, other, tolerance): | ||
| """Asserts that val is numeric and is not close to other within tolerance.""" | ||
| self._validate_close_to_args(self.val, other, tolerance) | ||
| if self.val >= (other-tolerance) and self.val <= (other+tolerance): | ||
| if type(self.val) is datetime.datetime: | ||
| tolerance_seconds = tolerance.days * 86400 + tolerance.seconds + tolerance.microseconds / 1000000 | ||
| h, rem = divmod(tolerance_seconds, 3600) | ||
| m, s = divmod(rem, 60) | ||
| self._err('Expected <%s> to not be close to <%s> within tolerance <%d:%02d:%02d>, but was.' % (self.val.strftime('%Y-%m-%d %H:%M:%S'), other.strftime('%Y-%m-%d %H:%M:%S'), h, m, s)) | ||
| else: | ||
| self._err('Expected <%s> to not be close to <%s> within tolerance <%s>, but was.' % (self.val, other, tolerance)) | ||
| return self | ||
| ### string assertions ### | ||
@@ -915,5 +909,13 @@ def is_equal_to_ignoring_case(self, other): | ||
| if not os.path.exists(self.val): | ||
| self._err('Expected <%s> to exist, but not found.' % self.val) | ||
| self._err('Expected <%s> to exist, but was not found.' % self.val) | ||
| return self | ||
| def does_not_exist(self): | ||
| """Asserts that val is a path and that it does not exist.""" | ||
| if not isinstance(self.val, str_types): | ||
| raise TypeError('val is not a path') | ||
| if os.path.exists(self.val): | ||
| self._err('Expected <%s> to not exist, but was found.' % self.val) | ||
| return self | ||
| def is_file(self): | ||
@@ -1134,2 +1136,45 @@ """Asserts that val is an existing path to a file.""" | ||
| def _validate_between_args(self, val_type, low, high): | ||
| low_type = type(low) | ||
| high_type = type(high) | ||
| if val_type in self.NON_COMPAREABLE_TYPES: | ||
| raise TypeError('ordering is not defined for type <%s>' % val_type.__name__) | ||
| if val_type in self.COMPAREABLE_TYPES: | ||
| if low_type is not val_type: | ||
| raise TypeError('given low arg must be <%s>, but was <%s>' % (val_type.__name__, low_type.__name__)) | ||
| if high_type is not val_type: | ||
| raise TypeError('given high arg must be <%s>, but was <%s>' % (val_type.__name__, low_type.__name__)) | ||
| elif isinstance(self.val, numbers.Number): | ||
| if isinstance(low, numbers.Number) is False: | ||
| raise TypeError('given low arg must be numeric, but was <%s>' % low_type.__name__) | ||
| if isinstance(high, numbers.Number) is False: | ||
| raise TypeError('given high arg must be numeric, but was <%s>' % high_type.__name__) | ||
| else: | ||
| raise TypeError('ordering is not defined for type <%s>' % val_type.__name__) | ||
| if low > high: | ||
| raise ValueError('given low arg must be less than given high arg') | ||
| def _validate_close_to_args(self, val, other, tolerance): | ||
| if type(val) is complex or type(other) is complex or type(tolerance) is complex: | ||
| raise TypeError('ordering is not defined for complex numbers') | ||
| if isinstance(val, numbers.Number) is False and type(val) is not datetime.datetime: | ||
| raise TypeError('val is not numeric or datetime') | ||
| if type(val) is datetime.datetime: | ||
| if type(other) is not datetime.datetime: | ||
| raise TypeError('given arg must be datetime, but was <%s>' % type(other).__name__) | ||
| if type(tolerance) is not datetime.timedelta: | ||
| raise TypeError('given tolerance arg must be timedelta, but was <%s>' % type(tolerance).__name__) | ||
| else: | ||
| if isinstance(other, numbers.Number) is False: | ||
| raise TypeError('given arg must be numeric') | ||
| if isinstance(tolerance, numbers.Number) is False: | ||
| raise TypeError('given tolerance arg must be numeric') | ||
| if tolerance < 0: | ||
| raise ValueError('given tolerance arg must be positive') | ||
| def _check_dict_like(self, d, check_keys=True, check_values=True, check_getitem=True, name='val', return_as_bool=False): | ||
@@ -1162,7 +1207,35 @@ if not isinstance(d, collections.Iterable): | ||
| def _dict_not_equal(self, val, other, ignore=None): | ||
| if ignore: | ||
| def _dict_not_equal(self, val, other, ignore=None, include=None): | ||
| if ignore or include: | ||
| ignores = self._dict_ignore(ignore) | ||
| k1 = set([k for k in val if k not in ignores]) | ||
| k2 = set([k for k in other if k not in ignores]) | ||
| includes = self._dict_include(include) | ||
| # guarantee include keys are in val | ||
| if include: | ||
| missing = [] | ||
| for i in includes: | ||
| if i not in val: | ||
| missing.append(i) | ||
| if missing: | ||
| self._err('Expected <%s> to include key%s %s, but did not include key%s %s.' % ( | ||
| val, | ||
| '' if len(includes) == 1 else 's', | ||
| self._fmt_items(['.'.join([str(s) for s in i]) if type(i) is tuple else i for i in includes]), | ||
| '' if len(missing) == 1 else 's', | ||
| self._fmt_items(missing))) | ||
| if ignore and include: | ||
| k1 = set([k for k in val if k not in ignores and k in includes]) | ||
| elif ignore: | ||
| k1 = set([k for k in val if k not in ignores]) | ||
| else: # include | ||
| k1 = set([k for k in val if k in includes]) | ||
| if ignore and include: | ||
| k2 = set([k for k in other if k not in ignores and k in includes]) | ||
| elif ignore: | ||
| k2 = set([k for k in other if k not in ignores]) | ||
| else: # include | ||
| k2 = set([k for k in other if k in includes]) | ||
| if k1 != k2: | ||
@@ -1173,7 +1246,8 @@ return True | ||
| if self._check_dict_like(val[k], check_values=False, return_as_bool=True) and self._check_dict_like(other[k], check_values=False, return_as_bool=True): | ||
| return self._dict_not_equal(val[k], other[k], ignore=[i[1:] for i in ignores if type(i) is tuple and i[0] == k]) | ||
| return self._dict_not_equal(val[k], other[k], | ||
| ignore=[i[1:] for i in ignores if type(i) is tuple and i[0] == k] if ignore else None, | ||
| include=[i[1:] for i in self._dict_ignore(include) if type(i) is tuple and i[0] == k] if include else None) | ||
| elif val[k] != other[k]: | ||
| return True | ||
| return False | ||
| #return k1 != k2 or any(val[k] != other[k] for k in k1) | ||
| else: | ||
@@ -1186,3 +1260,7 @@ return val != other | ||
| def _dict_err(self, val, other, ignore=None): | ||
| def _dict_include(self, include): | ||
| return [i[0] if type(i) is tuple else i \ | ||
| for i in (include if type(include) is list else [include])] | ||
| def _dict_err(self, val, other, ignore=None, include=None): | ||
| def _dict_repr(d, other): | ||
@@ -1205,7 +1283,11 @@ out = '' | ||
| ignore_err = ' ignoring keys %s' % self._fmt_items(['.'.join([str(s) for s in i]) if type(i) is tuple else i for i in ignores]) | ||
| if include: | ||
| includes = self._dict_ignore(include) | ||
| include_err = ' including keys %s' % self._fmt_items(['.'.join([str(s) for s in i]) if type(i) is tuple else i for i in includes]) | ||
| self._err('Expected <%s> to be equal to <%s>%s, but was not.' % ( | ||
| self._err('Expected <%s> to be equal to <%s>%s%s, but was not.' % ( | ||
| _dict_repr(val, other), | ||
| _dict_repr(other, val), | ||
| ignore_err if ignore else '' | ||
| ignore_err if ignore else '', | ||
| include_err if include else '' | ||
| )) | ||
@@ -1212,0 +1294,0 @@ |
+2
-2
| Metadata-Version: 1.1 | ||
| Name: assertpy | ||
| Version: 0.13 | ||
| Version: 0.14 | ||
| Summary: Assertion library for python unit testing with a fluent API | ||
@@ -9,3 +9,3 @@ Home-page: https://github.com/ActivisionGameScience/assertpy | ||
| License: BSD | ||
| Download-URL: https://codeload.github.com/ActivisionGameScience/assertpy/tar.gz/0.13 | ||
| Download-URL: https://codeload.github.com/ActivisionGameScience/assertpy/tar.gz/0.14 | ||
| Description: assertpy | ||
@@ -12,0 +12,0 @@ ======== |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
67043
6.23%1263
5.43%