import tarfile
-import os.path
+import os
import sys
import logging
import io
-import pathlib
+import json
+import fnmatch
# Setup logger's output
FORMAT = '%(funcName)s():%(lineno)s: %(message)s'
logging.basicConfig(format=FORMAT, level=logging.DEBUG)
logger = logging.getLogger()
-"""Salome Extension Directory inside any extension's archive"""
+'''Salome Extension Directory inside any extension's archive'''
salomeExtDir = '__SALOME_EXT__'
-salomexcName = 'salomexc'
+arcFileNameExt = 'salomex'
+bFileNameExt = 'salomexb'
+cFileNameExt = 'salomexc'
+dFileNameExt = 'salomexd'
+
+extNameKey = 'name'
+extDescrKey = 'descr'
+extDependsOnKey = 'dependsOn'
+extAuthorKey = 'author'
+extComponentsKey = 'components'
+
+
+def createSalomexdFile(name, descr = '', dependsOn = [], author = '', components = []):
+ '''
+ Create a basic salomexd file from provided args.
+ '''
+
+ logger.debug('Create salomexd file...')
+
+ jsonString = json.dumps(
+ {
+ extNameKey: name,
+ extDescrKey: descr,
+ extDependsOnKey: dependsOn,
+ extAuthorKey: author,
+ extComponentsKey: components
+ },
+ indent = 4
+ )
-def listFilesAbs(dirPath):
- """
- Returns the recursive list of absolut paths to files (as pathlib.Path objects)
- in the dirPath root directory and all subdirectories.
- """
+ try:
+ with open(name + '.' + dFileNameExt, "w") as file:
+ file.write(jsonString)
+
+ except Exception:
+ import traceback
+ logger.error(traceback.format_exc())
+
+
+def createSalomexbFile(name, included):
+ '''
+ Create a salomexb file from a list of included file names.
+ For example:
+ */*.py
+ doc/*.html
+ doc/*.jp
+ '''
+
+ logger.debug('Create salomexb file...')
+
+ try:
+ with open(name + '.' + bFileNameExt, "w") as file:
+ file.write('\n'.join(included[0:]))
- files = []
+ except Exception:
+ import traceback
+ logger.error(traceback.format_exc())
+
+
+def readSalomexbFile(filePath):
+ '''
+ Returns a content af a salomexb file as a list of strings
+ '''
+
+ logger.debug('Read salomexb file %s', filePath)
+
+ try:
+ with open(filePath, 'r', encoding='UTF-8') as file:
+ return [line.rstrip() for line in file]
+
+ except Exception:
+ import traceback
+ logger.error(traceback.format_exc())
+ return []
- for path in pathlib.Path(dirPath).iterdir():
- if path.is_file():
- files.append(path)
- else:
- files += listFilesAbs(path)
- return files
+def readJsonFile(filePath):
+ '''
+ Returns a content af a json file as a dictionary
+ '''
+
+ logger.debug('Read json file %s', filePath)
+
+ try:
+ with open(filePath) as jsonFile:
+ return json.load(jsonFile)
+
+ except Exception:
+ import traceback
+ logger.error(traceback.format_exc())
+ return {}
+
def listFilesRel(dirPath):
- """
- Returns the recursive list of relative paths to files (as pathlib.Path objects)
+ '''
+ Returns the recursive list of relative paths to files as strings
in the dirPath root directory and all subdirectories.
- """
+ '''
- filesAbs = listFilesAbs(dirPath)
- return [file.relative_to(dirPath) for file in filesAbs]
+ filesList = []
+ for root, dirs, files in os.walk(dirPath):
+ for file in files:
+ filesList += os.path.relpath(os.path.join(root, file), dirPath)
-def listFiles(dirPath, isRel = True):
- """
- Returns the recursive list of paths to files (as a list of strings)
- in the dirPath root directory and all subdirectories.
- """
+ return filesList
- pathList = listFilesRel(dirPath) if isRel else listFilesAbs(dirPath)
- return [str(path) for path in pathList]
def fileListToNewLineStr(fileList):
- """
+ '''
Returns the list of paths as a newline separated string
- """
+ '''
return '\n'.join(file for file in fileList)
-def salomeExtFromInstallDir(sourceDirPath, extName = ''):
- """
+
+def createSalomexFile(sourceDirPath, salomexbPath, salomexdPath):
+ '''
Makes salome extension archive from a classic module install directory
- """
+ '''
+
+ logger.debug('Starting create an salome extension file')
+
+ if sourceDirPath == '':
+ logger.error('sourceDirPath argument cannot be empty!')
+ return
- logger.debug('salomeExtFromInstallDir() call')
+ extName = ''
+
+ # Try to get info from salomexd file
+ salomexdContent = readJsonFile(salomexdPath)
+ if extNameKey in salomexdContent and salomexdContent[extNameKey]:
+ extName = salomexdContent[extNameKey]
- sourceDirName = os.path.basename(sourceDirPath)
if extName == '':
- extName = sourceDirName
+ extName = os.path.basename(sourceDirPath)
try:
- with tarfile.open(extName, "w:gz") as ext:
- ext.add(sourceDirPath, salomeExtDir)
+ with tarfile.open(extName + '.' + arcFileNameExt, "w:gz") as ext:
+ # Write all included files to the extension's dir
+
+ # Get the file's matching pattern in the first place
+ includedFilesPattern = readSalomexbFile(salomexbPath)
+ if not includedFilesPattern:
+ # We don't have any pattern, so include all the files
+ includedFilesPattern = ['*']
+
+ logger.debug('Included files pattern: %s', includedFilesPattern)
+
+ # List of the files those actually written to the archive.
+ # It goes to the salomexc file then.
+ files = []
+
+ def fileFilter(tarinfo):
+ logger.debug('File name: %s', tarinfo.name)
- # Write control file - list of files inside extension's dir
- files = listFiles(sourceDirPath)
+ # Skip dir itself, otherwise it excludes all the files inside
+ if tarinfo.isdir():
+ return tarinfo
+
+ for f in includedFilesPattern:
+ if fnmatch.fnmatch(tarinfo.name, f):
+ logger.debug('File name %s matches pattern %s', tarinfo.name, f)
+ files.append(tarinfo.name)
+ return tarinfo
+
+ return None
+
+ ext.add(sourceDirPath, salomeExtDir, recursive = True, filter = fileFilter)
+
+ # Write the control file - list of the files inside extension's dir
extDirListData = fileListToNewLineStr(files).encode('utf8')
- info = tarfile.TarInfo(salomexcName)
+ info = tarfile.TarInfo(extName + '.' + cFileNameExt)
info.size=len(extDirListData)
ext.addfile(info, io.BytesIO(extDirListData))
+ # Write the description file as is
+ ext.add(salomexdPath)
+
except Exception:
import traceback
logger.error(traceback.format_exc())
+
if __name__ == '__main__':
- salomeExtFromInstallDir(sys.argv[1])
+ createSalomexFile(sys.argv[1:])