Skip to content

Commit

Permalink
Completed core support for Linux. Bumped version to 0.3.0.0.
Browse files Browse the repository at this point in the history
  • Loading branch information
BuvinJ committed Jan 14, 2019
1 parent 7fc3b1c commit f4200e8
Show file tree
Hide file tree
Showing 11 changed files with 216 additions and 80 deletions.
2 changes: 1 addition & 1 deletion distbuilder/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.2.0.1"
__version__ = "0.3.0.0"
47 changes: 38 additions & 9 deletions distbuilder/master.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,22 +112,47 @@ def __ifwPkgName( self ):
def __pkgSrcDirPath( self ):
if self.pkgSrcDirPath : return self.pkgSrcDirPath
return joinPath( THIS_DIR, self.binaryName )

# -----------------------------------------------------------------------------
class PyToBinInstallerProcess:

def __init__( self, configFactory,
def __init__( self, configFactory,
name="Python To Binary Installer Process",
isObfuscating=False,
isMovedToDesktop=False ) :
isDesktopTarget=False ) :
self.name = name
self.configFactory = configFactory
self.isObfuscating = isObfuscating
self.isMovedToDesktop = isMovedToDesktop
self.isDesktopTarget = isDesktopTarget
self.isTestingObfuscation = False
self.isTestingExe = False
self.isTestingInstall = False
self.isVerboseInstall = False

def __printHeader( self ):
try:
from distbuilder import __version__ as ver
libPath = modulePackagePath( "distbuilder" )
except:
ver = "?"
libPath = "?"
DIVIDER = "------------------------------------"
print( DIVIDER )
print( ">>> Distrbution Builder Process <<<" )
print( "" )
print( "Process Name: %s" % (self.name,) )
print( "" )
print( "Library Version: %s" % (ver,) )
print( "Library Path:\n%s" % (libPath,) )
print( "" )
print( "Python Translator:\n%s" % (sys.version,) )
print( "" )
print( "System Info:\n%s\n%s" % (platform.system(), platform.release()) )
print( DIVIDER )
print( "" )

def run( self ):
def run( self ):
self.__printHeader()

if self.isObfuscating :
opyConfig = self.configFactory.opyConfig()
Expand All @@ -139,22 +164,26 @@ def run( self ):
else: opyConfig = None

pyInstConfig = self.configFactory.pyInstallerConfig()
self.onPyInstConfig( pyInstConfig )
self.onPyInstConfig( pyInstConfig )
_, binPath = buildExecutable( pyInstConfig=pyInstConfig,
opyConfig=opyConfig )
if self.isTestingExe : run( binPath, isDebug=True )

ifwConfig = self.configFactory.qtIfwConfig()
self.onQtIfwConfig( ifwConfig )
setupPath = buildInstaller( ifwConfig, isPkgSrcRemoved=True )
if self.isMovedToDesktop :
if self.isDesktopTarget :
setupPath = moveToDesktop( setupPath )
if self.isTestingInstall :
run( setupPath,
QT_IFW_VERBOSE_SWITCH
if self.isVerboseInstall else None )
if self.isVerboseInstall else None )

self.__printFooter()

print( "\n\nDone!" )
def __printFooter( self ):
#TODO: add time elapsed...
print( "Done!" )

# Use these to further customize the build process once the
# ConfigFactory has produced each initial config object
Expand Down
33 changes: 31 additions & 2 deletions distbuilder/py_installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from distbuilder.util import * # @UnusedWildImport
from distbuilder.opy_library import obfuscatePy, OBFUS_DIR_PATH

PYINST_BIN_NAME = "pyinstaller"

SPEC_EXT = ".spec"

