def test_matches(self): for spec, (matching, failing) in self.matches.items(): spec = version.Spec(spec) for v in [version.Version(v) for v in matching]: self.assertTrue(v in spec, "%r should be in %r" % (v, spec)) self.assertTrue(spec.match(v), "%r should match %r" % (v, spec)) for v in [version.Version(v) for v in failing]: self.assertFalse(v in spec, "%r should not be in %r" % (v, spec)) self.assertFalse(spec.match(v), "%r should not match %r" % (v, spec))
def semanticSpecMatches(self, v): if isinstance(v, str): v = version.Version(v) if self.semantic_spec is None: return True else: return self.semantic_spec.match(v)
def patchType(s): if s.lower() in ('major', 'minor', 'patch'): return s.lower() try: return version.Version(s) except: raise argparse.ArgumentTypeError( '"%s" is not a valid version (expected patch, major, minor, or something like 1.2.3)' % s)
def test_availableVersions(self): versions = self.working_copy.availableVersions() self.assertIn(version.Version('v0.0.1'), versions)
def __init__(self, path, description_filename, installed_linked, schema_filename=None, latest_suitable_version=None, inherit_shrinkwrap=None): # version, , represent versions and specifications, internal from yotta.lib import version # vcs, , represent version controlled directories, internal from yotta.lib import vcs # resolve links at creation time, to minimise path lengths: self.unresolved_path = path self.path = fsutils.realpath(path) self.installed_linked = installed_linked self.vcs = None self.error = None self.latest_suitable_version = latest_suitable_version self.version = None self.description_filename = description_filename self.ignore_list_fname = Ignore_List_Fname self.ignore_patterns = copy.copy(Default_Publish_Ignore) self.origin_info = None description_file = os.path.join(path, description_filename) if os.path.isfile(description_file): try: self.description = ordered_json.load(description_file) if self.description: if not 'name' in self.description: raise Exception('missing "name"') if 'version' in self.description: self.version = version.Version( self.description['version']) else: raise Exception('missing "version"') except Exception as e: self.description = OrderedDict() self.error = "Description invalid %s: %s" % (description_file, e) logger.debug(self.error) raise InvalidDescription(self.error) else: self.error = "No %s file." % description_filename self.description = OrderedDict() try: with open(os.path.join(path, self.ignore_list_fname), 'r') as ignorefile: self.ignore_patterns += self._parseIgnoreFile(ignorefile) except IOError as e: if e.errno != errno.ENOENT: raise # warn about invalid yotta versions before schema errors (as new yotta # might introduce new schema) yotta_version_spec = None if self.description and self.description.get('yotta', None): try: yotta_version_spec = version.Spec(self.description['yotta']) except ValueError as e: logger.warning( "could not parse yotta version spec '%s' from %s: it " + "might require a newer version of yotta", self.description['yotta'], self.description['name']) if yotta_version_spec is not None: import yotta yotta_version = version.Version(yotta.__version__) if not yotta_version_spec.match(yotta_version): self.error = "requires yotta version %s (current version is %s). see http://yottadocs.mbed.com for update instructions" % ( str(yotta_version_spec), str(yotta_version)) if self.description and schema_filename and not self.path in self.schema_errors_displayed: self.schema_errors_displayed.add(self.path) have_errors = False with open(schema_filename, 'r') as schema_file: schema = json.load(schema_file) validator = jsonschema.Draft4Validator(schema) for error in validator.iter_errors(self.description): if not have_errors: logger.warning(u'%s has invalid %s:' % (os.path.split( self.path.rstrip('/'))[1], description_filename)) have_errors = True logger.warning( u" %s value %s" % (u'.'.join([str(x) for x in error.path]), error.message)) # for now schema validation errors aren't fatal... will be soon # though! #if have_errors: # raise InvalidDescription('Invalid %s' % description_filename) self.inherited_shrinkwrap = None self.shrinkwrap = None # we can only apply shrinkwraps to instances with valid descriptions: # instances do not become valid after being invalid so this is safe # (but it means you cannot trust the shrinkwrap of an invalid # component) # (note that it is unsafe to use the __bool__ operator on self here as # we are not fully constructed) if self.description: if inherit_shrinkwrap is not None: # when inheriting a shrinkwrap, check that this module is # listed in the shrinkwrap, otherwise emit a warning: if next((x for x in inherit_shrinkwrap.get('modules', []) if x['name'] == self.getName()), None) is None: logger.warning("%s missing from shrinkwrap", self.getName()) self.inherited_shrinkwrap = inherit_shrinkwrap self.shrinkwrap = tryReadJSON(os.path.join(path, Shrinkwrap_Fname), Shrinkwrap_Schema) if self.shrinkwrap: logger.warning( 'dependencies of %s are pegged by yotta-shrinkwrap.json', self.getName()) if self.inherited_shrinkwrap: logger.warning( 'shrinkwrap in %s overrides inherited shrinkwrap', self.getName()) #logger.info('%s created with inherited_shrinkwrap %s', self.getName(), self.inherited_shrinkwrap) self.vcs = vcs.getVCS(path)
def formatResult(result, plain=False, short=False, indent=''): if not plain: # colorama, BSD 3-Clause license, cross-platform terminal colours, pip install colorama import colorama DIM = colorama.Style.DIM #pylint: disable=no-member BRIGHT = colorama.Style.BRIGHT #pylint: disable=no-member NORMAL = colorama.Style.NORMAL #pylint: disable=no-member GREEN = colorama.Fore.GREEN #pylint: disable=no-member BLUE = colorama.Fore.BLUE #pylint: disable=no-member RED = colorama.Fore.RED #pylint: disable=no-member YELLOW = colorama.Fore.YELLOW #pylint: disable=no-member RESET = colorama.Style.RESET_ALL #pylint: disable=no-member else: DIM = BRIGHT = NORMAL = GREEN = BLUE = RED = YELLOW = RESET = u'' def formatKeyword(keyword): if keyword.endswith('official'): return BRIGHT + GREEN + keyword + RESET else: return BRIGHT + keyword + NORMAL def formatAuthor(author): if isinstance(author, dict): return author.get('name', '<name unknown>') + ' ' + author.get( 'email', '<email unknown') else: return author # --short: # module-name module-version: description description # not --short: # module-name module-version # description description description # keyword, keyword, keyword # author, author v = version.Version(result['version']) if v.major() < 1: if v.minor() < 1: ver_string = RED + result['version'] + RESET else: ver_string = YELLOW + result['version'] + RESET else: ver_string = GREEN + result['version'] + RESET name_string = BRIGHT + result['name'] + NORMAL if 'description' in result: description = result['description'] description_colour = '' else: description = '<description missing>' description_colour = RED if short: description = description_colour + lengthLimit( description, 160).replace('\n', ' ') + RESET else: description = description_colour + lengthLimit( description, 800).replace('\n', indent + ' ').rstrip('\n') + RESET if short: return indent + u'%s %s: %s%s' % (name_string, ver_string, description, RESET) else: r = indent+(u'%s %s:\n' % (name_string, ver_string)) +\ indent+(u' %s\n' % (description)) if 'keywords' in result and result['keywords']: r += indent + ( u' %s\n' % (', '.join([formatKeyword(k) for k in result['keywords']]))) if 'author' in result and result['author']: authors = [result['author']] elif 'maintainers' in result and len(result['maintainers']): authors = result['maintainers'] else: authors = [] if len(authors): r += indent + (u' %s\n' % (DIM + (', '.join([formatAuthor(a) for a in authors])) + RESET)) return r.rstrip('\n')