--- a/setup.py Mon Apr 15 19:53:29 2019 +0200 +++ b/setup.py Tue Apr 16 19:43:53 2019 +0200 @@ -4,11 +4,17 @@ # Copyright (c) 2019 Detlev Offenbach <detlev@die-offenbachs.de> # +""" +Module to prepare a distribution package for uploading to PyPI. +""" + from __future__ import unicode_literals import os import sys import subprocess +import shutil +import fnmatch from setuptools import setup, find_packages from distutils.command.install_data import install_data @@ -25,9 +31,15 @@ @rtype str """ version = "<unknown>" - with open(os.path.join(os.path.dirname(__file__), "VERSION"), - encoding="ASCII") as f: - version = f.read().strip() + if sys.argv[-1].startswith(("1", "2")): + # assume it is a version info starting with year + version = sys.argv[-1] + del sys.argv[-1] + else: + # calculate according our version scheme (year.month) + import datetime + today = datetime.date.today() + version = "{0}.{1}".format(today.year - 2000, today.month) return version @@ -65,9 +77,10 @@ 'eric6/icons/default/eric.png', 'eric6/icons/default/ericWeb48.png' ]), - ('share/metainfo', ['linux/eric6.appdata.xml']) + ('share/appdata', ['linux/eric6.appdata.xml']), + ('share/metainfo', ['linux/eric6.appdata.xml']), ] - elif os.name == 'nt': + elif sys.platform.startswith(("win", "cygwin")): dataFiles = [ ('scripts', [ 'eric6/pixmaps/eric6.ico', @@ -81,26 +94,148 @@ ## make Linux detect eric6 desktop files ###################################################################### -class Eric6InstallData(install_data): +class Eric6InstallDataWrapper(install_data): + """ + Class providing an install_data command wrapper to perform + post-installation tasks. + """ def run(self): + """ + Public method to perform the data installation. + """ + # do the distutils install_data first install_data.run(self) + + # now perform our post installation stuff if sys.platform.startswith('linux'): try: subprocess.call(['update-desktop-database']) except: print("ERROR: unable to update desktop database", file=sys.stderr) + CmdClass = { - 'install_data': Eric6InstallData, + 'install_data': Eric6InstallDataWrapper, } ###################################################################### +## functions to prepare the sources for building +###################################################################### + +def prepareInfoFile(fileName, version): + """ + Function to prepare an Info.py file when installing from source. + + @param fileName name of the Python file containing the info (string) + @param version version string for the package (string) + """ + if not fileName: + return + + try: + os.rename(fileName, fileName + ".orig") + except EnvironmentError: + pass + try: + hgOut = subprocess.check_output(["hg", "identify", "-i"]) + if sys.version_info[0] == 3: + hgOut = hgOut.decode() + except (OSError, subprocess.CalledProcessError): + hgOut = "" + if hgOut: + hgOut = hgOut.strip() + if hgOut.endswith("+"): + hgOut = hgOut[:-1] + f = open(fileName + ".orig", "r", encoding="utf-8") + text = f.read() + f.close() + text = text.replace("@@REVISION@@", hgOut)\ + .replace("@@VERSION@@", version) + f = open(fileName, "w") + f.write(text) + f.close() + else: + shutil.copy(fileName + ".orig", fileName) + + +def cleanupSource(dirName): + """ + Cleanup the sources directory to get rid of leftover files + and directories. + + @param dirName name of the directory to prune (string) + """ + # step 1: delete all Ui_*.py files without a corresponding + # *.ui file + dirListing = os.listdir(dirName) + for formName, sourceName in [ + (f.replace('Ui_', "").replace(".py", ".ui"), f) + for f in dirListing if fnmatch.fnmatch(f, "Ui_*.py")]: + if not os.path.exists(os.path.join(dirName, formName)): + os.remove(os.path.join(dirName, sourceName)) + if os.path.exists(os.path.join(dirName, sourceName + "c")): + os.remove(os.path.join(dirName, sourceName + "c")) + + # step 2: delete the __pycache__ directory and all remaining *.pyc files + if os.path.exists(os.path.join(dirName, "__pycache__")): + shutil.rmtree(os.path.join(dirName, "__pycache__")) + for name in [f for f in os.listdir(dirName) + if fnmatch.fnmatch(f, "*.pyc")]: + os.remove(os.path.join(dirName, name)) + + # step 3: delete *.orig files + for name in [f for f in os.listdir(dirName) + if fnmatch.fnmatch(f, "*.orig")]: + os.remove(os.path.join(dirName, name)) + + # step 4: descent into subdirectories and delete them if empty + for name in os.listdir(dirName): + name = os.path.join(dirName, name) + if os.path.isdir(name): + cleanupSource(name) + if len(os.listdir(name)) == 0: + os.rmdir(name) + + +def __pyName(py_dir, py_file): + """ + Local function to create the Python source file name for the compiled + .ui file. + + @param py_dir suggested name of the directory (string) + @param py_file suggested name for the compile source file (string) + @return tuple of directory name (string) and source file name (string) + """ + return py_dir, "Ui_{0}".format(py_file) + + +def compileUiFiles(dirName): + """ + Compile the .ui files to Python sources. + + @param dirName name of the directory to compile UI files for (string) + """ + from PyQt5.uic import compileUiDir + compileUiDir(dirName, True, __pyName) + +###################################################################### ## setup() below ###################################################################### +Version = getVersion() +sourceDir = os.path.join(os.path.dirname(__file__), "eric6") +infoFileName = os.path.join(sourceDir, "UI", "Info.py") +if sys.argv[1].startswith("bdist"): + # prepare the sources under "eric6" for building the wheel file + print("preparing the sources...") + cleanupSource(sourceDir) + compileUiFiles(sourceDir) + prepareInfoFile(infoFileName, Version) + print("Preparation finished") + setup( name="eric6", - version=getVersion(), + version=Version, description="eric6 is an integrated development environment for the" " Python language.", long_description="eric6 is an integrated development environment for the" @@ -148,18 +283,18 @@ "pip", "docutils", "Markdown", + "pywin32>=1.0;platform_system=='Windows'", ], data_files=getDataFiles(), packages=find_packages(), -# include_package_data=True, zip_safe=False, package_data={ "": getPackageData( "eric6", [".png", ".svg", ".svgz", ".xpm", ".ico", ".gif", ".icns", ".txt", ".style", ".tmpl", ".html", ".qch", ".css", ".qss", ".e4h", - ".e6h", ".api", ".bas" ".dat"]) + - ["i18n/eric6_de.qm", "i18n/eric6_en.qm", "i18n/eric6_es.qm", + ".e6h", ".api", ".bas" ".dat"] + ) + ["i18n/eric6_de.qm", "i18n/eric6_en.qm", "i18n/eric6_es.qm", "i18n/eric6_ru.qm", ] }, @@ -190,7 +325,15 @@ "console_scripts":[ "eric6_api = eric6.eric6_api:main", "eric6_doc = eric6.eric6_doc:main", + "eric6_post_install = eric6.eric6_post_install:main" ], }, cmdclass=CmdClass, ) + +if os.path.exists(infoFileName + ".orig"): + try: + os.remove(infoFileName) + os.rename(infoFileName + ".orig", infoFileName) + except EnvironmentError: + pass