Hello community, here is the log from the commit of package python-msm for openSUSE:Factory checked in at 2019-02-04 14:25:00 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-msm (Old) and /work/SRC/openSUSE:Factory/.python-msm.new.28833 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-msm" Mon Feb 4 14:25:00 2019 rev:6 rq:670889 version:0.6.3 Changes: -------- --- /work/SRC/openSUSE:Factory/python-msm/python-msm.changes 2018-11-06 14:31:44.305263738 +0100 +++ /work/SRC/openSUSE:Factory/.python-msm.new.28833/python-msm.changes 2019-02-04 14:25:03.221063950 +0100 @@ -1,0 +2,29 @@ +Sat Feb 2 22:41:00 UTC 2019 - [email protected] + +- Update to python-msm 0.6.3 + * Do not destroy the existing repo on git errors + +- Update to python-msm 0.6.2 + * Convert booleans in installed field to 0 + +- Update to python-msm 0.6.1 + * Make sure saving_handled is reset + * Handle writing automatically + +- Update to python-msm 0.6.0 + * Use existing installation/update times + * Only write skills data if the info has changed + * Fix update_deps() issue with constraints + * Fix handling of beta and cleanup + * Add process lock using fasteners + * Add handling of the skills.json file + * Updates returns True if an update occured + * Try to handle errors in the .skills-repo + * Add option to use pip constraints + +- Rebase patches: + * add-local-patch-support.patch + * do-not-run-pip-or-requirements-script.patch + * fix-skills-directories.patch + +------------------------------------------------------------------- Old: ---- msm-0.5.19.tar.gz New: ---- msm-0.6.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-msm.spec ++++++ --- /var/tmp/diff_new_pack.ovvQ57/_old 2019-02-04 14:25:03.785063683 +0100 +++ /var/tmp/diff_new_pack.ovvQ57/_new 2019-02-04 14:25:03.789063681 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-msm # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %define skip_python2 1 %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-msm -Version: 0.5.19 +Version: 0.6.3 Release: 0 Summary: Mycroft Skills Manager License: Apache-2.0 @@ -60,6 +60,7 @@ %files %{python_files} %license LICENSE %python3_only %{_bindir}/msm -%{python_sitelib}/* +%{python_sitelib}/msm +%{python_sitelib}/msm-%{version}-py%{python_version}.egg-info %changelog ++++++ add-local-patch-support.patch ++++++ --- /var/tmp/diff_new_pack.ovvQ57/_old 2019-02-04 14:25:03.813063670 +0100 +++ /var/tmp/diff_new_pack.ovvQ57/_new 2019-02-04 14:25:03.817063668 +0100 @@ -11,13 +11,13 @@ LOG = logging.getLogger(__name__) -@@ -242,6 +244,7 @@ class SkillEntry(object): +@@ -256,6 +258,7 @@ class SkillEntry(object): try: move(tmp_location, self.path) + apply_skill_patch(self.name, self.path) self.run_requirements_sh() - self.run_pip() + self.run_pip(constraints) finally: @@ -274,6 +277,7 @@ class SkillEntry(object): with git_to_msm_exceptions(): ++++++ do-not-run-pip-or-requirements-script.patch ++++++ --- /var/tmp/diff_new_pack.ovvQ57/_old 2019-02-04 14:25:03.825063664 +0100 +++ /var/tmp/diff_new_pack.ovvQ57/_new 2019-02-04 14:25:03.825063664 +0100 @@ -9,8 +9,8 @@ + LOG.info("Please check manually the requirements file at " + requirements_file) + return False - LOG.info('Installing requirements.txt for ' + self.name) - can_pip = os.access(dirname(sys.executable), os.W_OK | os.X_OK) + # Use constraints to limit the installed versions + if constraints and not exists(constraints): @@ -184,6 +186,8 @@ class SkillEntry(object): setup_script = join(self.path, "requirements.sh") if not exists(setup_script): ++++++ fix-skills-directories.patch ++++++ --- /var/tmp/diff_new_pack.ovvQ57/_old 2019-02-04 14:25:03.833063660 +0100 +++ /var/tmp/diff_new_pack.ovvQ57/_new 2019-02-04 14:25:03.833063660 +0100 @@ -69,14 +69,15 @@ =================================================================== --- msm-0.5.17.orig/msm/mycroft_skills_manager.py +++ msm-0.5.17/msm/mycroft_skills_manager.py -@@ -31,13 +31,14 @@ from msm import GitException - from msm.exceptions import MsmException, SkillNotFound, MultipleSkillMatches - from msm.skill_entry import SkillEntry - from msm.skill_repo import SkillRepo -+from msm.configuration import get_skills_directory - - LOG = logging.getLogger(__name__) +@@ -30,6 +30,7 @@ from msm import GitException + from typing import Dict, List + from msm import GitException ++from msm.configuration import get_skills_directory + from msm.exceptions import (MsmException, SkillNotFound, MultipleSkillMatches, + AlreadyInstalled) + from msm.skill_entry import SkillEntry +@@ -68,7 +69,7 @@ from msm import GitException class MycroftSkillsManager(object): SKILL_GROUPS = {'default', 'mycroft_mark_1', 'picroft', 'kde'} ++++++ msm-0.5.19.tar.gz -> msm-0.6.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msm-0.5.19/PKG-INFO new/msm-0.6.3/PKG-INFO --- old/msm-0.5.19/PKG-INFO 2018-08-28 13:37:00.000000000 +0200 +++ new/msm-0.6.3/PKG-INFO 2018-12-07 00:25:44.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: msm -Version: 0.5.19 +Version: 0.6.3 Summary: Mycroft Skills Manager Home-page: https://github.com/MycroftAI/mycroft-skills-manager Author: jarbasAI, Matthew Scholefield diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msm-0.5.19/msm/__main__.py new/msm-0.6.3/msm/__main__.py --- old/msm-0.5.19/msm/__main__.py 2018-08-28 13:22:08.000000000 +0200 +++ new/msm-0.6.3/msm/__main__.py 2018-12-07 00:25:28.000000000 +0100 @@ -63,6 +63,11 @@ subparsers = parser.add_subparsers(dest='action') subparsers.required = True + def add_constraint_args(subparser): + subparser.add_argument('--constraints', + help='limit the installed requirements using ' + 'a pip constraint.txt file.') + def add_search_args(subparser, skill_is_optional=False): if skill_is_optional: subparser.add_argument('skill', nargs='?') @@ -70,7 +75,9 @@ subparser.add_argument('skill') subparser.add_argument('author', nargs='?') - add_search_args(subparsers.add_parser('install')) + install_parser = subparsers.add_parser('install') + add_search_args(install_parser) + add_constraint_args(install_parser) add_search_args(subparsers.add_parser('remove')) add_search_args(subparsers.add_parser('search')) add_search_args(subparsers.add_parser('info')) @@ -90,7 +97,8 @@ args.platform, args.skills_dir, repo, args.versioned ) main_functions = { - 'install': lambda: msm.install(args.skill, args.author), + 'install': lambda: msm.install(args.skill, args.author, + args.constraints, 'cli'), 'remove': lambda: msm.remove(args.skill, args.author), 'list': lambda: '\n'.join( skill.name + ( @@ -108,18 +116,18 @@ ), 'info': lambda: skill_info(msm.find_skill(args.skill, args.author)) } - try: - result = main_functions[args.action]() - if result is False: - return 1 - if isinstance(result, str): - printer(result) - return 0 - except MsmException as e: - exc_type = e.__class__.__name__ - printer('{}: {}'.format(exc_type, str(e))) - return get_error_code(e.__class__) - + with msm.lock: + try: + result = main_functions[args.action]() + if result is False: + return 1 + if isinstance(result, str): + printer(result) + return 0 + except MsmException as e: + exc_type = e.__class__.__name__ + printer('{}: {}'.format(exc_type, str(e))) + return get_error_code(e.__class__) if __name__ == "__main__": main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msm-0.5.19/msm/mycroft_skills_manager.py new/msm-0.6.3/msm/mycroft_skills_manager.py --- old/msm-0.5.19/msm/mycroft_skills_manager.py 2018-08-28 13:22:08.000000000 +0200 +++ new/msm-0.6.3/msm/mycroft_skills_manager.py 2018-12-07 00:25:28.000000000 +0100 @@ -24,16 +24,47 @@ from itertools import chain from multiprocessing.pool import ThreadPool from os.path import expanduser, join, dirname, isdir +from functools import wraps +import time from typing import Dict, List from msm import GitException -from msm.exceptions import MsmException, SkillNotFound, MultipleSkillMatches +from msm.exceptions import (MsmException, SkillNotFound, MultipleSkillMatches, + AlreadyInstalled) from msm.skill_entry import SkillEntry from msm.skill_repo import SkillRepo +from msm.skills_data import (build_skill_entry, get_skill_entry, + write_skills_data, load_skills_data, + skills_data_hash) + +from msm.util import MsmProcessLock LOG = logging.getLogger(__name__) +CURRENT_SKILLS_DATA_VERSION = 1 + + +def save_skills_data(func): + @wraps(func) + def func_wrapper(self, *args, **kwargs): + will_save = False + if not self.saving_handled: + will_save = self.saving_handled = True + try: + ret = func(self, *args, **kwargs) + # Write only if no exception occurs + if will_save: + self.write_skills_data() + finally: + # Always restore saving_handled flag + if will_save: + self.saving_handled = False + + return ret + + return func_wrapper + class MycroftSkillsManager(object): SKILL_GROUPS = {'default', 'mycroft_mark_1', 'picroft', 'kde'} @@ -46,30 +77,165 @@ or self.DEFAULT_SKILLS_DIR self.repo = repo or SkillRepo() self.versioned = versioned + self.lock = MsmProcessLock() + + self.skills_data = None + self.saving_handled = False + with self.lock: + self.sync_skills_data() + + def __upgrade_skills_data(self, skills_data): + new = {} + if skills_data.get('version', 0) == 0: + new['blacklist'] = [] + new['version'] = 1 + new['skills'] = [] + local_skills = [s for s in self.list() if s.is_local] + default_skills = [s.name for s in self.list_defaults()] + for skill in local_skills: + if 'origin' in skills_data.get(skill.name, {}): + origin = skills_data[skill.name]['origin'] + elif skill.name in default_skills: + origin = 'default' + elif skill.url: + origin = 'cli' + else: + origin = 'non-msm' + beta = skills_data.get(skill.name, {}).get('beta', False) + entry = build_skill_entry(skill.name, origin, beta) + entry['installed'] = \ + skills_data.get(skill.name, {}).get('installed') or 0 + if isinstance(entry['installed'], bool): + entry['installed'] = 0 + + entry['update'] = \ + skills_data.get(skill.name, {}).get('updated') or 0 + + new['skills'].append(entry) + new['upgraded'] = True + return new + + def curate_skills_data(self, skills_data): + """ Sync skills_data with actual skills on disk. """ + local_skills = [s for s in self.list() if s.is_local] + default_skills = [s.name for s in self.list_defaults()] + local_skill_names = [s.name for s in local_skills] + skills_data_skills = [s['name'] for s in skills_data['skills']] + + # Check for skills that aren't in the list + for skill in local_skills: + if skill.name not in skills_data_skills: + if skill.name in default_skills: + origin = 'default' + elif skill.url: + origin = 'cli' + else: + origin = 'non-msm' + entry = build_skill_entry(skill.name, origin, False) + skills_data['skills'].append(entry) + + # Check for skills in the list that doesn't exist in the filesystem + remove_list = [] + for s in skills_data.get('skills', []): + if (s['name'] not in local_skill_names and + s['installation'] == 'installed'): + remove_list.append(s) + for skill in remove_list: + skills_data['skills'].remove(skill) + return skills_data + + def load_skills_data(self) -> dict: + skills_data = load_skills_data() + if skills_data.get('version', 0) < CURRENT_SKILLS_DATA_VERSION: + skills_data = self.__upgrade_skills_data(skills_data) + else: + skills_data = self.curate_skills_data(skills_data) + return skills_data + + def sync_skills_data(self): + """ Update internal skill_data_structure from disk. """ + self.skills_data = self.load_skills_data() + if 'upgraded' in self.skills_data: + self.skills_data.pop('upgraded') + self.skills_data_hash = '' + else: + self.skills_data_hash = skills_data_hash(self.skills_data) + + def write_skills_data(self, data=None): + """ Write skills data hash if it has been modified. """ + data = data or self.skills_data + if skills_data_hash(data) != self.skills_data_hash: + write_skills_data(data) - def install(self, param, author=None): + @save_skills_data + def install(self, param, author=None, constraints=None, origin=''): """Install by url or name""" - self.find_skill(param, author).install() + if isinstance(param, SkillEntry): + skill = param + else: + skill = self.find_skill(param, author) + entry = build_skill_entry(skill.name, origin, skill.is_beta) + try: + skill.install(constraints) + entry['installed'] = time.time() + entry['installation'] = 'installed' + entry['status'] = 'active' + except AlreadyInstalled: + entry = None + raise + except MsmException as e: + entry['installation'] = 'failed' + entry['status'] = 'error' + entry['failure_message'] = repr(e) + raise + finally: + # Store the entry in the list + if entry: + self.skills_data['skills'].append(entry) + @save_skills_data def remove(self, param, author=None): """Remove by url or name""" - self.find_skill(param, author).remove() + if isinstance(param, SkillEntry): + skill = param + else: + skill = self.find_skill(param, author) + skill.remove() + skills = [s for s in self.skills_data['skills'] + if s['name'] != skill.name] + self.skills_data['skills'] = skills + return def update_all(self): local_skills = [skill for skill in self.list() if skill.is_local] def update_skill(skill): - skill.update() + entry = get_skill_entry(skill.name, self.skills_data) + if entry: + entry['beta'] = skill.is_beta + if skill.update(): + if entry: + entry['updated'] = time.time() return self.apply(update_skill, local_skills) + @save_skills_data def update(self, skill=None, author=None): """Update all downloaded skills or one specified skill.""" if skill is None: return self.update_all() else: - return self.find_skill(skill, author).update() + if isinstance(skill, str): + skill = self.find_skill(skill, author) + entry = get_skill_entry(skill.name, self.skills_data) + if entry: + entry['beta'] = skill.is_beta + if skill.update(): + # On successful update update the update value + if entry: + entry['updated'] = time.time() + @save_skills_data def apply(self, func, skills): """Run a function on all skills in parallel""" @@ -88,16 +254,16 @@ )) with ThreadPool(100) as tp: - return all(tp.map(run_item, skills)) + return (tp.map(run_item, skills)) + @save_skills_data def install_defaults(self): """Installs the default skills, updates all others""" - def install_or_update_skill(skill): if skill.is_local: - skill.update() + self.update(skill) else: - skill.install() + self.install(skill, origin='default') return self.apply(install_or_update_skill, self.list_defaults()) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msm-0.5.19/msm/skill_entry.py new/msm-0.6.3/msm/skill_entry.py --- old/msm-0.5.19/msm/skill_entry.py 2018-08-28 13:22:08.000000000 +0200 +++ new/msm-0.6.3/msm/skill_entry.py 2018-11-14 14:28:24.000000000 +0100 @@ -46,6 +46,8 @@ # TODO Make this configurable SWITCHABLE_BRANCHES = ['master'] +# default constraints to use if no are given +DEFAULT_CONSTRAINTS = '/etc/mycroft/constraints.txt' @contextmanager def work_dir(directory): @@ -71,6 +73,13 @@ self.id = self.extract_repo_id(url) if url else name self.is_local = exists(path) + @property + def is_beta(self): + return not self.sha or self.sha == 'HEAD' + + def __str__(self): + return self.name + def attach(self, remote_entry): """Attach a remote entry to a local entry""" self.name = remote_entry.name @@ -150,16 +159,25 @@ sum(weight for weight, val in weights) ) - def run_pip(self): + def run_pip(self, constraints): requirements_file = join(self.path, "requirements.txt") if not exists(requirements_file): return False + # Use constraints to limit the installed versions + if constraints and not exists(constraints): + LOG.error('Couldn\'t find the constraints file') + return False + elif exists(DEFAULT_CONSTRAINTS): + constraints = DEFAULT_CONSTRAINTS + LOG.info('Installing requirements.txt for ' + self.name) can_pip = os.access(dirname(sys.executable), os.W_OK | os.X_OK) pip_args = [ sys.executable, '-m', 'pip', 'install', '-r', requirements_file ] + if constraints: + pip_args += ['-c', constraints] if not can_pip: pip_args = ['sudo', '-n'] + pip_args @@ -215,7 +233,7 @@ with open(reqs, "r") as f: return [i.strip() for i in f.readlines() if i.strip()] - def install(self): + def install(self, constraints=None): if self.is_local: raise AlreadyInstalled(self.name) @@ -239,7 +257,7 @@ move(tmp_location, self.path) self.run_requirements_sh() - self.run_pip() + self.run_pip(constraints) finally: if isfile(join(self.path, '__init__')): move(join(self.path, '__init__'), @@ -247,11 +265,11 @@ LOG.info('Successfully installed ' + self.name) - def update_deps(self): + def update_deps(self, constraints=None): if self.msm: self.run_skill_requirements() self.run_requirements_sh() - self.run_pip() + self.run_pip(constraints) def _find_sha_branch(self): git = Git(self.path) @@ -291,8 +309,10 @@ LOG.info('Updated ' + self.name) # Trigger reload by modifying the timestamp os.utime(join(self.path, '__init__.py')) + return True else: LOG.info('Nothing new for ' + self.name) + return False def remove(self): if not self.is_local: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msm-0.5.19/msm/skill_repo.py new/msm-0.6.3/msm/skill_repo.py --- old/msm-0.5.19/msm/skill_repo.py 2018-08-28 13:22:08.000000000 +0200 +++ new/msm-0.6.3/msm/skill_repo.py 2018-12-07 00:25:28.000000000 +0100 @@ -24,7 +24,7 @@ from os.path import exists, join, isdir, dirname, basename from git import Repo -from git.exc import GitCommandError +from git.exc import GitCommandError, GitError from msm import git_to_msm_exceptions from msm.exceptions import MsmException @@ -45,17 +45,16 @@ with open(join(self.path, filename)) as f: return f.read() - def update(self): + def __prepare_repo(self): if not exists(dirname(self.path)): makedirs(dirname(self.path)) - with git_to_msm_exceptions(): - if not isdir(self.path): - Repo.clone_from(self.url, self.path) - - git = Git(self.path) - git.config('remote.origin.url', self.url) - git.fetch() + if not isdir(self.path): + Repo.clone_from(self.url, self.path) + + git = Git(self.path) + git.config('remote.origin.url', self.url) + git.fetch() try: git.checkout(self.branch) @@ -63,6 +62,24 @@ except GitCommandError: raise MsmException('Invalid branch: ' + self.branch) + def update(self): + try: + self.__prepare_repo() + except GitError as e: + LOG.warning('Could not prepare repo ({}), ' + ' Creating temporary repo'.format(repr(e))) + original_path = self.path + self.path = '/tmp/.skills-repo' + try: + with git_to_msm_exceptions(): + self.__prepare_repo() + except Exception: + LOG.warning('Could not use temporary repo either ({}), ' + ' trying to use existing one without ' + 'update'.format(repr(e))) + self.path = original_path # Restore path to previous value + raise + def get_skill_data(self): """ generates tuples of name, path, url, sha """ path_to_sha = { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msm-0.5.19/msm/skills_data.py new/msm-0.6.3/msm/skills_data.py --- old/msm-0.5.19/msm/skills_data.py 1970-01-01 01:00:00.000000000 +0100 +++ new/msm-0.6.3/msm/skills_data.py 2018-11-14 14:28:24.000000000 +0100 @@ -0,0 +1,55 @@ +""" + Functions related to manipulating the skills_data.json +""" + +from os.path import expanduser, isfile +import json + +def load_skills_data() -> dict: + """Contains info on how skills should be updated""" + skills_data_file = expanduser('~/.mycroft/skills.json') + if isfile(skills_data_file): + try: + with open(skills_data_file) as f: + return json.load(f) + except json.JSONDecodeError: + return {} + else: + return {} + +def write_skills_data(data: dict): + skills_data_file = expanduser('~/.mycroft/skills.json') + with open(skills_data_file, 'w') as f: + json.dump(data, f, indent=4, separators=(',',':')) + +def get_skill_entry(name, skills_data) -> dict: + """ Find a skill entry in the skills_data and returns it. """ + for e in skills_data.get('skills', []): + if e.get('name') == name: + return e + return None + + +def build_skill_entry(name, origin, beta) -> dict: + """ Create a new skill entry + + Arguments: + name: skill name + origin: the source of the installation + beta: Boolean indicating wether the skill is in beta + Returns: + populated skills entry + """ + entry = {} + entry['name'] = name + entry['origin'] = origin + entry['beta'] = beta + entry['status'] = 'active' + entry['installed'] = 0 + entry['updated'] = 0 + entry['installation'] = 'installed' + return entry + + +def skills_data_hash(data): + return hash(json.dumps(data, sort_keys=True)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msm-0.5.19/msm/util.py new/msm-0.6.3/msm/util.py --- old/msm-0.5.19/msm/util.py 2018-08-28 13:22:08.000000000 +0200 +++ new/msm-0.6.3/msm/util.py 2018-11-14 14:28:24.000000000 +0100 @@ -20,7 +20,9 @@ # specific language governing permissions and limitations # under the License. import git - +from os.path import exists +from os import chmod +from fasteners.process_lock import InterProcessLock class Git(git.cmd.Git): """Prevents asking for password for private repos""" @@ -32,3 +34,13 @@ env.update(self.env) return super(Git, self).__getattr__(item)(*args, env=env, **kwargs) return wrapper + + +class MsmProcessLock(InterProcessLock): + def __init__(self): + lock_path = '/tmp/msm_lock' + if not exists(lock_path): + lock_file = open(lock_path, '+w') + lock_file.close() + chmod(lock_path, 0o777) + super().__init__(lock_path) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msm-0.5.19/msm.egg-info/PKG-INFO new/msm-0.6.3/msm.egg-info/PKG-INFO --- old/msm-0.5.19/msm.egg-info/PKG-INFO 2018-08-28 13:37:00.000000000 +0200 +++ new/msm-0.6.3/msm.egg-info/PKG-INFO 2018-12-07 00:25:44.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: msm -Version: 0.5.19 +Version: 0.6.3 Summary: Mycroft Skills Manager Home-page: https://github.com/MycroftAI/mycroft-skills-manager Author: jarbasAI, Matthew Scholefield diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msm-0.5.19/msm.egg-info/SOURCES.txt new/msm-0.6.3/msm.egg-info/SOURCES.txt --- old/msm-0.5.19/msm.egg-info/SOURCES.txt 2018-08-28 13:37:00.000000000 +0200 +++ new/msm-0.6.3/msm.egg-info/SOURCES.txt 2018-12-07 00:25:44.000000000 +0100 @@ -6,6 +6,7 @@ msm/mycroft_skills_manager.py msm/skill_entry.py msm/skill_repo.py +msm/skills_data.py msm/util.py msm.egg-info/PKG-INFO msm.egg-info/SOURCES.txt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msm-0.5.19/msm.egg-info/requires.txt new/msm-0.6.3/msm.egg-info/requires.txt --- old/msm-0.5.19/msm.egg-info/requires.txt 2018-08-28 13:37:00.000000000 +0200 +++ new/msm-0.6.3/msm.egg-info/requires.txt 2018-12-07 00:25:44.000000000 +0100 @@ -1,2 +1,3 @@ GitPython typing +fasteners diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/msm-0.5.19/setup.py new/msm-0.6.3/setup.py --- old/msm-0.5.19/setup.py 2018-08-28 13:22:08.000000000 +0200 +++ new/msm-0.6.3/setup.py 2018-12-07 00:25:28.000000000 +0100 @@ -23,9 +23,9 @@ setup( name='msm', - version='0.5.19', + version='0.6.3', packages=['msm'], - install_requires=['GitPython', 'typing'], + install_requires=['GitPython', 'typing', 'fasteners'], url='https://github.com/MycroftAI/mycroft-skills-manager', license='Apache-2.0', author='jarbasAI, Matthew Scholefield',