BUILD_DIR_PATH = absPath( "build" )
Expand All @@ -14,7 +16,31 @@ class PyInstallerConfig:
See PyInstaller docs for details on these settings.
"""
def __init__( self ) :
self.pyInstallerPath = util._pythonScriptsPath( "pyinstaller" )

# Find the "default" installation of pyInstaller.
# Fall back to using the system path if an absolute path is not found.
# Note, it is possible for a user to have multiple versions
# on their machine so the "first" one found in a blind search is
# not an advisable auto detection methed. The logic here is
# based primarily upon pyInstaller documentation.
# Note a user can assign a value to this attribute directly
# when this default fails to meet their needs.
if IS_WINDOWS :
# resolves multi-python version environments
p = util._pythonScriptsPath( PYINST_BIN_NAME )
elif IS_LINUX :
p = util._usrBinPath( PYINST_BIN_NAME )
if not exists( p ) :
p = util._userHiddenLocalBinDirPath( PYINST_BIN_NAME )
elif IS_MACOS :
p = util._usrBinPath( PYINST_BIN_NAME )
if not exists( p ) :
p = util._usrLocalBinPath( PYINST_BIN_NAME )
if not exists( p ) :
p = util._optLocalBinPath( PYINST_BIN_NAME )
else : p = None
self.pyInstallerPath = (
PYINST_BIN_NAME if p is None or not exists(p) else p)

self.name = None
self.entryPointPy = None
Expand Down Expand Up @@ -64,6 +90,8 @@ def toPyInstallerSrcDestSpec( pyInstArg, paths ):
binarySpec += toPyInstallerSrcDestSpec( "--add-binary", paths )

try:
# if the iconFilePath is a tuple or list,
# it represents an exe path and an icon index embedded within that
if( isinstance( self.iconFilePath, tuple ) or
isinstance( self.iconFilePath, list ) ):
if splitExt( self.iconFilePath[0] )[1]==".exe" :
Expand All @@ -72,7 +100,7 @@ def toPyInstallerSrcDestSpec( pyInstArg, paths ):
else : raise
else :
self.iconFilePath = ( splitExt( self.iconFilePath )[0] +
".ico" if IS_WINDOWS else ".icns" )
(".icns" if IS_MACOS else ".ico") )
except: self.iconFilePath = None
iconSpec = ( '--icon "%s"' % (self.iconFilePath,)
if self.iconFilePath else "" )
Expand All @@ -81,6 +109,7 @@ def toPyInstallerSrcDestSpec( pyInstArg, paths ):
versionSpec = ( '--version-file "%s"' % (self.versionFilePath,)
if self.versionFilePath else "" )
adminSwitch = "--uac-admin" if self.isAutoElevated else ""
else : versionSpec = adminSwitch = ""

tokens = (nameSpec, distSpec, oneFileSwitch,
windowedSwitch, adminSwitch, iconSpec, versionSpec,
Expand Down
26 changes: 22 additions & 4 deletions distbuilder/qt_installer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

BUILD_SETUP_DIR_PATH = absPath( "build_setup" )
INSTALLER_DIR_PATH = "installer"
DEFAULT_SETUP_NAME = "setup.exe"
DEFAULT_SETUP_NAME = util._normExeName( "setup" )
DEFAULT_QT_IFW_SCRIPT_NAME = "installscript.qs"

QT_IFW_VERBOSE_SWITCH = '-v'
Expand All @@ -17,7 +17,7 @@
QT_BIN_DIR_ENV_VAR = "QT_BIN_DIR"

__BIN_SUB_DIR = "bin"
__QT_INSTALL_CREATOR_EXE_NAME = "binarycreator.exe"
__QT_INSTALL_CREATOR_EXE_NAME = util._normExeName( "binarycreator" )

__QT_WINDOWS_DEPLOY_EXE_NAME = "windeployqt.exe"
__QT_WINDOWS_DEPLOY_QML_SWITCH = "--qmldir"
Expand Down Expand Up @@ -273,6 +273,22 @@ class QtIfwPackageScript:
"iconId=[ICON_ID]"
);
""" )

__X11_ADD_DESKTOP_ENTRY_TMPLT = (
"""
component.addOperation( "CreateDesktopEntry",
"/usr/share/applications/[APP_NAME].desktop",
"Version=1.0\nType=Application\nTerminal=false\nExec=@TargetDir@/[EXE_NAME]\nName=[APP_NAME]\nIcon=@TargetDir@[APP_ICON_PNG]\nName[en_US]=[APP_NAME]"
);
""" )

__X11_COPY_DESKTOP_ENTRY_TO_DESKTOP_TMPLT = (
"""
component.addElevatedOperation( "Copy",
"/usr/share/applications/[APP_NAME].desktop",
"@HomeDir@/Desktop/[APP_NAME].desktop"
);
""" )

