def test_esky_locking(self): """Test that locking an Esky works correctly.""" platform = get_platform() appdir = tempfile.mkdtemp() try: vdir = os.path.join(appdir, ESKY_APPDATA_DIR, "testapp-0.1.%s" % (platform,)) os.makedirs(vdir) os.mkdir(os.path.join(vdir, ESKY_CONTROL_DIR)) open(os.path.join(vdir, ESKY_CONTROL_DIR, "bootstrap-manifest.txt"), "wb").close() e1 = esky.Esky(appdir, "http://example.com/downloads/") assert e1.name == "testapp" assert e1.version == "0.1" assert e1.platform == platform e2 = esky.Esky(appdir, "http://example.com/downloads/") assert e2.name == "testapp" assert e2.version == "0.1" assert e2.platform == platform locked = [] errors = [] trigger1 = threading.Event() trigger2 = threading.Event() def runit(e, t1, t2): def runme(): try: e.lock() except Exception, err: errors.append(err) else: locked.append(e)
def run(self): fullname = self.distribution.get_fullname() platform = get_platform() vdir = "%s.%s" % (fullname,platform,) appname = split_app_version(vdir)[0] # Ensure we have current version's esky, as target for patch. target_esky = os.path.join(self.dist_dir,vdir+".zip") if not os.path.exists(target_esky): self.run_command("bdist_esky") # Generate list of source eskys to patch against. if self.from_version: source_vdir = join_app_version(appname,self.from_version,platform) source_eskys = [os.path.join(self.dist_dir,source_vdir+".zip")] else: source_eskys = [] for nm in os.listdir(self.dist_dir): if target_esky.endswith(nm): continue if nm.startswith(appname+"-") and nm.endswith(platform+".zip"): source_eskys.append(os.path.join(self.dist_dir,nm)) # Write each patch, transparently unzipping the esky for source_esky in source_eskys: target_vdir = os.path.basename(source_esky)[:-4] target_version = split_app_version(target_vdir)[1] patchfile = vdir+".from-%s.patch" % (target_version,) patchfile = os.path.join(self.dist_dir,patchfile) print "patching", target_esky, "against", source_esky, "=>", patchfile if not self.dry_run: try: esky.patch.main(["-Z","diff",source_esky,target_esky,patchfile]) except: import traceback traceback.print_exc() raise
def test_esky_locking(self): """Test that locking an Esky works correctly.""" platform = get_platform() appdir = tempfile.mkdtemp() try: vdir = os.path.join(appdir, ESKY_APPDATA_DIR, "testapp-0.1.%s" % (platform, )) os.makedirs(vdir) os.mkdir(os.path.join(vdir, ESKY_CONTROL_DIR)) open( os.path.join(vdir, ESKY_CONTROL_DIR, "bootstrap-manifest.txt"), "wb").close() e1 = esky.Esky(appdir, "http://example.com/downloads/") assert e1.name == "testapp" assert e1.version == "0.1" assert e1.platform == platform e2 = esky.Esky(appdir, "http://example.com/downloads/") assert e2.name == "testapp" assert e2.version == "0.1" assert e2.platform == platform locked = [] errors = [] trigger1 = threading.Event() trigger2 = threading.Event() def runit(e, t1, t2): def runme(): try: e.lock() except Exception, err: errors.append(err) else: locked.append(e)
def test_multiple_runs_of_setup_function(): '''make sure our fixes support multiple runs ''' from esky.bdist_esky import Executable setup, options, new_script = esky_setup('Simple Working', WORKING_SCRIPT) new_script2 = make_new_script_name('test_multiple_working.py') insert_code(new_script2,'import sys') options2 = copy.deepcopy(options) options2['scripts'] = [new_script2] options2['version'] = '0.2' esky_zip_name = get_zip_name(options2) # Now test that freeze future works as well cleanup_dirs() setup(**options) clean_exit, stderr = run_script(new_script, freezer='esky') assert clean_exit # only works if we cleanup dirs.. same as original esky cleanup_dirs() setup(**options2) if os.name == 'nt': platform = get_platform() esky_zip_name = 'Simple Working-0.2.%s.zip' % platform clean_exit, stderr = run_script(new_script2, freezer='esky', zip_name=esky_zip_name) assert clean_exit
def _run_freeze_scripts(self): """Call the selected freezer module to freeze the scripts.""" fullname = self.distribution.get_fullname() platform = get_platform() self.freezer_module.freeze(self) if platform != "win32": lockfile = os.path.join(self.freeze_dir,ESKY_CONTROL_DIR,"lockfile.txt") with open(lockfile,"w") as lf: lf.write("this file is used by esky to lock the version dir\n")
def _run_create_zipfile(self): """Zip up the final distribution.""" print "zipping up the esky" fullname = self.distribution.get_fullname() platform = get_platform() zfname = os.path.join(self.dist_dir,"%s.%s.zip"%(fullname,platform,)) if hasattr(self.freezer_module,"zipit"): self.freezer_module.zipit(self,self.bootstrap_dir,zfname) else: create_zipfile(self.bootstrap_dir,zfname,compress=True) really_rmtree(self.bootstrap_dir)
def _run_initialise_dirs(self): """Create the dirs into which to freeze the app.""" fullname = self.distribution.get_fullname() platform = get_platform() self.bootstrap_dir = os.path.join(self.dist_dir, "%s.%s"%(fullname,platform,)) self.freeze_dir = os.path.join(self.bootstrap_dir, "%s.%s"%(fullname,platform,)) if os.path.exists(self.bootstrap_dir): shutil.rmtree(self.bootstrap_dir) os.makedirs(self.freeze_dir)
def _run_initialise_dirs(self): """Create the dirs into which to freeze the app.""" fullname = self.distribution.get_fullname() platform = get_platform() self.bootstrap_dir = os.path.join(self.dist_dir, "%s.%s" % (fullname, platform)) if self.enable_appdata_dir: self.freeze_dir = os.path.join(self.bootstrap_dir, ESKY_APPDATA_DIR, "%s.%s" % (fullname, platform)) else: self.freeze_dir = os.path.join(self.bootstrap_dir, "%s.%s" % (fullname, platform)) if os.path.exists(self.bootstrap_dir): really_rmtree(self.bootstrap_dir) os.makedirs(self.freeze_dir)
def _run_freeze_scripts(self): """Call the selected freezer module to freeze the scripts.""" fullname = self.distribution.get_fullname() platform = get_platform() self.freezer_module.freeze(self) if platform != "win32": lockfile = os.path.join(self.freeze_dir,ESKY_CONTROL_DIR,"lockfile.txt") with open(lockfile,"w") as lf: lf.write("this file is used by esky to lock the version dir\n") # TODO: remove compatability hook shutil.copyfile(os.path.join(self.freeze_dir,ESKY_CONTROL_DIR,"lockfile.txt"),os.path.join(self.freeze_dir,"esky-lockfile.txt")) # TODO: remove compatability hook shutil.copyfile(os.path.join(self.freeze_dir,ESKY_CONTROL_DIR,"bootstrap-manifest.txt"),os.path.join(self.freeze_dir,"esky-bootstrap.txt"))
def _run_initialise_dirs(self): """Create the dirs into which to freeze the app.""" fullname = self.distribution.get_fullname() platform = get_platform() self.bootstrap_dir = os.path.join(self.dist_dir, "%s.%s"%(fullname,platform,)) if self.enable_appdata_dir: self.freeze_dir = os.path.join(self.bootstrap_dir,ESKY_APPDATA_DIR, "%s.%s"%(fullname,platform,)) else: self.freeze_dir = os.path.join(self.bootstrap_dir, "%s.%s"%(fullname,platform,)) if os.path.exists(self.bootstrap_dir): really_rmtree(self.bootstrap_dir) os.makedirs(self.freeze_dir)
def _run_create_zipfile(self): """Zip up the final distribution.""" print "zipping up the esky" fullname = self.distribution.get_fullname() platform = get_platform() zfname = os.path.join(self.dist_dir, "%s.%s.zip" % (fullname, platform, )) if hasattr(self.freezer_module, "zipit"): self.freezer_module.zipit(self, self.bootstrap_dir, zfname) else: create_zipfile(self.bootstrap_dir, zfname, compress=True) # Only remove bootstrap dir if option is passed if (self.rm_freeze_dir_after_zipping and self.rm_freeze_dir_after_zipping != 'False'): really_rmtree(self.bootstrap_dir)
def get_zip_name(options): '''mirrors the esky behaviour of creating a zipfile name, ''' def get_name(): try: return options['name'] or "UNKNOWN" except KeyError: return "UNKNOWN" def get_version(): try: return options['version'] or "0.0.0" except KeyError: return "0.0.0" fullname = "%s-%s" % (get_name(), get_version()) platform = get_platform() zfname = os.path.join("%s.%s.zip"%(fullname,platform,)) return zfname
def setUp(self): self.tests_root = dirname(__file__) platform = get_platform() self.tfdir = tfdir = os.path.join(self.tests_root,"patch-test-files") self.workdir = workdir = os.path.join(self.tests_root,"patch-test-temp."+platform) if not os.path.isdir(tfdir): os.makedirs(tfdir) if not os.path.isdir(workdir): os.makedirs(workdir) # Ensure we have the expected test files. # Download from PyPI if necessary. for (tfname,hash) in self._TEST_FILES: tfpath = os.path.join(tfdir,tfname) if not os.path.exists(tfpath): data = urllib2.urlopen(self._TEST_FILES_URL+tfname).read() assert hashlib.md5(data).hexdigest() == hash with open(tfpath,"wb") as f: f.write(data)
def setUp(self): self.tests_root = dirname(__file__) platform = get_platform() self.tfdir = tfdir = os.path.join(self.tests_root, "patch-test-files") self.workdir = workdir = os.path.join(self.tests_root, "patch-test-temp." + platform) if not os.path.isdir(tfdir): os.makedirs(tfdir) if not os.path.isdir(workdir): os.makedirs(workdir) # Ensure we have the expected test files. # Download from PyPI if necessary. for (tfname, hash) in self._TEST_FILES: tfpath = os.path.join(tfdir, tfname) if not os.path.exists(tfpath): data = urllib2.urlopen(self._TEST_FILES_URL + tfname).read() assert hashlib.md5(data).hexdigest() == hash with open(tfpath, "wb") as f: f.write(data)
def compile_to_bootstrap_exe(self,exe,source,relpath=None): """Compile the given sourcecode into a bootstrapping exe. This method compiles the given sourcecode into a stand-alone exe using PyPy, then stores that in the bootstrap env under the name of the given Executable object. If the source has been previously compiled then a cached version of the exe may be used. """ if not relpath: relpath = exe.name source = "__rpython__ = True\n" + source cdir = os.path.join(self.tempdir,"compile") if not os.path.exists(cdir): os.mkdir(cdir) source_hash = hashlib.md5(source).hexdigest() outname = "bootstrap_%s.%s" % (source_hash,get_platform()) if exe.gui_only: outname += ".gui" if sys.platform == "win32": outname += ".exe" # First try to use a precompiled version. if COMPILED_BOOTSTRAP_CACHE is not None: outfile = os.path.join(COMPILED_BOOTSTRAP_CACHE,outname) if os.path.exists(outfile): return self.copy_to_bootstrap_env(outfile,relpath) # Otherwise we have to compile it anew. try: outfile = self._compiled_exes[(source_hash,exe.gui_only)] except KeyError: infile = os.path.join(cdir,"bootstrap.py") outfile = os.path.join(cdir,outname) with open(infile,"wt") as f: f.write(source) opts = dict(gui_only=exe.gui_only) pypyc.compile_rpython(infile,outfile,**opts) self._compiled_exes[(source_hash,exe.gui_only)] = outfile # Try to save the compiled exe for future use. if COMPILED_BOOTSTRAP_CACHE is not None: cachedfile = os.path.join(COMPILED_BOOTSTRAP_CACHE,outname) try: shutil.copy2(outfile,cachedfile) except EnvironmentError: pass return self.copy_to_bootstrap_env(outfile,relpath)
def _run_create_zipfile(self): """Zip up the final distribution.""" if self.compress: fullname = self.distribution.get_fullname() platform = get_platform() zfname = os.path.join(self.dist_dir,"%s.%s.zip"%(fullname,platform,)) if hasattr(self.freezer_module,"zipit"): self.freezer_module.zipit(self,self.bootstrap_dir,zfname) else: if self.compress == 'zip': print "zipping up the esky with compression" create_zipfile(self.bootstrap_dir,zfname,compress=True) really_rmtree(self.bootstrap_dir) elif self.compress == 'ZIP': print "zipping up the esky without compression" create_zipfile(self.bootstrap_dir,zfname,compress=False) really_rmtree(self.bootstrap_dir) else: print("To zip the esky use compress or c set to ZIP or zip")
def get_zip_name(options): '''mirrors the esky behaviour of creating a zipfile name, ''' def get_name(): try: return options['name'] or "UNKNOWN" except KeyError: return "UNKNOWN" def get_version(): try: return options['version'] or "0.0.0" except KeyError: return "0.0.0" fullname = "%s-%s" % (get_name(), get_version()) platform = get_platform() zfname = os.path.join("%s.%s.zip" % ( fullname, platform, )) return zfname
def test_esky_patch(): '''need to have our esky fixes developed in freeze future moved to f_py2exe or f_cxfrexe etc for patchingo work''' tdir=os.getcwd() uzdir = os.path.join(tdir,"unzip") try: really_rmtree(uzdir) except Exception: pass setup, options, new_script = esky_setup('Simple Working', WORKING_SCRIPT) setup(**options) new_script2 = make_new_script_name('testing_patching.py') insert_code(new_script2,'import sys') options2 = copy.deepcopy(options) options2['scripts'] = [new_script2] options2['script_args'] = ['bdist_esky_patch'] options2['version'] = '2.0' options2['freezer'] = '2.0' setup(**options2) platform = get_platform() deep_extract_zipfile(os.path.join(tdir,"dist","Simple Working-1.0.%s.zip"%(platform,)),uzdir) with open(os.path.join(tdir,"dist","Simple Working-2.0.%s.from-1.0.patch"%(platform,)),"rb") as f: esky.patch.apply_patch(uzdir,f) filewithext = os.path.basename(new_script2) file = os.path.splitext(filewithext)[0] path_file = os.path.join(uzdir, file) cmd = [path_file] proc = subprocess.Popen(cmd, stderr=subprocess.PIPE) errs = proc.communicate() if not proc.returncode: exit_code = True else: exit_code = False assert exit_code really_rmtree(uzdir)
def __init__(self, driveAttributes): from distutils.core import setup attribs = driveAttributes freeze_options = {} ext_modules = [] script = attribs.get_script() scripts = attribs.get_scripts() name = attribs.get_name() packages = Packages(attribs.get_package_dirs()).load() # special handling for data files, except for Linux if ((sys.platform == "win32" or sys.platform == 'darwin') and 'nxdrive.data' in packages): packages.remove('nxdrive.data') package_data = attribs.get_package_data() icons_home = attribs.get_icons_home() ui5_home = attribs.get_ui5_home() win_icon = os.path.join(icons_home, attribs.get_win_icon()) png_icon = os.path.join(icons_home, attribs.get_png_icon()) osx_icon = os.path.join(icons_home, attribs.get_osx_icon()) if sys.platform == 'win32': icon = win_icon elif sys.platform == 'darwin': icon = osx_icon else: icon = png_icon # Files to include in frozen app # build_exe freeze with cx_Freeze (Windows) include_files = attribs.get_includes() # bdist_esky freeze with cx_Freeze (Windows) and py2app (OS X) # In fact this is a global setup option # TODO NXP-13810: check removed data_files from py2app and added to # global setup icon_files = data_file_dir(icons_home, 'icons', include_files).load() ui5_files = data_file_dir(ui5_home, 'ui5', include_files).load_recursive() data_files = [('icons', icon_files)] data_files.extend(ui5_files) data_files.extend(attribs.get_data_files()) old_version = None init_file = attribs.get_init_file() version = read_version(init_file) if '-dev' in version: # timestamp the dev artifacts as distutils only accepts "b" + digit timestamp = datetime.utcnow().isoformat() timestamp = timestamp.replace(":", "") timestamp = timestamp.replace(".", "") timestamp = timestamp.replace("T", "") timestamp = timestamp.replace("-", "") old_version = version # distutils imposes a max 3 levels integer version # (+ prerelease markers which are not allowed in a # msi package version). On the other hand, # msi imposes the a.b.c.0 or a.b.c.d format where # a, b, c and d are all 16 bits integers # TODO: align on latest distutils versioning month_day = timestamp[4:8] if month_day.startswith('0'): month_day = month_day[1:] version = version.replace('-dev', ".%s" % ( month_day)) update_version(init_file, version) print "Updated version to " + version # Create JSON metadata file for the frozen application json_file = create_json_metadata(version, SERVER_MIN_VERSION) print "Created JSON metadata file for frozen app: " + json_file includes = [ "PyQt4", "PyQt4.QtCore", "PyQt4.QtNetwork", "PyQt4.QtGui", "atexit" # implicitly required by PyQt4 ] if attribs.include_xattr_binaries(): includes.append('cffi') includes.append('xattr') attribs.append_includes(includes) excludes = [ "ipdb", "clf", "IronPython", "pydoc", "tkinter", ] if not attribs.include_xattr_binaries(): excludes.append('cffi') excludes.append('xattr') if '--freeze' in sys.argv: print "Building standalone executable..." sys.argv.remove('--freeze') from nx_cx_Freeze import setup from cx_Freeze import Executable as cx_Executable from esky.util import get_platform # build_exe does not seem to take the package_dir info into account sys.path.append(attribs.get_path_append()) executables = [cx_Executable(script)] freeze_options = dict() if sys.platform == "win32": # Windows GUI program that can be launched without a cmd # console script_w = attribs.get_win_script() if script_w is not None: scripts.append( es_Executable(script_w, icon=icon, shortcutDir="ProgramMenuFolder", shortcutName=attribs.shortcutName())) executables.append( cx_Executable(script_w, targetName=attribs.get_win_targetName(), base="Win32GUI", icon=icon, shortcutDir="ProgramMenuFolder", shortcutName=attribs.shortcutName())) freeze_options.update({'attribs': attribs}) package_data = {} esky_app_name = (attribs.get_name() + '-' + version + '.' + get_platform()) esky_dist_dir = os.path.join(OUTPUT_DIR, esky_app_name) freeze_options.update({ 'executables': executables, 'options': { "build": { "exe_command": "bdist_esky", }, "build_exe": { "includes": includes, "packages": packages + [ "nose", ], "excludes": excludes, "include_files": include_files, }, "bdist_esky": { "excludes": excludes, "enable_appdata_dir": True, "freezer_options": { "packages": packages + [ "nose", ], }, "rm_freeze_dir_after_zipping": False, }, "install": { "skip_sub_commands": "install_lib,install_scripts,install_data", }, "install_exe": { "skip_build": True, "build_dir": esky_dist_dir, }, "bdist_msi": { "add_to_path": True, "upgrade_code": attribs.get_uid(), }, }, }) # Include cffi compiled C extension under Linux if sys.platform.startswith('linux') and attribs.include_xattr_binaries(): import xattr includeFiles = [(os.path.join(os.path.dirname(xattr.__file__), '_cffi__x7c9e2f59xb862c7dd.so'), '_cffi__x7c9e2f59xb862c7dd.so')] freeze_options['options']['bdist_esky']['freezer_options'].update({ "includeFiles": includeFiles }) if sys.platform == 'darwin': # Under OSX we use py2app instead of cx_Freeze because we need: # - argv_emulation=True for nxdrive:// URL scheme handling # - easy Info.plist customization import py2app # install the py2app command if attribs.include_xattr_binaries(): import xattr ext_modules = [xattr.lib.ffi.verifier.get_extension()] includes.append("_cffi__x7c9e2f59xb862c7dd") name = attribs.get_CFBundleName() py2app_options = dict( iconfile=icon, qt_plugins='imageformats', argv_emulation=False, # We use QT for URL scheme handling plist=dict( CFBundleDisplayName=attribs.get_CFBundleDisplayName(), CFBundleName=attribs.get_CFBundleName(), CFBundleIdentifier=attribs.get_CFBundleIdentifier(), LSUIElement=True, # Do not launch as a Dock application CFBundleURLTypes=[ dict( CFBundleURLName=attribs.get_CFBundleURLName(), CFBundleURLSchemes=(attribs .get_CFBundleURLSchemes()), ) ], NSServices=[ dict( NSMenuItem=dict( default=attribs.get_CFBundleDisplayName() ), NSMessage=u"macRightClick", NSPortName=attribs.get_CFBundleDisplayName(), NSRequiredContext=dict(), NSSendTypes=[ u'NSStringPboardType', ], NSSendFileTypes=[ u"public.item" ] ) ] ), includes=includes, excludes=excludes, ) freeze_options = dict( app=attribs.get_app(), options=dict( py2app=py2app_options, bdist_esky=dict( enable_appdata_dir=True, create_zipfile=False, freezer_options=py2app_options, ) ) ) setup( name=name, version=version, description=attribs.get_description(), author=attribs.get_author(), author_email=attribs.get_author_email(), url=attribs.get_url(), packages=packages, package_dir=attribs.get_package_dir(), package_data=package_data, scripts=scripts, long_description=attribs.get_long_description(), data_files=data_files, ext_modules=ext_modules, **freeze_options ) if old_version is not None: update_version(init_file, old_version) print "Restored version to " + old_version
def _run_eskytester(self, options): """Build and run the eskytester app using the given distutils options. The "eskytester" application can be found next to this file, and the sequence of tests performed range across "script1.py" to "script3.py". """ olddir = os.path.abspath(os.curdir) # tdir = os.path.join(os.path.dirname(__file__),"DIST") # if os.path.exists(tdir): # really_rmtree(tdir) # os.mkdir(tdir) tdir = tempfile.mkdtemp() server = None script2 = None try: options.setdefault("build", {})["build_base"] = os.path.join(tdir, "build") options.setdefault("bdist", {})["dist_dir"] = os.path.join(tdir, "dist") # Set some callbacks to test that they work correctly options.setdefault("bdist_esky", {}).setdefault( "pre_freeze_callback", "esky.tests.test_esky.assert_freezedir_exists" ) options.setdefault("bdist_esky", {}).setdefault("pre_zip_callback", assert_freezedir_exists) platform = get_platform() deploydir = "deploy.%s" % (platform,) esky_root = dirname(dirname(dirname(__file__))) os.chdir(tdir) shutil.copytree(os.path.join(esky_root, "esky", "tests", "eskytester"), "eskytester") dir_util._path_created.clear() # Build three increasing versions of the test package. # Version 0.2 will include a bundled MSVCRT on win32. # Version 0.3 will be distributed as a patch. metadata = dict( name="eskytester", packages=["eskytester"], author="rfk", description="the esky test package", data_files=[("data", ["eskytester/datafile.txt"])], package_data={"eskytester": ["pkgdata.txt"]}, ) options2 = options.copy() options2["bdist_esky"] = options["bdist_esky"].copy() options2["bdist_esky"]["bundle_msvcrt"] = True script1 = "eskytester/script1.py" script2 = Executable([None, open("eskytester/script2.py")], name="script2") script3 = "eskytester/script3.py" dist_setup(version="0.1", scripts=[script1], options=options, script_args=["bdist_esky"], **metadata) dist_setup( version="0.2", scripts=[script1, script2], options=options2, script_args=["bdist_esky"], **metadata ) dist_setup( version="0.3", scripts=[script2, script3], options=options, script_args=["bdist_esky_patch"], **metadata ) os.unlink(os.path.join(tdir, "dist", "eskytester-0.3.%s.zip" % (platform,))) # Check that the patches apply cleanly uzdir = os.path.join(tdir, "unzip") deep_extract_zipfile(os.path.join(tdir, "dist", "eskytester-0.1.%s.zip" % (platform,)), uzdir) with open(os.path.join(tdir, "dist", "eskytester-0.3.%s.from-0.1.patch" % (platform,)), "rb") as f: esky.patch.apply_patch(uzdir, f) shutil.rmtree(uzdir) deep_extract_zipfile(os.path.join(tdir, "dist", "eskytester-0.2.%s.zip" % (platform,)), uzdir) with open(os.path.join(tdir, "dist", "eskytester-0.3.%s.from-0.2.patch" % (platform,)), "rb") as f: esky.patch.apply_patch(uzdir, f) shutil.rmtree(uzdir) # Serve the updates at http://localhost:8000/dist/ print "running local update server" server = HTTPServer(("localhost", 8000), SimpleHTTPRequestHandler) server_thread = threading.Thread(target=server.serve_forever) server_thread.daemon = True server_thread.start() # Set up the deployed esky environment for the initial version zfname = os.path.join(tdir, "dist", "eskytester-0.1.%s.zip" % (platform,)) os.mkdir(deploydir) extract_zipfile(zfname, deploydir) # Run the scripts in order. if options["bdist_esky"]["freezer_module"] == "py2app": appdir = os.path.join(deploydir, os.listdir(deploydir)[0]) cmd1 = os.path.join(appdir, "Contents", "MacOS", "script1") cmd2 = os.path.join(appdir, "Contents", "MacOS", "script2") cmd3 = os.path.join(appdir, "Contents", "MacOS", "script3") else: appdir = deploydir if sys.platform == "win32": cmd1 = os.path.join(deploydir, "script1.exe") cmd2 = os.path.join(deploydir, "script2.exe") cmd3 = os.path.join(deploydir, "script3.exe") else: cmd1 = os.path.join(deploydir, "script1") cmd2 = os.path.join(deploydir, "script2") cmd3 = os.path.join(deploydir, "script3") print "spawning eskytester script1", options["bdist_esky"]["freezer_module"] os.unlink(os.path.join(tdir, "dist", "eskytester-0.1.%s.zip" % (platform,))) p = subprocess.Popen(cmd1) assert p.wait() == 0 os.unlink(os.path.join(appdir, "tests-completed")) print "spawning eskytester script2" os.unlink(os.path.join(tdir, "dist", "eskytester-0.2.%s.zip" % (platform,))) p = subprocess.Popen(cmd2) assert p.wait() == 0 os.unlink(os.path.join(appdir, "tests-completed")) print "spawning eskytester script3" p = subprocess.Popen(cmd3) assert p.wait() == 0 os.unlink(os.path.join(appdir, "tests-completed")) finally: if script2: script2.script[1].close() os.chdir(olddir) if sys.platform == "win32": # wait for the cleanup-at-exit pocess to finish time.sleep(4) really_rmtree(tdir) if server: server.shutdown()
def __init__(self, attribs): from distutils.core import setup freeze_options = {} ext_modules = [] script = attribs.get_script() scripts = [script] name = attribs.get_name() packages = Packages(attribs.get_package_dirs()).load() package_data = attribs.get_package_data() icons_home = attribs.get_icons_home() ui5_home = attribs.get_ui5_home() if sys.platform == 'win32': icon = os.path.join(icons_home, attribs.get_win_icon()) elif sys.platform == 'darwin': icon = os.path.join(icons_home, attribs.get_osx_icon()) else: icon = os.path.join(icons_home, attribs.get_png_icon()) # Files to include in frozen app # build_exe freeze with cx_Freeze (Windows) include_files = attribs.get_includes() # bdist_esky freeze with cx_Freeze (Windows) and py2app (OS X) # In fact this is a global setup option # TODO NXP-13810: check removed data_files from py2app and added to # global setup icon_files = DataFileDir(icons_home, 'icons', include_files).load() ui5_files = DataFileDir(ui5_home, 'ui5', include_files).load_recursive() data_files = [('icons', icon_files)] data_files.extend(ui5_files) data_files.extend(attribs.get_data_files()) drive_version = get_version(attribs.get_init_file()) # Create JSON metadata file for the frozen application json_file = create_json_metadata(drive_version, SERVER_MIN_VERSION) print('Created JSON metadata file for frozen app: ' + json_file) includes = [ 'atexit', # Implicitly required by PyQt4 'js2py.pyjs', # Implicitly required by pypac ] excludes = [ 'ipdb', 'pydoc', 'yappi', ] if attribs.include_xattr_binaries(): includes.append('cffi') includes.append('xattr') else: excludes.append('cffi') excludes.append('xattr') attribs.append_includes(includes) if '--freeze' in sys.argv: print('Building standalone executable...') sys.argv.remove('--freeze') from nx_cx_Freeze import setup from cx_Freeze import Executable as cx_Executable from esky.util import get_platform # build_exe does not seem to take the package_dir info into account sys.path.insert(0, attribs.get_path_append()) try: packages.remove('nxdrive.data') except ValueError: pass executables = [cx_Executable(script)] freeze_options = dict() if sys.platform == 'win32': # Copy OpenSSL DLL data_files.append('libeay32.dll') data_files.append('ssleay32.dll') # Windows GUI program that can be launched without a cmd # console scripts.append(es_Executable( attribs.get_script(), icon=icon, shortcutDir='ProgramMenuFolder', shortcutName=attribs.shortcutName(), )) executables.append(cx_Executable( attribs.get_win_target_name(), targetName=attribs.get_win_target_name(), base='Win32GUI', icon=icon, shortcutDir='ProgramMenuFolder', shortcutName=attribs.shortcutName(), )) # Add a shortcut on the desktop executables.append(cx_Executable( attribs.get_win_target_name(), targetName=attribs.get_win_target_name(), base='Win32GUI', icon=icon, shortcutDir='DesktopFolder', shortcutName=attribs.shortcutName(), )) freeze_options.update({'attribs': attribs}) package_data = {} esky_app_name = (attribs.get_name() + '-' + drive_version + '.' + get_platform()) esky_dist_dir = os.path.join(OUTPUT_DIR, esky_app_name) freeze_options.update({ 'executables': executables, 'options': { 'build': { 'exe_command': 'bdist_esky', }, 'build_exe': { 'includes': includes, 'packages': packages, 'excludes': excludes, 'include_files': include_files, }, 'bdist_esky': { 'includes': includes, 'excludes': excludes, 'enable_appdata_dir': True, 'freezer_options': { 'packages': packages, }, 'rm_freeze_dir_after_zipping': False, }, 'install': { 'skip_sub_commands': 'install_lib,install_scripts,install_data', }, 'install_exe': { 'skip_build': True, 'build_dir': esky_dist_dir, }, 'bdist_msi': { 'add_to_path': True, 'upgrade_code': attribs.get_uid(), }, }, }) if sys.platform == 'darwin': # Under OSX we use py2app instead of cx_Freeze because we need: # - argv_emulation=True for nxdrive:// URL scheme handling # - easy Info.plist customization name = attribs.get_CFBundleName() py2app_options = { 'iconfile': icon, 'qt_plugins': 'imageformats', 'argv_emulation': False, # We use Qt for URL scheme handling 'plist': { 'CFBundleDisplayName': attribs.get_CFBundleDisplayName(), 'CFBundleName': attribs.get_CFBundleName(), 'CFBundleIdentifier': attribs.get_CFBundleIdentifier(), 'LSUIElement': True, # Do not launch as a Dock application 'CFBundleURLTypes': [{ 'CFBundleURLName': attribs.get_CFBundleURLName(), 'CFBundleURLSchemes': attribs.get_CFBundleURLSchemes(), }], 'NSServices': [{ 'NSMenuItem': { 'default': attribs.get_CFBundleDisplayName(), }, 'NSMessage': 'macRightClick', 'NSPortName': attribs.get_CFBundleDisplayName(), 'NSRequiredContext': {}, 'NSSendTypes': [ 'NSStringPboardType', ], 'NSSendFileTypes': [ 'public.item', ], }], }, 'includes': includes, 'excludes': excludes, } freeze_options = { 'app': scripts, 'options': { 'py2app': py2app_options, 'bdist_esky': { 'enable_appdata_dir': True, 'create_zipfile': False, 'freezer_options': py2app_options, } } } entry_points = {} if sys.platform == 'win32': entry_points = { 'console_scripts': ['ndrive=nxdrive.commandline:main'], 'gui_scripts': ['ndrivew=nxdrive.commandline:main'], } with warnings.catch_warnings(): # Hide Windows "Unknown distribution option: 'attribs'" warnings.simplefilter('ignore', category=UserWarning) setup( name=name, version=drive_version, description=attribs.get_description(), author=attribs.get_author(), author_email=attribs.get_author_email(), url=attribs.get_url(), packages=packages, package_dir=attribs.get_package_dir(), package_data=package_data, scripts=scripts, long_description=attribs.get_long_description(), data_files=data_files, ext_modules=ext_modules, entry_points=entry_points, platforms=['Darwin', 'Linux', 'Windows'], license=attribs.get_licence(), **freeze_options )
def __init__(self, attribs): from distutils.core import setup freeze_options = {} ext_modules = [] script = attribs.get_script() scripts = [script] name = attribs.get_name() packages = Packages(attribs.get_package_dirs()).load() package_data = attribs.get_package_data() icons_home = attribs.get_icons_home() ui5_home = attribs.get_ui5_home() if sys.platform == 'win32': icon = os.path.join(icons_home, attribs.get_win_icon()) elif sys.platform == 'darwin': icon = os.path.join(icons_home, attribs.get_osx_icon()) else: icon = os.path.join(icons_home, attribs.get_png_icon()) # Files to include in frozen app # build_exe freeze with cx_Freeze (Windows) include_files = attribs.get_includes() # bdist_esky freeze with cx_Freeze (Windows) and py2app (OS X) # In fact this is a global setup option # TODO NXP-13810: check removed data_files from py2app and added to # global setup icon_files = DataFileDir(icons_home, 'icons', include_files).load() ui5_files = DataFileDir(ui5_home, 'ui5', include_files).load_recursive() data_files = [('icons', icon_files)] data_files.extend(ui5_files) data_files.extend(attribs.get_data_files()) drive_version = get_version(attribs.get_init_file()) # Create JSON metadata file for the frozen application json_file = create_json_metadata(drive_version, SERVER_MIN_VERSION) print('Created JSON metadata file for frozen app: ' + json_file) includes = [ 'atexit', # Implicitly required by PyQt4 'js2py.pyjs', # Implicitly required by pypac ] excludes = [ 'ipdb', 'pydoc', 'yappi', ] if attribs.include_xattr_binaries(): includes.append('cffi') includes.append('xattr') else: excludes.append('cffi') excludes.append('xattr') attribs.append_includes(includes) if '--freeze' in sys.argv: print('Building standalone executable...') sys.argv.remove('--freeze') from nx_cx_Freeze import setup from cx_Freeze import Executable as cx_Executable from esky.util import get_platform # build_exe does not seem to take the package_dir info into account sys.path.insert(0, attribs.get_path_append()) try: packages.remove('nxdrive.data') except ValueError: pass executables = [cx_Executable(script)] freeze_options = dict() if sys.platform == 'win32': # Copy OpenSSL DLL data_files.append('libeay32.dll') data_files.append('ssleay32.dll') # Windows GUI program that can be launched without a cmd # console scripts.append( es_Executable( attribs.get_script(), icon=icon, shortcutDir='ProgramMenuFolder', shortcutName=attribs.shortcutName(), )) executables.append( cx_Executable( attribs.get_win_target_name(), targetName=attribs.get_win_target_name(), base='Win32GUI', icon=icon, shortcutDir='ProgramMenuFolder', shortcutName=attribs.shortcutName(), )) # Add a shortcut on the desktop executables.append( cx_Executable( attribs.get_win_target_name(), targetName=attribs.get_win_target_name(), base='Win32GUI', icon=icon, shortcutDir='DesktopFolder', shortcutName=attribs.shortcutName(), )) freeze_options.update({'attribs': attribs}) package_data = {} esky_app_name = (attribs.get_name() + '-' + drive_version + '.' + get_platform()) esky_dist_dir = os.path.join(OUTPUT_DIR, esky_app_name) freeze_options.update({ 'executables': executables, 'options': { 'build': { 'exe_command': 'bdist_esky', }, 'build_exe': { 'includes': includes, 'packages': packages, 'excludes': excludes, 'include_files': include_files, }, 'bdist_esky': { 'includes': includes, 'excludes': excludes, 'enable_appdata_dir': True, 'freezer_options': { 'packages': packages, }, 'rm_freeze_dir_after_zipping': False, }, 'install': { 'skip_sub_commands': 'install_lib,install_scripts,install_data', }, 'install_exe': { 'skip_build': True, 'build_dir': esky_dist_dir, }, 'bdist_msi': { 'add_to_path': True, 'upgrade_code': attribs.get_uid(), }, }, }) if sys.platform == 'darwin': # Under OSX we use py2app instead of cx_Freeze because we need: # - argv_emulation=True for nxdrive:// URL scheme handling # - easy Info.plist customization name = attribs.get_CFBundleName() py2app_options = { 'iconfile': icon, 'qt_plugins': 'imageformats', 'argv_emulation': False, # We use Qt for URL scheme handling 'plist': { 'CFBundleDisplayName': attribs.get_CFBundleDisplayName(), 'CFBundleName': attribs.get_CFBundleName(), 'CFBundleIdentifier': attribs.get_CFBundleIdentifier(), 'LSUIElement': True, # Do not launch as a Dock application 'CFBundleURLTypes': [{ 'CFBundleURLName': attribs.get_CFBundleURLName(), 'CFBundleURLSchemes': attribs.get_CFBundleURLSchemes(), }], 'NSServices': [{ 'NSMenuItem': { 'default': attribs.get_CFBundleDisplayName(), }, 'NSMessage': 'macRightClick', 'NSPortName': attribs.get_CFBundleDisplayName(), 'NSRequiredContext': {}, 'NSSendTypes': [ 'NSStringPboardType', ], 'NSSendFileTypes': [ 'public.item', ], }], }, 'includes': includes, 'excludes': excludes, } freeze_options = { 'app': scripts, 'options': { 'py2app': py2app_options, 'bdist_esky': { 'enable_appdata_dir': True, 'create_zipfile': False, 'freezer_options': py2app_options, } } } entry_points = {} if sys.platform == 'win32': entry_points = { 'console_scripts': ['ndrive=nxdrive.commandline:main'], 'gui_scripts': ['ndrivew=nxdrive.commandline:main'], } with warnings.catch_warnings(): # Hide Windows "Unknown distribution option: 'attribs'" warnings.simplefilter('ignore', category=UserWarning) setup(name=name, version=drive_version, description=attribs.get_description(), author=attribs.get_author(), author_email=attribs.get_author_email(), url=attribs.get_url(), packages=packages, package_dir=attribs.get_package_dir(), package_data=package_data, scripts=scripts, long_description=attribs.get_long_description(), data_files=data_files, ext_modules=ext_modules, entry_points=entry_points, platforms=['Darwin', 'Linux', 'Windows'], license=attribs.get_licence(), **freeze_options)
def __init__(self, driveAttributes): from distutils.core import setup attribs = driveAttributes freeze_options = {} script = attribs.get_script() scripts = attribs.get_scripts() name = attribs.get_name() packages = Packages(attribs.get_package_dirs()).load() # special handling for data files packages.remove('nxdrive.data') packages.remove('nxdrive.data.icons') package_data = attribs.get_package_data() icons_home = attribs.get_icons_home() alembic_home = attribs.get_alembic_home() alembic_versions_home = attribs.get_alembic_versions_home() win_icon = os.path.join(icons_home, attribs.get_win_icon()) png_icon = os.path.join(icons_home, attribs.get_png_icon()) osx_icon = os.path.join(icons_home, attribs.get_osx_icon()) if sys.platform == 'win32': icon = win_icon elif sys.platform == 'darwin': icon = osx_icon else: icon = png_icon # Files to include in frozen app: icons, alembic, alembic versions # build_exe freeze with cx_Freeze (Windows) include_files = attribs.get_includes() # bdist_esky freeze with cx_Freeze (Windows) and py2app (OS X) # In fact this is a global setup option # TODO NXP-13810: check removed data_files from py2app and added to # global setup icon_files = data_file_dir(icons_home, 'icons', include_files).load() alembic_files = data_file_dir( alembic_home, 'alembic', include_files).load() alembic_version_files = data_file_dir( alembic_versions_home, 'alembic/versions', include_files).load() data_files = [('icons', icon_files), ('alembic', alembic_files), ('alembic/versions', alembic_version_files)] data_files.extend(attribs.get_data_files()) old_version = None init_file = attribs.get_init_file() version = read_version(init_file) if '--dev' in sys.argv: # timestamp the dev artifacts for continuous integration # distutils only accepts "b" + digit sys.argv.remove('--dev') timestamp = datetime.utcnow().isoformat() timestamp = timestamp.replace(":", "") timestamp = timestamp.replace(".", "") timestamp = timestamp.replace("T", "") timestamp = timestamp.replace("-", "") old_version = version # distutils imposes a max 3 levels integer version # (+ prerelease markers which are not allowed in a # msi package version). On the other hand, # msi imposes the a.b.c.0 or a.b.c.d format where # a, b, c and d are all 16 bits integers version = version.replace('-dev', ".%s" % ( timestamp[4:8])) update_version(init_file, version) print "Updated version to " + version # Create JSON metadata file for the frozen application json_file = create_json_metadata(version, SERVER_MIN_VERSION) print "Created JSON metadata file for frozen app: " + json_file includes = [ "PyQt4", "PyQt4.QtCore", "PyQt4.QtNetwork", "PyQt4.QtGui", "atexit", # implicitly required by PyQt4 "sqlalchemy.dialects.sqlite", ] attribs.append_includes(includes) excludes = [ "ipdb", "clf", "IronPython", "pydoc", "tkinter", ] if '--freeze' in sys.argv: print "Building standalone executable..." sys.argv.remove('--freeze') from nx_cx_Freeze import setup from cx_Freeze import Executable as cx_Executable from esky.util import get_platform # build_exe does not seem to take the package_dir info into account sys.path.append(attribs.get_path_append()) executables = [cx_Executable(script)] if sys.platform == "win32": # Windows GUI program that can be launched without a cmd # console script_w = attribs.get_win_script() if script_w is not None: scripts.append( es_Executable(script_w, icon=icon, shortcutDir="ProgramMenuFolder", shortcutName=attribs.shortcutName())) executables.append( cx_Executable(script_w, targetName=attribs.get_win_targetName(), base="Win32GUI", icon=icon, shortcutDir="ProgramMenuFolder", shortcutName=attribs.shortcutName())) package_data = {} esky_app_name = (attribs.get_name() + '-' + version + '.' + get_platform()) esky_dist_dir = os.path.join(OUTPUT_DIR, esky_app_name) freeze_options = dict( executables=executables, options={ "build": { "exe_command": "bdist_esky", }, "build_exe": { "includes": includes, "packages": packages + [ "nose", ], "excludes": excludes, "include_files": include_files, }, "bdist_esky": { "excludes": excludes, "enable_appdata_dir": True, "freezer_options": { "packages": packages + [ "nose", ], }, "rm_freeze_dir_after_zipping": False, }, "install": { "skip_sub_commands": "install_lib,install_scripts,install_data", }, "install_exe": { "skip_build": True, "build_dir": esky_dist_dir, }, "bdist_msi": { "add_to_path": True, "upgrade_code": '{800B7778-1B71-11E2-9D65-A0FD6088709B}', }, }, ) if sys.platform == 'darwin': # Under OSX we use py2app instead of cx_Freeze because we need: # - argv_emulation=True for nxdrive:// URL scheme handling # - easy Info.plist customization import py2app # install the py2app command name = attribs.get_CFBundleName() py2app_options = dict( iconfile=icon, argv_emulation=False, # We use QT for URL scheme handling plist=dict( CFBundleDisplayName=attribs.get_CFBundleDisplayName(), CFBundleName=attribs.get_CFBundleName(), CFBundleIdentifier=attribs.get_CFBundleIdentifier(), LSUIElement=True, # Do not launch as a Dock application CFBundleURLTypes=[ dict( CFBundleURLName=attribs.get_CFBundleURLName(), CFBundleURLSchemes=(attribs .get_CFBundleURLSchemes()), ) ] ), includes=includes, excludes=excludes, ) freeze_options = dict( app=attribs.get_app(), options=dict( py2app=py2app_options, bdist_esky=dict( enable_appdata_dir=True, create_zipfile=False, freezer_options=py2app_options, ) ) ) setup( name=name, version=version, description=attribs.get_description(), author=attribs.get_author(), author_email=attribs.get_author_email(), url=attribs.get_url(), packages=packages, package_dir=attribs.get_package_dir(), package_data=package_data, scripts=scripts, long_description=attribs.get_long_description(), data_files=data_files, **freeze_options ) if old_version is not None: update_version(init_file, old_version) print "Restored version to " + old_version
def _run_eskytester(self, options): """Build and run the eskytester app using the given distutils options. The "eskytester" application can be found next to this file, and the sequence of tests performed range across "script1.py" to "script3.py". """ olddir = os.path.abspath(os.curdir) # tdir = os.path.join(os.path.dirname(__file__),"DIST") # if os.path.exists(tdir): # really_rmtree(tdir) # os.mkdir(tdir) tdir = tempfile.mkdtemp() server = None script2 = None try: options.setdefault("build", {})["build_base"] = os.path.join(tdir, "build") options.setdefault("bdist", {})["dist_dir"] = os.path.join(tdir, "dist") # Set some callbacks to test that they work correctly options.setdefault("bdist_esky", {}).setdefault( "pre_freeze_callback", "esky.tests.test_esky.assert_freezedir_exists") options.setdefault("bdist_esky", {}).setdefault("pre_zip_callback", assert_freezedir_exists) options["bdist_esky"].setdefault("excludes", []).extend(["Tkinter", "tkinter"]) platform = get_platform() deploydir = "deploy.%s" % (platform, ) esky_root = dirname(dirname(dirname(__file__))) os.chdir(tdir) shutil.copytree( os.path.join(esky_root, "esky", "tests", "eskytester"), "eskytester") dir_util._path_created.clear() # Build three increasing versions of the test package. # Version 0.2 will include a bundled MSVCRT on win32. # Version 0.3 will be distributed as a patch. metadata = dict( name="eskytester", packages=["eskytester"], author="rfk", description="the esky test package", data_files=[("data", ["eskytester/datafile.txt"])], package_data={"eskytester": ["pkgdata.txt"]}, ) options2 = options.copy() options2["bdist_esky"] = options["bdist_esky"].copy() options2["bdist_esky"]["bundle_msvcrt"] = True script1 = "eskytester/script1.py" script2 = Executable([None, open("eskytester/script2.py")], name="script2") script3 = "eskytester/script3.py" dist_setup(version="0.1", scripts=[script1], options=options, script_args=["bdist_esky"], **metadata) dist_setup(version="0.2", scripts=[script1, script2], options=options2, script_args=["bdist_esky"], **metadata) dist_setup(version="0.3", scripts=[script2, script3], options=options, script_args=["bdist_esky_patch"], **metadata) os.unlink( os.path.join(tdir, "dist", "eskytester-0.3.%s.zip" % (platform, ))) # Check that the patches apply cleanly uzdir = os.path.join(tdir, "unzip") deep_extract_zipfile( os.path.join(tdir, "dist", "eskytester-0.1.%s.zip" % (platform, )), uzdir) with open( os.path.join( tdir, "dist", "eskytester-0.3.%s.from-0.1.patch" % (platform, )), "rb") as f: esky.patch.apply_patch(uzdir, f) really_rmtree(uzdir) deep_extract_zipfile( os.path.join(tdir, "dist", "eskytester-0.2.%s.zip" % (platform, )), uzdir) with open( os.path.join( tdir, "dist", "eskytester-0.3.%s.from-0.2.patch" % (platform, )), "rb") as f: esky.patch.apply_patch(uzdir, f) really_rmtree(uzdir) # Serve the updates at LOCAL_HTTP_PORT set in esky.util print "running local update server" try: server = HTTPServer(("localhost", LOCAL_HTTP_PORT), SimpleHTTPRequestHandler) except Exception: # in travis ci we start our own server pass else: server_thread = threading.Thread(target=server.serve_forever) server_thread.daemon = True server_thread.start() # Set up the deployed esky environment for the initial version zfname = os.path.join(tdir, "dist", "eskytester-0.1.%s.zip" % (platform, )) os.mkdir(deploydir) extract_zipfile(zfname, deploydir) # Run the scripts in order. if options["bdist_esky"]["freezer_module"] == "py2app": appdir = os.path.join(deploydir, os.listdir(deploydir)[0]) cmd1 = os.path.join(appdir, "Contents", "MacOS", "script1") cmd2 = os.path.join(appdir, "Contents", "MacOS", "script2") cmd3 = os.path.join(appdir, "Contents", "MacOS", "script3") else: appdir = deploydir if sys.platform == "win32": cmd1 = os.path.join(deploydir, "script1.exe") cmd2 = os.path.join(deploydir, "script2.exe") cmd3 = os.path.join(deploydir, "script3.exe") else: cmd1 = os.path.join(deploydir, "script1") cmd2 = os.path.join(deploydir, "script2") cmd3 = os.path.join(deploydir, "script3") print "spawning eskytester script1", options["bdist_esky"][ "freezer_module"] os.unlink( os.path.join(tdir, "dist", "eskytester-0.1.%s.zip" % (platform, ))) p = subprocess.Popen(cmd1) assert p.wait() == 0 os.unlink(os.path.join(appdir, "tests-completed")) print "spawning eskytester script2" os.unlink( os.path.join(tdir, "dist", "eskytester-0.2.%s.zip" % (platform, ))) p = subprocess.Popen(cmd2) assert p.wait() == 0 os.unlink(os.path.join(appdir, "tests-completed")) print "spawning eskytester script3" p = subprocess.Popen(cmd3) assert p.wait() == 0 os.unlink(os.path.join(appdir, "tests-completed")) finally: if script2: script2.script[1].close() os.chdir(olddir) if sys.platform == "win32": # wait for the cleanup-at-exit pocess to finish time.sleep(4) really_rmtree(tdir) if server: server.shutdown()
def __init__(self, driveAttributes): from distutils.core import setup attribs = driveAttributes freeze_options = {} ext_modules = [] script = attribs.get_script() scripts = attribs.get_scripts() name = attribs.get_name() packages = Packages(attribs.get_package_dirs()).load() # special handling for data files, except for Linux if ((sys.platform == "win32" or sys.platform == 'darwin') and 'nxdrive.data' in packages): packages.remove('nxdrive.data') package_data = attribs.get_package_data() icons_home = attribs.get_icons_home() ui5_home = attribs.get_ui5_home() win_icon = os.path.join(icons_home, attribs.get_win_icon()) png_icon = os.path.join(icons_home, attribs.get_png_icon()) osx_icon = os.path.join(icons_home, attribs.get_osx_icon()) if sys.platform == 'win32': icon = win_icon elif sys.platform == 'darwin': icon = osx_icon else: icon = png_icon # Files to include in frozen app # build_exe freeze with cx_Freeze (Windows) include_files = attribs.get_includes() # bdist_esky freeze with cx_Freeze (Windows) and py2app (OS X) # In fact this is a global setup option # TODO NXP-13810: check removed data_files from py2app and added to # global setup icon_files = data_file_dir(icons_home, 'icons', include_files).load() ui5_files = data_file_dir(ui5_home, 'ui5', include_files).load_recursive() data_files = [('icons', icon_files)] data_files.extend(ui5_files) data_files.extend(attribs.get_data_files()) old_version = None init_file = attribs.get_init_file() version = read_version(init_file) if '-dev' in version: # timestamp the dev artifacts as distutils only accepts "b" + digit timestamp = datetime.utcnow().isoformat() timestamp = timestamp.replace(":", "") timestamp = timestamp.replace(".", "") timestamp = timestamp.replace("T", "") timestamp = timestamp.replace("-", "") old_version = version # distutils imposes a max 3 levels integer version # (+ prerelease markers which are not allowed in a # msi package version). On the other hand, # msi imposes the a.b.c.0 or a.b.c.d format where # a, b, c and d are all 16 bits integers # TODO: align on latest distutils versioning month_day = timestamp[4:8] if month_day.startswith('0'): month_day = month_day[1:] version = version.replace('-dev', ".%s" % (month_day)) update_version(init_file, version) print "Updated version to " + version # Create JSON metadata file for the frozen application json_file = create_json_metadata(version, SERVER_MIN_VERSION) print "Created JSON metadata file for frozen app: " + json_file includes = [ "PyQt4", "PyQt4.QtCore", "PyQt4.QtNetwork", "PyQt4.QtGui", "atexit", # implicitly required by PyQt4 "cffi", "xattr" ] attribs.append_includes(includes) excludes = [ "ipdb", "clf", "IronPython", "pydoc", "tkinter", ] if '--freeze' in sys.argv: print "Building standalone executable..." sys.argv.remove('--freeze') from nx_cx_Freeze import setup from cx_Freeze import Executable as cx_Executable from esky.util import get_platform # build_exe does not seem to take the package_dir info into account sys.path.append(attribs.get_path_append()) executables = [cx_Executable(script)] freeze_options = dict() if sys.platform == "win32": # Windows GUI program that can be launched without a cmd # console script_w = attribs.get_win_script() if script_w is not None: scripts.append( es_Executable(script_w, icon=icon, shortcutDir="ProgramMenuFolder", shortcutName=attribs.shortcutName())) executables.append( cx_Executable(script_w, targetName=attribs.get_win_targetName(), base="Win32GUI", icon=icon, shortcutDir="ProgramMenuFolder", shortcutName=attribs.shortcutName())) freeze_options.update({'attribs': attribs}) package_data = {} esky_app_name = (attribs.get_name() + '-' + version + '.' + get_platform()) esky_dist_dir = os.path.join(OUTPUT_DIR, esky_app_name) freeze_options.update({ 'executables': executables, 'options': { "build": { "exe_command": "bdist_esky", }, "build_exe": { "includes": includes, "packages": packages + [ "nose", ], "excludes": excludes, "include_files": include_files, }, "bdist_esky": { "excludes": excludes, "enable_appdata_dir": True, "freezer_options": { "packages": packages + [ "nose", ], }, "rm_freeze_dir_after_zipping": False, }, "install": { "skip_sub_commands": "install_lib,install_scripts,install_data", }, "install_exe": { "skip_build": True, "build_dir": esky_dist_dir, }, "bdist_msi": { "add_to_path": True, "upgrade_code": attribs.get_uid(), }, }, }) # Include cffi compiled C extension under Linux if sys.platform.startswith('linux'): import xattr includeFiles = [(os.path.join(os.path.dirname(xattr.__file__), '_cffi__x7c9e2f59xb862c7dd.so'), '_cffi__x7c9e2f59xb862c7dd.so')] freeze_options['options']['bdist_esky'][ 'freezer_options'].update({"includeFiles": includeFiles}) if sys.platform == 'darwin': # Under OSX we use py2app instead of cx_Freeze because we need: # - argv_emulation=True for nxdrive:// URL scheme handling # - easy Info.plist customization import py2app # install the py2app command import xattr ext_modules = [xattr.lib.ffi.verifier.get_extension()] includes.append("_cffi__x7c9e2f59xb862c7dd") name = attribs.get_CFBundleName() py2app_options = dict( iconfile=icon, qt_plugins='imageformats', argv_emulation=False, # We use QT for URL scheme handling plist=dict( CFBundleDisplayName=attribs.get_CFBundleDisplayName(), CFBundleName=attribs.get_CFBundleName(), CFBundleIdentifier=attribs.get_CFBundleIdentifier(), LSUIElement=True, # Do not launch as a Dock application CFBundleURLTypes=[ dict( CFBundleURLName=attribs.get_CFBundleURLName(), CFBundleURLSchemes=( attribs.get_CFBundleURLSchemes()), ) ], NSServices=[ dict(NSMenuItem=dict( default=attribs.get_CFBundleDisplayName()), NSMessage=u"macRightClick", NSPortName=attribs.get_CFBundleDisplayName(), NSRequiredContext=dict(), NSSendTypes=[ u'NSStringPboardType', ], NSSendFileTypes=[u"public.item"]) ]), includes=includes, excludes=excludes, ) freeze_options = dict(app=attribs.get_app(), options=dict( py2app=py2app_options, bdist_esky=dict( enable_appdata_dir=True, create_zipfile=False, freezer_options=py2app_options, ))) setup(name=name, version=version, description=attribs.get_description(), author=attribs.get_author(), author_email=attribs.get_author_email(), url=attribs.get_url(), packages=packages, package_dir=attribs.get_package_dir(), package_data=package_data, scripts=scripts, long_description=attribs.get_long_description(), data_files=data_files, ext_modules=ext_modules, **freeze_options) if old_version is not None: update_version(init_file, old_version) print "Restored version to " + old_version