def osDependentPreparation(): config = Project.Config() binarycreator_path = config['qtifw']['binarycreator_path'] if os.path.exists(binarycreator_path): return () os_name = config['os']['name'] message = "prepare for os '{0}'".format(os_name) if os_name == 'osx': try: Functions.attachDmg(config['qtifw']['setup']['download_path']) except Exception as exception: BasicFunctions.printFailMessage(message, exception) sys.exit() else: BasicFunctions.printSuccessMessage(message) elif os_name == 'linux': try: Functions.setEnvVariable("QT_QPA_PLATFORM", "minimal") Functions.addReadPermission(config['qtifw']['setup']['exe_path']) except Exception as exception: BasicFunctions.printFailMessage(message, exception) sys.exit() else: BasicFunctions.printSuccessMessage(message) else: message = "* No preparation needed for os '{0}'".format(os_name) print(message)
def createInstallerSourceDir(): message = "create installer source directory" try: config = Project.Config() Functions.createFile(path=config['installer']['config_xml_path'], content=installerConfigXml()) Functions.copyFile( source=config['installer']['config_control_script']['path'], destination=config['installer']['config_dir_path']) Functions.createFile(path=config['installer']['package_xml_path'], content=installerPackageXml()) Functions.copyFile( source=config['installer']['package_install_script']['path'], destination=config['installer']['packages_meta_path']) Functions.copyFile( source=config['app']['license']['file_path'], destination=config['installer']['packages_meta_path']) Functions.createDir(config['installer']['packages_data_path']) Functions.moveDir( source=config['app']['freezed']['path'], destination=config['installer']['packages_data_path']) Functions.moveDir( source=config['project']['subdirs']['examples']['path'], destination=config['installer']['packages_data_path']) except Exception as exception: BasicFunctions.printFailMessage(message, exception) sys.exit() else: BasicFunctions.printSuccessMessage(message)
def osDependentDeploy(): config = Project.Config() os_name = config['os']['name'] project_dir_path = config['project']['dir_path'] branch = BasicFunctions.environmentVariable('TRAVIS_BRANCH') if os_name == 'linux': if branch == 'develop' or branch == 'examples': snapcraft_dir_name = '.snapcraft' docker_image = 'cibuilds/snapcraft:core18' downloaded_image_path = '.soft/snap.tar.gz' createSnapcraftDir(snapcraft_dir_name) decryptCertificates() extractCertificates() moveCertificates(snapcraft_dir_name) saveDockerImage(docker_image, downloaded_image_path) loadDockerImage(downloaded_image_path) runDockerImage(docker_image, project_dir_path, branch) else: message = "* No deployment for branch '{}' is implemented".format( branch) print(message) else: message = "* No deployment for '{}' App Store is implemented".format( os_name) print(message)
def _updateVersionAndDate(self, content): config = Project.Config() version = config.getVal('release', 'version') date = config.getVal('release', 'date') out = re.sub(r'Version \d+\.\d+\.\d+ \(\d{1,2} \w{3} \d{4}\)', 'Version {0} ({1})'.format(version, date), content) out = re.sub(r'v\d+\.\d+\.\d+', 'v{0}'.format(version), out) return out
def installerConfigXml(): message = "create config.xml content" try: config = Project.Config() os_name = config['os']['name'] app_name = config['app']['name'] if os_name == 'osx': target_dir = '/Applications/{0}'.format( app_name ) # macOS returns $HOME/Applications instead of /Applications for @ApplicationsDir@: https://bugreports.qt.io/browse/QTIFW-1011 elif os_name == 'windows': target_dir = '@ApplicationsDir@\\{0}'.format(app_name) elif os_name == 'linux': target_dir = '@ApplicationsDir@/{0}'.format(app_name) else: BasicFunctions.printFailMessage( "Unsupported os '{0}'".format(os_name)) sys.exit() pydict = { 'Installer': { 'Name': config['app']['name'], 'Version': config['release']['version'], 'Title': config['app']['name'], 'Publisher': config['app']['name'], 'ProductUrl': config['app']['url'], #'Logo': 'logo.png', #'WizardStyle': 'Classic',#'Aero', 'StartMenuDir': config['app']['name'], 'TargetDir': target_dir, 'MaintenanceToolName': '{0}{1}'.format(config['app']['name'], 'Uninstaller'), 'AllowNonAsciiCharacters': 'true', 'AllowSpaceInPath': 'true', 'InstallActionColumnVisible': 'false', 'ControlScript': config['installer']['config_control_script']['name'], } } raw_xml = Functions.dict2xml(pydict) pretty_xml = raw_xml #xml.dom.minidom.parseString(raw_xml).toprettyxml() #raw_xml = html.fromstring(raw_xml) #raw_xml = etree.tostring(raw_xml, xml_declaration=False, encoding='unicode', pretty_print=True)#.decode() except Exception as exception: BasicFunctions.printFailMessage(message, exception) sys.exit() else: BasicFunctions.printSuccessMessage(message) return pretty_xml
def downloadQtInstallerFramework(): config = Project.Config() download_path = config['qtifw']['setup']['download_path'] if os.path.exists(download_path): message = "* QtInstallerFramework was already downloaded to {}".format( download_path) print(message) return () message = "download QtInstallerFramework" try: config = Project.Config() Functions.downloadFile( url=config['qtifw']['setup']['download_url'], destination=config['qtifw']['setup']['download_path']) except Exception as exception: BasicFunctions.printFailMessage(message, exception) sys.exit() else: BasicFunctions.printSuccessMessage(message)
def createInstallerFile(): message = "create installer file" try: config = Project.Config() BasicFunctions.run(config['qtifw']['binarycreator_path'], '--verbose', '--offline-only', '-c', config['installer']['config_xml_path'], '-p', config['installer']['packages_dir_path'], '-t', config['qtifw']['installerbase_path'], config['app']['installer']['exe_path']) except Exception as exception: BasicFunctions.printFailMessage(message, exception) sys.exit() else: BasicFunctions.printSuccessMessage(message)
def fixDictdifferNumpy(): from_str = " LIST_TYPES += (numpy.ndarray, )" to_str = (from_str + os.linesep + os.linesep + "#Temporary fix for PyInstaller assuming numpy is installed" + os.linesep + "HAS_NUMPY = True" + os.linesep + "import numpy" + os.linesep + "LIST_TYPES += (numpy.ndarray, )") import Project config = Project.Config() dictdiffer_init_py_path = os.path.join( config['pyinstaller']['lib_path']['dictdiffer'], '__init__.py') with open(dictdiffer_init_py_path, 'r') as file: filedata = file.read() filedata = filedata.replace(from_str, to_str) with open(dictdiffer_init_py_path, 'w') as file: file.write(filedata)
def installerPackageXml(): message = "create package.xml content" try: config = Project.Config() pydict = { 'Package': { 'DisplayName': config['app']['name'], 'Description': config['app']['description'], 'Version': config['release']['version'], 'ReleaseDate': datetime.datetime.strptime(config['release']['date'], "%d %b %Y").strftime("%Y-%m-%d"), 'Default': 'true', 'Essential': 'true', 'ForcedInstallation': 'true', #'RequiresAdminRights': 'true', 'Licenses': '_LICENCE_STR', #{ # 'License': { # 'name': "GNU Lesser General Public License v3.0", # 'file': "LICENSE" # } ## <License name="GNU Lesser General Public License v3.0" file="LICENSE" /> # SHOULD BE IN THIS FORMAT #}, 'Script': config['installer']['package_install_script']['name'], } } raw_xml = Functions.dict2xml(pydict) pretty_xml = raw_xml # xml.dom.minidom.parseString(raw_xml).toprettyxml() #pretty_xml = xml.dom.minidom.parseString(raw_xml).toprettyxml() pretty_xml = pretty_xml.replace( '_LICENCE_STR', '<License name="GNU Lesser General Public License v3.0" file="LICENSE" />' ) except Exception as exception: BasicFunctions.printFailMessage(message, exception) sys.exit() else: BasicFunctions.printSuccessMessage(message) return pretty_xml
def createExamplesResource(): message = "create examples resource file" try: config = Project.Config() project_dir_path = config['project']['dir_path'] BasicFunctions.run( 'pyside2-rcc', '{0}/App/Examples.qrc'.format(project_dir_path), '-o', '{0}/App/Examples.py'.format(project_dir_path), # Write output to file rather than stdout '-no-compress' # Disable all compression ) except Exception as exception: BasicFunctions.printFailMessage(message, exception) sys.exit() else: BasicFunctions.printSuccessMessage(message)
def freezeApp(): message = "freeze app" try: config = Project.Config() os_name = config['os']['name'] app_name = config['app']['name'] project_name = config['project']['name'] project_dir_path = config['project']['dir_path'] distribution_dir_path = config['project']['subdirs']['distribution'][ 'path'] cryspy_path = config['pyinstaller']['lib_path']['cryspy'] easyInterface_path = config['pyinstaller']['lib_path']['easyInterface'] icon_ext = config['app']['icon']['ext'][os_name] separator = config['pyinstaller']['separator'][os_name] BasicFunctions.run( 'pyinstaller', '{0}/App/{1}.py'.format(project_dir_path, project_name), '--name', project_name, # Name to assign to the bundled app and spec file (default: first script’s basename) '--noconfirm', # Replace output directory (default: SPECPATH/dist/SPECNAME) without asking for confirmation '--clean', # Clean PyInstaller cache and remove temporary files before building. '--windowed', # Windows and Mac OS X: do not provide a console window for standard i/o. '--onedir', # Create a one-folder bundle containing an executable (default) '--log-level', 'WARN', # LEVEL may be one of DEBUG, INFO, WARN, ERROR, CRITICAL (default: INFO). '--distpath', "{0}".format(distribution_dir_path ), # Where to put the bundled app (default: ./dist) '--workpath', os.path.join( distribution_dir_path, 'FreezeAppTmp' ), # Where to put all the temporary work files, .log, .pyz and etc. (default: ./build) '--add-data', "{0}{1}cryspy".format(cryspy_path, separator), # Add CrysPy library '--add-data', "{0}/App{1}.".format( project_dir_path, separator), # Add App Pythnon and QML source files '--icon', '{0}/App/QmlImports/{1}/Resources/Icons/App.{2}'.format( project_dir_path, project_name, icon_ext)) except Exception as exception: BasicFunctions.printFailMessage(message, exception) sys.exit() else: BasicFunctions.printSuccessMessage(message)
def installQtInstallerFramework(): config = Project.Config() dir_path = config['qtifw']['dir_path'] bin_dir_path = config['qtifw']['bin_dir_path'] if os.path.exists(bin_dir_path): message = "* QtInstallerFramework was already installed to {}".format( bin_dir_path) print(message) return () message = "install QtInstallerFramework to '{}'".format(dir_path) try: Functions.installSilently( installer=config['qtifw']['setup']['exe_path'], silent_script=config['scripts']['silent_install']) except Exception as exception: BasicFunctions.printFailMessage(message, exception) sys.exit() else: BasicFunctions.printSuccessMessage(message)
def osDependentAddons(): config = Project.Config() os_name = config['os']['name'] app_name = config['app']['name'] distribution_dir_path = config['project']['subdirs']['distribution'][ 'path'] if os_name == 'osx': message = "add hidpi support ({0})".format(os_name) try: BasicFunctions.run( 'plutil', '-insert', 'NSHighResolutionCapable', '-bool', 'YES', '{0}/{1}.app/Contents/Info.plist'.format( distribution_dir_path, app_name)) except Exception as exception: BasicFunctions.printFailMessage(message, exception) sys.exit() else: BasicFunctions.printSuccessMessage(message) elif os_name == 'linux': message = "copy missing EGL and GLX plugins ({0})".format(os_name) try: missing_plugins = config['pyinstaller']['missing_plugins'][os_name] pyside2_path = config['pyinstaller']['lib_path']['pyside2'] app_plugins_path = os.path.join(distribution_dir_path, app_name, 'PySide2', 'plugins') for relative_dir_path in missing_plugins: src_dir_name = os.path.basename(relative_dir_path) src_dir_path = os.path.join(pyside2_path, relative_dir_path) dst_dir_path = os.path.join(app_plugins_path, src_dir_name) print("< src:", src_dir_path) print("> dst:", app_plugins_path) dir_util.copy_tree(src_dir_path, dst_dir_path) except Exception as exception: BasicFunctions.printFailMessage(message, exception) sys.exit() else: BasicFunctions.printSuccessMessage(message) else: message = "* No addons needed for os '{0}'".format(os_name) print(message)
# MAIN if __name__ == "__main__": BasicFunctions.printTitle('Deploy to GitHub releases') # Exit if pull request pull_request = BasicFunctions.environmentVariable('TRAVIS_PULL_REQUEST') if pull_request != 'false': print("* Deployment not needed. It's a pull request No. '{}'".format( pull_request)) exit() # Load config config = Project.Config() # Init github communication owner = config.getVal('github', 'owner') repo = config.getVal('github', 'repo') token = BasicFunctions.environmentVariable('GITHUB_TOKEN') #token = BasicFunctions.environmentVariable('GITHUB_TOKEN', default='...') github = GithubAgent(owner=owner, repo=repo, token=token) # Create release config version = config.getVal('release', 'version') date = config.getVal('release', 'date') changes = config.getVal('release', 'changes') branch = BasicFunctions.environmentVariable('TRAVIS_BRANCH') #branch = BasicFunctions.environmentVariable('TRAVIS_BRANCH', default='upload-artifacts') release = ReleaseConfig(version=version,