__WIN_SHORTCUT_LOCATIONS = {
DESKTOP_WIN_SHORTCUT : "@DesktopDir@"
Expand Down Expand Up @@ -416,7 +432,8 @@ def __validateConfig( qtIfwConfig ):
def __initBuild( qtIfwConfig ) :
print( "Initializing installer build..." )
# remove any prior setup file
setupExePath = joinPath( THIS_DIR, qtIfwConfig.setupExeName )
setupExePath = joinPath( THIS_DIR,
util._normExeName( qtIfwConfig.setupExeName ) )
if exists( setupExePath ) : removeFile( setupExePath )
# create a "clean" build directory
if exists( BUILD_SETUP_DIR_PATH ) : removeDir( BUILD_SETUP_DIR_PATH )
Expand Down Expand Up @@ -495,7 +512,8 @@ def __build( qtIfwConfig ) :
print( "Building installer using Qt IFW...\n" )
qtUtilityPath = joinPath( qtIfwConfig.qtIfwDirPath,
joinPath( __BIN_SUB_DIR, __QT_INSTALL_CREATOR_EXE_NAME ) )
setupExePath = joinPath( THIS_DIR, qtIfwConfig.setupExeName )
setupExePath = joinPath( THIS_DIR,
util._normExeName( qtIfwConfig.setupExeName ) )
cmd = '%s %s "%s"' % ( qtUtilityPath, str(qtIfwConfig), setupExePath )
util._system( cmd )
if exists( setupExePath ) : print( "Created %s!" % (setupExePath,) )
Expand Down
99 changes: 70 additions & 29 deletions distbuilder/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from os.path import exists, isfile as isFile, \
dirname as dirPath, normpath, realpath, relpath, \
join as joinPath, split as splitPath, splitext as splitExt, \
expanduser, \
basename, pathsep # @UnusedImport
from shutil import rmtree as removeDir, move, make_archive, \
copytree as copyDir, copyfile as copyFile # @UnusedImport
Expand All @@ -17,38 +18,51 @@
from distutils.sysconfig import get_python_lib
import inspect # @UnusedImport

# -----------------------------------------------------------------------------
IS_WINDOWS = platform.system() == "Windows"
THIS_DIR = dirPath( realpath( argv[0] ) )
IS_LINUX = platform.system() == "Linux"
IS_MACOS = platform.system() == "Darwin"

PY_EXT = ".py"
PY_DIR = dirPath( PYTHON_PATH )
PY_SCRIPTS_DIR = joinPath( PY_DIR, "Scripts" )
SITE_PACKAGES_PATH = get_python_lib()
PY_EXT = ".py"

USER_BIN_DIR = "/usr/bin"
USER_LOCAL_BIN_DIR = "/usr/local/bin"
OPT_LOCAL_BIN_DIR = "/opt/local/bin"

DESKTOP_DIR_NAME = "Desktop"
THIS_DIR = dirPath( realpath( argv[0] ) )

__IMPORT_TMPLT = "import %s"
__FROM_IMPORT_TMPLT = "from %s import %s"
__GET_MOD_PATH_TMPLT = "inspect.getfile( %s )"


__NOT_SUPPORTED_MSG = ( "Sorry this operation is not supported " +
"this for this platform!" )

__CSIDL_DESKTOP_DIRECTORY = 16

# -----------------------------------------------------------------------------
def isDir( path ): return exists(path) and not isFile(path)

# absolute path relative to the script directory NOT the working directory
def absPath( relativePath ):
return normpath( joinPath( THIS_DIR, relativePath ) )

def _pythonPath( relativePath ):
return normpath( joinPath( PY_DIR, relativePath ) )

def _pythonScriptsPath( relativePath ):
return normpath( joinPath( PY_SCRIPTS_DIR, relativePath ) )

def tempDirPath(): return gettempdir()

# -----------------------------------------------------------------------------
def run( binPath, args=[], isDebug=False ):
wrkDir, fileName = splitPath( binPath )
# -----------------------------------------------------------------------------
def run( binPath, args=[],
wrkDir=None, isElevated=False, isDebug=False ):
# TODO: finish isElevated logic (for windows, in debug mode...)
binDir, fileName = splitPath( binPath )
if wrkDir is None : wrkDir = binDir
if isDebug :
cmdList = [binPath]
if isinstance(args,list): cmdList.extend( args )
else: cmdList.append( args )
elif args is not None: cmdList.append( args )
print( 'cd "%s"' % (wrkDir,) )
print( list2cmdline(cmdList) )
p = Popen( cmdList, cwd=wrkDir, shell=False,
Expand All @@ -60,13 +74,18 @@ def run( binPath, args=[], isDebug=False ):
stdout.write( "\nReturn code: %d\n" % (p.returncode,) )
stdout.flush()
else :
if isinstance(args,list): args = list2cmdline(args)
_system( '%s %s' % (fileName, args), wrkDir )
if isinstance(args,list): args = list2cmdline(args)
elif args is None: args=""
elevate = "" if not isElevated or IS_WINDOWS else "sudo"
pwdCmd = "" if IS_WINDOWS else "./"
cmd = ('%s %s%s %s' % (elevate, pwdCmd, fileName, args)).strip()
_system( cmd, wrkDir )

def runPy( pyPath, args=[] ):
def runPy( pyPath, args=[], isElevated=False ):
wrkDir, fileName = splitPath( pyPath )
if isinstance(args,list): args = list2cmdline(args)
_system( '%s %s %s' % (PYTHON_PATH, fileName, args), wrkDir )
pyArgs = [fileName]
if isinstance(args,list): pyArgs.extend( args )
run( PYTHON_PATH, pyArgs, wrkDir, isElevated, isDebug=False )

def _system( cmd, wrkDir=None ):
if wrkDir is not None:
Expand Down Expand Up @@ -120,11 +139,12 @@ def toZipFile( sourceDir, zipDest=None, removeScr=True ):
return filePath

def moveToDesktop( path ):
destPath = joinPath( _userDesktopDirPath(),
desktopDir = _userDesktopDirPath()
destPath = joinPath( desktopDir,
basename( normpath(path) ) )
if isFile( destPath ): removeFile( destPath )
elif isDir( destPath ): removeDir( destPath )
move( path, _userDesktopDirPath() )
move( path, desktopDir )
print( 'Moved "%s" to "%s"' % (path, destPath) )
return destPath

Expand All @@ -146,6 +166,26 @@ def printExc( e, isDetailed=False, isFatal=False ):
else : printErr( e )
if isFatal: exit(1)

# -----------------------------------------------------------------------------
def _pythonPath( relativePath ):
return normpath( joinPath( PY_DIR, relativePath ) )

def _pythonScriptsPath( relativePath ):
return normpath( joinPath( PY_SCRIPTS_DIR, relativePath ) )

def _usrBinPath( relativePath ):
return normpath( joinPath( USER_BIN_DIR, relativePath ) )

def _usrLocalBinPath( relativePath ):
return normpath( joinPath( USER_LOCAL_BIN_DIR, relativePath ) )

def _optLocalBinPath( relativePath ):
return normpath( joinPath( OPT_LOCAL_BIN_DIR, relativePath ) )

def _userHiddenLocalBinDirPath( relativePath ) :
return normpath( joinPath( "%s/.local/bin" % (_userDirPath(),),
relativePath ) )

# -----------------------------------------------------------------------------
def _toSrcDestPair( pathPair, destDir=None ):
''' "Protected" function for internal library uses only '''
Expand Down Expand Up @@ -182,14 +222,15 @@ def _toSrcDestPair( pathPair, destDir=None ):
return (src, dest)

# -----------------------------------------------------------------------------
__CSIDL_DESKTOP_DIRECTORY = 16

def _userDirPath(): return expanduser('~')

def _userDesktopDirPath():
if not IS_WINDOWS :
raise Exception(
"Sorry this library does not yet support " +
"this function on this platform!" )
return __getFolderPathByCSIDL( __CSIDL_DESKTOP_DIRECTORY )
if IS_WINDOWS :
return __getFolderPathByCSIDL( __CSIDL_DESKTOP_DIRECTORY )
elif IS_LINUX :
return normpath( joinPath( _userDirPath(), DESKTOP_DIR_NAME ) )
raise Exception( __NOT_SUPPORTED_MSG )

def __getFolderPathByCSIDL( csidl ):
import ctypes.wintypes
Expand All @@ -205,10 +246,10 @@ def __importByStr( moduleName, memberName=None ):
else: exec( __FROM_IMPORT_TMPLT % (moduleName, memberName) )
except Exception as e: printExc( e )

def _normExeName( exeName ):
def _normExeName( exeName ):
base, ext = splitExt( basename( exeName ) )
if IS_WINDOWS:
if ext == "": ext = "exe"
return base + "." + ext
if ext=="": ext="exe"
return base + "." + ext
return base

0 comments on commit f4200e8

Please sign in to comment.