def check_removal_version(v, version_field, collection_name_field, error_code='invalid-removal-version'): version = v.get(version_field) collection_name = v.get(collection_name_field) if not isinstance(version, string_types) or not isinstance(collection_name, string_types): # If they are not strings, schema validation will have already complained. return v if collection_name == 'ansible.builtin': try: parsed_version = StrictVersion() parsed_version.parse(version) except ValueError as exc: raise _add_ansible_error_code( Invalid('%s (%r) is not a valid ansible-core version: %s' % (version_field, version, exc)), error_code=error_code) return v try: parsed_version = SemanticVersion() parsed_version.parse(version) if parsed_version.major != 0 and (parsed_version.minor != 0 or parsed_version.patch != 0): raise _add_ansible_error_code( Invalid('%s (%r) must be a major release, not a minor or patch release (see specification at ' 'https://semver.org/)' % (version_field, version)), error_code='removal-version-must-be-major') except ValueError as exc: raise _add_ansible_error_code( Invalid('%s (%r) is not a valid collection version (see specification at https://semver.org/): ' '%s' % (version_field, version, exc)), error_code=error_code) return v
def version_added(v): if 'version_added' in v: version_added = v.get('version_added') if isinstance(version_added, string_types): # If it is not a string, schema validation will have already complained # - or we have a float and we are in ansible/ansible, in which case we're # also happy. if v.get('version_added_collection') == 'ansible.builtin': try: version = StrictVersion() version.parse(version_added) except ValueError as exc: raise _add_ansible_error_code( Invalid( 'version_added (%r) is not a valid ansible-base version: ' '%s' % (version_added, exc)), error_code='deprecation-either-date-or-version') else: try: version = SemanticVersion() version.parse(version_added) except ValueError as exc: raise _add_ansible_error_code( Invalid( 'version_added (%r) is not a valid collection version ' '(see specification at https://semver.org/): ' '%s' % (version_added, exc)), error_code='deprecation-either-date-or-version') elif 'version_added_collection' in v: # Must have been manual intervention, since version_added_collection is only # added automatically when version_added is present raise Invalid( 'version_added_collection cannot be specified without version_added' ) return v
def version_init(self, s): '''Chcek if valid version string, using distutils.StrictVersion :param s: :return: ''' VersionChecker = StrictVersion() VersionChecker.parse(s) # raises ValueError if no agreement return s
def validate_version(version): validator = StrictVersion() try: validator.parse(version) except: raise ValidationError('invalid version {}'.format(version)) return version
def __cmp__(self, other): if self.version is None or other.version is None: # cannot compare None version raise Exception("Unable to compare None versions") try: sv = StrictVersion() sv.parse(self.version) return sv.__cmp__(other.version) except Exception: return LooseVersion(self.version).__cmp__(LooseVersion(other.version))
def version_added(v, error_code='version-added-invalid', accept_historical=False): if 'version_added' in v: version_added = v.get('version_added') if isinstance(version_added, string_types): # If it is not a string, schema validation will have already complained # - or we have a float and we are in ansible/ansible, in which case we're # also happy. if v.get('version_added_collection') == 'ansible.builtin': if version_added == 'historical' and accept_historical: return v try: version = StrictVersion() version.parse(version_added) except ValueError as exc: raise _add_ansible_error_code(Invalid( 'version_added (%r) is not a valid ansible-core version: ' '%s' % (version_added, exc)), error_code=error_code) else: try: version = SemanticVersion() version.parse(version_added) if version.major != 0 and version.patch != 0: raise _add_ansible_error_code( Invalid( 'version_added (%r) must be a major or minor release, ' 'not a patch release (see specification at ' 'https://semver.org/)' % (version_added, )), error_code='version-added-must-be-major-or-minor') except ValueError as exc: raise _add_ansible_error_code(Invalid( 'version_added (%r) is not a valid collection version ' '(see specification at https://semver.org/): ' '%s' % (version_added, exc)), error_code=error_code) elif 'version_added_collection' in v: # Must have been manual intervention, since version_added_collection is only # added automatically when version_added is present raise Invalid( 'version_added_collection cannot be specified without version_added' ) return v
def removal_version(value, is_assible): """Validate a removal version string.""" msg = ('Removal version must be a string' if is_assible else 'Removal version must be a semantic version (https://semver.org/)') if not isinstance(value, string_types): raise Invalid(msg) try: if is_assible: version = StrictVersion() version.parse(value) else: version = SemanticVersion() version.parse(value) if version.major != 0 and (version.minor != 0 or version.patch != 0): raise Invalid( 'removal_version (%r) must be a major release, not a minor or patch release ' '(see specification at https://semver.org/)' % (value, )) except ValueError: raise Invalid(msg) return value
def removal_version(value, is_ansible, current_version=None, is_tombstone=False): """Validate a removal version string.""" msg = ('Removal version must be a string' if is_ansible else 'Removal version must be a semantic version (https://semver.org/)') if not isinstance(value, string_types): raise Invalid(msg) try: if is_ansible: version = StrictVersion() version.parse(value) version = LooseVersion( value) # We're storing Ansible's version as a LooseVersion else: version = SemanticVersion() version.parse(value) if version.major != 0 and (version.minor != 0 or version.patch != 0): raise Invalid( 'removal_version (%r) must be a major release, not a minor or patch release ' '(see specification at https://semver.org/)' % (value, )) if current_version is not None: if is_tombstone: # For a tombstone, the removal version must not be in the future if version > current_version: raise Invalid( 'The tombstone removal_version (%r) must not be after the ' 'current version (%s)' % (value, current_version)) else: # For a deprecation, the removal version must be in the future if version <= current_version: raise Invalid( 'The deprecation removal_version (%r) must be after the ' 'current version (%s)' % (value, current_version)) except ValueError: raise Invalid(msg) return value
def load_config(filename): """ Load the configuration file and test if version is supported. """ (_, ext) = os.path.splitext(filename) config = None if ext == '.json': import json with open(filename, 'rb') as fds: config = json.load(fds) elif ext == '.yml': import yaml with open(filename, 'rb') as fds: config = yaml.safe_load(fds) else: logging.error('Config file extension not recognized: %s', filename) sys.exit(1) file_version_string = config.get('header', {}).get('version', None) if file_version_string is None: logging.error('Version missing: %s', filename) sys.exit(1) try: if not isinstance(file_version_string, str): logging.error('Version has to be a string: %s', filename) sys.exit(1) file_version = StrictVersion() file_version.parse(file_version_string) kas_version = StrictVersion() kas_version.parse(__version__) lower_version = StrictVersion() lower_version.parse(__compatible_version__) # Remove patch version, because we provide limited forwards # compatibility: if file_version.version[2] > 0: file_version.prerelease = None file_version.version = tuple(list(file_version.version[:2]) + [0]) if file_version < lower_version or kas_version < file_version: logging.error( 'This version of kas is compatible with version %s ' 'to %s, file has version %s: %s', lower_version, kas_version, file_version, filename) sys.exit(1) except ValueError: logging.exception('Not expected version format: %s', filename) raise return config
def parse(self, vstring): _StrictVersion.parse(self, vstring)
def parse(self, vstring): _StrictVersion.parse(self, vstring) if six.PY3: # Convert every part of the version to string in order to be able to compare self.version = [str(vp) for vp in self.version]