def test_make_spec(self): t_config = TConfig() t_config.DATA_DIR = os.getcwd() pyu = PyUpdater(t_config) pyu.setup() spec_cmd = [ 'make-spec', 'app.py', '-F', '--app-name', 'MyApp', '--app-version', '0.1.0' ] spec_file_name = get_system() + '.spec' build_cmd = [ 'build', '--app-name', 'MyApp', '--app-version', '0.1.0', spec_file_name ] build_cmd = [str(b) for b in build_cmd] parser = get_parser() with open('app.py', 'w') as f: f.write('print "Hello, World!"') args, pyu_args = parser.parse_known_args(spec_cmd) b = Builder(args, pyu_args) b.make_spec() assert os.path.exists(spec_file_name) args, pyu_args = parser.parse_known_args(build_cmd) b = Builder(args, pyu_args) b.build() with ChDir(new_folder): assert len(os.listdir(os.getcwd())) == 1
def _overwrite_app(self): # Unix: Overwrites the running applications binary, # then starts the updated binary in the currently # running applications process memory. if get_system() == u'mac': if self.current_app_dir.endswith('MacOS') is True: log.debug('Looks like we\'re dealing with a Mac Gui') temp_dir = self._get_mac_dot_app_dir(self.current_app_dir) self.current_app_dir = temp_dir app_update = os.path.join(self.update_folder, self.name) if not os.path.exists(app_update): app_update += u'.app' log.debug(u'Update Location' ':\n{}'.format(os.path.dirname(app_update))) log.debug(u'Update Name: {}'.format(os.path.basename(app_update))) current_app = os.path.join(self.current_app_dir, self.name) if not os.path.exists(current_app): current_app += u'.app' log.debug(u'Current App location:\n\n{}'.format(current_app)) if os.path.exists(current_app): if os.path.isfile(current_app): os.remove(current_app) else: shutil.rmtree(current_app, ignore_errors=True) log.debug(u'Moving app to new location') shutil.move(app_update, os.path.dirname(current_app))
def test_make_spec(self): t_config = TConfig() t_config.DATA_DIR = os.getcwd() pyu = PyUpdater(t_config) pyu.setup() spec_cmd = ['make-spec', 'app.py', '-F', '--app-name', 'MyApp', '--app-version', '0.1.0'] spec_file_name = get_system() + '.spec' build_cmd = ['build', '--app-name', 'MyApp', '--app-version', '0.1.0', spec_file_name] build_cmd = [str(b) for b in build_cmd] parser = get_parser() with open('app.py', 'w') as f: f.write('print "Hello, World!"') args, pyu_args = parser.parse_known_args(spec_cmd) b = Builder(args, pyu_args) b.make_spec() assert os.path.exists(spec_file_name) args, pyu_args = parser.parse_known_args(build_cmd) b = Builder(args, pyu_args) b.build() with ChDir(new_folder): assert len(os.listdir(os.getcwd())) == 1
def test_execution(self, pyu, db): archive_name = 'myapp-{}-0.1.0{}'.format(get_system(), ext) parser = get_parser() data_dir = pyu.config['DATA_DIR'] pyu_data_dir = os.path.join(data_dir, 'pyu-data') pyu.setup() pyu.make_keys(3) with ChDir(data_dir): loader = Loader(db) loader.save_config(pyu.config.copy()) with open('app.py', 'w') as f: f.write('print "Hello World"') args, pyu_args = parser.parse_known_args(create_build_cmd(0)) b = Builder(args, pyu_args) b.build() assert os.path.exists(os.path.join(pyu_data_dir, 'new', archive_name)) pyu.process_packages() assert os.path.exists(os.path.join(pyu_data_dir, 'deploy', archive_name)) assert os.path.exists(os.path.join(pyu_data_dir, 'files', archive_name)) pyu.sign_update() assert os.path.exists(os.path.join(pyu_data_dir, 'deploy', 'versions.gz'))
def test_extract_no_file(self, client): update = client.update_check(client.app_name, '0.0.1') assert update is not None assert update.download() is True with ChDir(update.update_folder): files = os.listdir(os.getcwd()) for f in files: remove_any(f) if get_system() != 'win': assert update.extract() is False
def _archive_installed_binary(self): # Archives current app and places in cache for future patch updates current_archive_filename = self._get_filename(self.name, self.version) current_archvie_path = os.path.join(self.update_folder, current_archive_filename) if not os.path.exists(current_archvie_path): log.debug(u'Adding base binary v{} to updates ' u'folder'.format(self.version)) # Changing in to directory of currently running exe with ChDir(os.path.dirname(sys.argv[0])): name = self.name if get_system() == u'win': name += u'.exe' if get_system() == u'mac': # If not found must be a mac gui app if not os.path.exists(name): name += u'.app' archive_ext = os.path.splitext(current_archive_filename)[1] if u'gz' in archive_ext: archive_format = u'gztar' else: archive_format = u'zip' try: plat = get_system() filename = make_archive(self.name, self.version, name, archive_format, platfrom=plat) except Exception as err: filename = None log.error(str(err), exc_info=True) if filename is not None: shutil.move(filename, self.update_folder)
def test_extract_no_file(self, client): update = client.update_check('jms', '0.0.1') assert update is not None assert update.download() is True with ChDir(update.update_folder): files = os.listdir(os.getcwd()) for f in files: if os.path.isfile(f): os.remove(f) else: shutil.rmtree(f, ignore_errors=True) if get_system() != 'win': assert update.extract() is False
def test_https(self, client): update = client.update_check(client.app_name, '0.0.1') assert update is not None assert update.app_name == 'jms' temp_name = update.name update.name = None assert update.is_downloaded() is False update.name = temp_name assert update.is_downloaded() is False assert update.download() is True assert update.is_downloaded() is True if get_system() != 'win': assert update.extract() is True
def restart(self): """Will overwrite old binary with updated binary and restart using the updated binary. Proxy method for :meth:`_overwrite_app` & :meth:`_restart`. """ if get_system() == u'win': log.debug(u'Only supported on Unix like systems') return try: self._overwrite_app() self._restart() except ClientError as err: log.error(str(err), exc_info=True)
def init_app(self, obj, test=False): """Sets up client with config values from obj Args: obj (instance): config object """ # ToDo: Remove once code is v1.0 # Updated how client is initialized. Can still be # used the old way but the new way is way more efficient # Just pass in the config object and the client takes care # of the rest. No need to initialize NotSoTuf object first! if hasattr(obj, 'config'): config = obj.config.copy() else: config = Config() config.from_object(obj) # Grabbing config information update_url = config.get(u'UPDATE_URL', None) update_urls = config.get(u'UPDATE_URLS', None) self.update_urls = self._sanatize_update_url(update_url, update_urls) self.app_name = config.get(u'APP_NAME', u'PyiUpdater') self.company_name = config.get(u'COMPANY_NAME', u'Digital Sapphire') if test: self.data_dir = 'cache' self.platform = 'mac' else: self.data_dir = user_cache_dir(self.app_name, self.company_name) self.platform = get_system() self.update_folder = os.path.join(self.data_dir, u'update') self.public_key = config.get(u'PUBLIC_KEY', None) self.debug = config.get(u'DEBUG', False) self.verify = config.get(u'VERIFY_SERVER_CERT', True) if self.verify is True: self.http_pool = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', ca_certs=certifi.where()) else: self.http_pool = urllib3.PoolManager() self.version_file = u'version.json' self.current_app_dir = os.path.dirname(sys.argv[0]) self._setup() self.refresh()
def _restart(self): # Oh yes i did just pull that new binary into # the currently running process and kept it pushing # like nobody's business. Windows what??? log.debug(u'Restarting') current_app = os.path.join(self.current_app_dir, self.name) if get_system() == u'mac': if not os.path.exists(current_app): current_app += u'.app' mac_app_binary_dir = os.path.join(current_app, u'Contents', u'MacOS') file_ = os.listdir(mac_app_binary_dir) # We are making an assumption here that only 1 # executable will be in the MacOS folder. current_app = os.path.join(mac_app_binary_dir, file_[0]) log.debug('Mac .app exe path: {}'.format(current_app)) os.execv(current_app, [self.name])
def install_restart(self): """ Will install (unzip) the update, overwrite the current app, then restart the app using the updated binary. On windows Proxy method for :meth:`_extract_update` & :meth:`_win_overwrite_app_restart` On unix Proxy method for :meth:`_extract_update`, :meth:`_overwrite_app` & :meth:`_restart` """ try: self._extract_update() if get_system() == u'win': self._win_overwrite_app_restart() else: self._overwrite_app() self._restart() except ClientError as err: log.error(str(err), exc_info=True)
def test_async_https(self, client): update = client.update_check(client.app_name, '0.0.1') assert update is not None assert update.app_name == 'jms' temp_name = update.name update.name = None assert update.is_downloaded() is False update.name = temp_name assert update.is_downloaded() is False update.download(async=True) count = 0 while count < 61: if update.is_downloaded() is True: break time.sleep(1) count += 1 assert update.is_downloaded() is True if get_system() != 'win': assert update.extract() is True
def test_build_fail_script_syntax_error(self): with pytest.raises(SystemExit): t_config = TConfig() t_config.DATA_DIR = os.getcwd() pyu = PyUpdater(t_config) pyu.setup() spec_cmd = ['make-spec', 'app.py', '-F'] spec_file_name = get_system() + '.spec' build_cmd = ['build', '--app-name', 'MyApp', '--clean' '--app-version', '0.1.0', spec_file_name] parser = get_parser() with open('app.py', 'w') as f: # Missing closing quote f.write('print "Hello, World!') args, pyu_args = parser.parse_known_args(spec_cmd) b = Builder(args, pyu_args) b.make_spec() assert os.path.exists(spec_file_name) args, pyu_args = parser.parse_known_args(build_cmd) b = Builder(args, pyu_args)
def test_build_fail_script_syntax_error(self): with pytest.raises(SystemExit): t_config = TConfig() t_config.DATA_DIR = os.getcwd() pyu = PyUpdater(t_config) pyu.setup() spec_cmd = ['make-spec', 'app.py', '-F'] spec_file_name = get_system() + '.spec' build_cmd = [ 'build', '--app-name', 'MyApp', '--clean' '--app-version', '0.1.0', spec_file_name ] parser = get_parser() with open('app.py', 'w') as f: # Missing closing quote f.write('print "Hello, World!') args, pyu_args = parser.parse_known_args(spec_cmd) b = Builder(args, pyu_args) b.make_spec() assert os.path.exists(spec_file_name) args, pyu_args = parser.parse_known_args(build_cmd) b = Builder(args, pyu_args)
def install(self): """Will extract archived update and leave in update folder. If updating a lib you can take over from there. If updating an app this call should be followed by :meth:`restart` to complete update. Proxy method for :meth:`_extract_update`. Returns: (bool) Meanings:: True - Install successful False - Install failed """ if get_system() == u'win': log.debug('Only supported on Unix like systems') return False try: self._extract_update() except ClientError as err: log.error(str(err), exc_info=True) return False return True
def gen_archive_name(version): archive_name = 'myapp-{}-0.1.{}{}'.format(get_system(), version, ext) return archive_name
def test_archive(self): with open('test2', 'w') as f: f.write('this is a test') ex2 = ExternalLib('test', 'test2', '0.2') ex2.archive() assert os.path.exists('test-{}-0.2{}'.format(get_system(), EXT))
def test_archive(self): with io.open('test', 'w', encoding='utf-8') as f: f.write('this is a test') ex = ExternalLib('test2', 'test', '0.1') ex.archive() assert os.path.exists('test2-{}-0.1{}'.format(get_system(), EXT))
def test_extract(self, client): update = client.update_check(client.app_name, '0.0.1') assert update is not None assert update.download() is True if get_system() != 'win': assert update.extract() is True
from jms_utils.paths import ChDir from jms_utils.system import get_system from pyupdater import PyUpdater from pyupdater.utils.config import Loader, TransistionDict from pyupdater.wrapper.builder import Builder from pyupdater.wrapper.options import get_parser from tconfig import TConfig def create_build_cmd(version): cmd = ['build', '--app-name', 'myapp', '--app-version', '0.1.{}'.format(version), 'app.py', '-F'] return cmd if get_system() == 'win': ext = '.zip' else: ext = '.tar.gz' @pytest.mark.usefixtures('cleandir', 'db', 'pyu') class TestUtils(object): def test_dev_dir_none(self): myconfig = TConfig() myconfig.APP_NAME = None updater = TransistionDict() updater.from_object(myconfig) assert updater['APP_NAME'] == 'PyUpdater App'
from jms_utils.paths import ChDir from jms_utils.system import get_system from pyi_updater.downloader import FileDownloader from pyi_updater.exceptions import PatcherError from pyi_updater.utils import (get_package_hashes, EasyAccessDict, version_string_to_tuple, version_tuple_to_string) if bsdiff4 is None: from pyi_updater.utils import bsdiff4_py as bsdiff4 log = logging.getLogger(__name__) platform_ = get_system() progress_signal = signal(u'progress_info') class Patcher(object): """Downloads, verifies, and patches binaries Args: name (str): Name of binary to patch json_data (dict): Info dict with all package meta data current_version (str): Version number of currently installed binary highest_version (str): Newest version available
def test_archive(self): with io.open('test2', 'w', encoding='utf-8') as f: f.write('this is a test') ex2 = ExternalLib('test', 'test2', '0.2') ex2.archive() assert os.path.exists('test-{}-0.2{}'.format(get_system(), EXT))
from jms_utils.system import get_system from pyi_updater.downloader import FileDownloader from pyi_updater.exceptions import PatcherError from pyi_updater.utils import (get_package_hashes, EasyAccessDict, version_string_to_tuple, version_tuple_to_string) if bsdiff4 is None: from pyi_updater.utils import bsdiff4_py as bsdiff4 log = logging.getLogger(__name__) platform_ = get_system() progress_signal = signal(u'progress_info') class Patcher(object): """Downloads, verifies, and patches binaries Args: name (str): Name of binary to patch json_data (dict): Info dict with all package meta data current_version (str): Version number of currently installed binary highest_version (str): Newest version available