def get_icons(url="https://openbases.github.io/openbases-icons/icons.json", regexp=None, N=1): '''get a number of icons from the openbases-icons repository, and return a list. Parameters ========== url: the openbases-icons json list (or other) of icons to choose from regexp: a regular expression to filter by (default None, no filter) N: the number of icons to return (default is 1) Returns ======= icons: a list of filtered (or not) icons ''' try: icons = requests.get(url).json() except: bot.error("Error parsing json at %s" % url) # Does the user want to filter? if regexp is not None: icons = [i for i in icons if re.search(regexp, i)] # The number of results to return random.shuffle(icons) # A search might not have results if len(icons) >= N: icons = icons[0:0 + N] return icons
def test_authors(spec, **kwargs): '''the paper header should have a list of authors, each with affiliation, name, and orcid. authors: - name: Submission must include a list of authors, well formatted - level: error - function: openbases.main.papers.tests.test_authors ''' header = spec.loaded if "authors" not in header: bot.exit('authors missing in front end paper matter.') if not isinstance(header['authors'], list): bot.exit('authors in front end paper matter should be a list') # Regular expression for orcid regexp = "[0-9]{4}-[0-9]{4}-[0-9]{4}-[0-9]{4}" # key type has_regexp regexp required_fields = ('affiliation', 'orcid', 'name') for field in required_fields: for author in header['authors']: if field not in author: bot.exit('Paper is missing a required author field %s' % field) print(author) if field == 'orcid': if not re.search(regexp, author[field]): bot.error('Orcid regular expression failed %s' % author[field]) print(author) return True
def check_install(software=None, quiet=True): '''check_install will attempt to run some command, and return True if installed. The command line utils will not run without this check. ''' if software == None: bot.error("Please enter the name of the software!") cmd = [software, '--version'] found = False try: version = run_command(cmd, quiet=True) except: # FileNotFoundError return found if version is not None: if version['return_code'] == 0: found = True if quiet is False: version = version['message'] bot.info("Found %s version %s" % (software.upper(), version)) return found
def read_bibtex(filename, mode='r'): '''read a yaml file, only including sections between dashes ''' from pybtex.database.input import bibtex parser = bibtex.Parser() try: data = parser.parse_file(filename) return data.entries except Exception as e: bot.error(e)
def mkdir_p(path): '''mkdir_p attempts to get the same functionality as mkdir -p :param path: the path to create. ''' try: os.makedirs(path) except OSError as e: if e.errno == errno.EEXIST and os.path.isdir(path): pass else: bot.error("Error creating path %s, exiting." % path) sys.exit(1)
def copy_directory(src, dest, force=False): ''' Copy an entire directory recursively ''' if os.path.exists(dest) and force is True: shutil.rmtree(dest) try: shutil.copytree(src, dest) except OSError as e: # If the error was caused because the source wasn't a directory if e.errno == errno.ENOTDIR: shutil.copy(src, dest) else: bot.error('Directory not copied. Error: %s' % e) sys.exit(1)
def getenv(variable_key, default=None, required=False, silent=True): '''getenv will attempt to get an environment variable. If the variable is not found, None is returned. :param variable_key: the variable name :param required: exit with error if not found :param silent: Do not print debugging information for variable ''' variable = os.environ.get(variable_key, default) if variable is None and required: bot.error("Cannot find environment variable %s, exiting." %variable_key) sys.exit(1) if not silent: if variable is not None: bot.verbose2("%s found as %s" %(variable_key,variable)) else: bot.verbose2("%s not defined (None)" %variable_key) return variable
def main(args, options): if len(args.names) < 2: bot.error('Must provide a label and name, e.g., experiment labjs') badge = Badge(label=args.names[0], name=args.names[1], longCache=args.longCache, link=args.link, style=args.style) # If the user provided a custom color, change it. if args.color is not None: badge.set_color(args.color) # Return the desired format to the user if args.format == "svg": print(badge.get_svg()) else: print(badge.get_markdown())
def run_command(self, cmd, sudo=False, capture=True): '''run_command is a wrapper for the global run_command, checking first for sudo and exiting on error if needed. The message is returned as a list of lines for the calling function to parse, and stdout uses the parent process so it appears for the user. Parameters ========== cmd: the command to run sudo: does the command require sudo? On success, returns result. Otherwise, exists on error ''' result = run_cmd(cmd, sudo=sudo, capture=capture, quiet=self.quiet) message = result['message'] return_code = result['return_code'] if result['return_code'] == 0: if len(message) == 1: message = message[0] return message if self.quiet is False: bot.error("Return Code %s: %s" % (return_code, message))
def test_references(spec, envar="OPENBASESENV_BIBFILE", **kwargs): '''required_structure looks for a schema's required fields, and issues an exit if doesn't exist. To implement this in a criteria.yml: references: - name: References are included and complete - level: warning - function: openbases.main.papers.tests.test_references Templates taken from https://github.com/licenses/license-templates ''' from openbases.utils import read_bibtex complete = True bibfile = os.environ.get(envar) # We must have a bibfile if not "bibfile" and "bibfile" not in kwargs: bot.warning('Bibfile not provided as argument, skipping test') return complete required_fields = ['title', 'month', 'year'] bib = read_bibtex(bibfile) for entryid, entry in bib.items(): bot.info('Testing bibliography entry %s' % entryid) bot.info(' type: %s' % entry.type) for field in entry.fields: if field not in entry.fields: bot.error(' %s is missing field %s' % (entryid, field)) complete = False if entry.fields[field] in [None, '']: bot.error(' %s has empty field %s' % (entryid, field)) complete = False bot.info(' title: %s' % entry.fields['title']) return complete
def test_license(spec, envar='OPENBASESENV_REPO_BASE', **kwargs): '''required_structure looks for a schema's required fields, and issues an exit if doesn't exist. To implement this in a criteria.yml: license: - name: An OSI license is included in the repository - level: error - function: openbases.main.papers.tests.test_license - environment: - OPENBASESENV_REPO_BASE: null Templates taken from https://github.com/licenses/license-templates ''' # By default, not found. found = False # A list of terms to indicate open source licenses LICENSE_FLAGS = [ "GNU Affero General Public License", "MIT License", "Apache", "Creative Commons", "CC0", # Creative Commans 1.0 "CC1", "General Public License", "The GNU General Public License", "GPL-2.0", "Free Software Foundation", "GNU LESSER GENERAL PUBLIC", "GPL-3.0", "Mozilla Public License", "free and unencumbered software released into the public", "www.gnu.org", "This program is free software", "www.wtfpl.net", "COMMON DEVELOPMENT AND DISTRIBUTION", # CCDL '"AS IS"', # bsd 22 'as-is' ] # zlib repo_base = os.environ.get(envar) if repo_base is not None: if os.path.exists(repo_base): licenses = find_files(repo_base, 'LICENSE') for license in licenses: content = read_file(license, readlines=False) matches = [ x for x in LICENSE_FLAGS if re.search(x.lower(), content.lower()) ] if len(matches) > 0: message = 'Found Open Source license flags! %s' bot.info(message % ','.join(matches)) print(content) found = True else: bot.error('%s does not exist! Skipping test.' % repo_base) else: bot.error('''Did not find %s export for repository base! Skipping license check''' % envar) return found
def validate_criteria(self, criteria=None, infile=None, params=None): '''validate an infile (or already loaded one) against criteria. Parameters ========== infile: an input specification file criteria: a loaded (json/dict) or criteria, or html/yml file ''' from openbases.utils import load_module # If criteria not set, use default if criteria is None: self.load_criteria() # Update environment with params for validation if params is not None: bot.info('Updating custom params with %s' % params) self.params.update(params) # Update the environment update_environment(params=self.params, prefix='OPENBASESENV_') # Read in the criteria - any errors will fall back to default if not isinstance(criteria, dict): criteria = self.load_criteria(criteria) # Case 1: input file provided at runtime if infile is not None: self.load(infile) # Case 2: Didn't successfully load, fall back to previously loaded if not hasattr(self, 'spec'): # infile didn't load successfully if hasattr(self, 'infile'): self.load(infile) # Case 3: Still no infile! Exit if not hasattr(self, 'spec'): bot.error('Please provide an infile to function, or load()') if "checks" not in criteria: bot.error('criteria is missing "checks" section, exiting.') # Default missing function missing_function = 'openbases.main.validate.criteria.base.missing' # Turn status into meaningful message for user lookup = {True: 'pass', False: 'fail', None: 'null'} # Loop through checks, run against specification file for group, checks in criteria['checks'].items(): print('[group|start:%s]' % group) values = dict() [values.update(dict(check)) for check in checks] # Obtain values, the only required is the function name = values.get('name', self.robot.generate()) level = values.get('level', 'warning').upper() function = values.get('function', missing_function) kwargs = values.get('kwargs') envars_list = values.get('environment') envars = dict() # If we have environment vars from criteria, export them if envars_list is not None: [update_environment(e) for e in envars_list] # If we have a function provided in the configuration yaml function_name = function function = load_module(function) if kwargs is None: valid = function(self.spec) else: values = dict() [values.update(dict(kwarg)) for kwarg in kwargs] valid = function(self.spec, **values) print('[check:%s]' % name) print(' test:function %s' % function_name) print(' test:result %s' % lookup[valid]) if valid: bot.test("PASSED %s" % function_name) else: print(' test:level %s' % level) bot.named(level, function_name) if not valid: sys.exit(1) print('[group|end:%s]' % group) print('ALL TESTS PASSING')
def set_color(self, color): if color in BADGE_COLORS: self.color = color self._update_design() else: bot.error("Color 404! Run ob-badge view colors.")