Exemple #1
0
    def writeI18NFiles(self, globalCodes, script):

        # for each locale code, collect mappings
        transKeys  = globalCodes['Translations'].keys()
        localeKeys = globalCodes['Locales'].keys()
        newParts   = {}    # language codes to part objects,    {"C": part}
        newPackages= {}    # language codes to private package objects, {"C": package}
        for localeCode in set(transKeys + localeKeys):
            # new: also provide a localeCode "part" with corresponding packages
            part = Part(localeCode)
            part.bit_mask = script.getPartBitMask()
            newParts[localeCode] = part
            package = Package(part.bit_mask)  # this might be modified later
            newPackages[localeCode] = package
            part.packages.append(package)

            data = {}
            data[localeCode] = { 'Translations': {}, 'Locales': {} }  # we want to have the locale code in the data
            if localeCode in transKeys:
                data[localeCode]['Translations']     = globalCodes['Translations'][localeCode]
                package.data.translations[localeCode] = globalCodes['Translations'][localeCode]
            if localeCode in localeKeys:
                data[localeCode]['Locales']     = globalCodes['Locales'][localeCode]
                package.data.locales[localeCode] = globalCodes['Locales'][localeCode]

            # write to file
            #dataS = json.dumpsCode(data)
            hash, dataS = package.packageContent()  # TODO: this currently works only for pure data packages
            dataS = dataS.replace('\\\\\\', '\\').replace(r'\\', '\\')  # undo damage done by simplejson to raw strings with escapes \\ -> \
            package.compiled = dataS
            fPath = self._resolveFileName(script.baseScriptPath, script.variants, script.settings, localeCode)
            self.writePackage(dataS, fPath, script)
            package.file = os.path.basename(fPath) # TODO: the use of os.path.basename is a hack
            package.hash = hash

        # Finalize the new packages and parts
        # - add prerequisite languages to parts; e.g. ["C", "en", "en_EN"]
        for partId, part in newParts.items():
            if newPackages["C"] not in part.packages:
                package = newPackages["C"]
                part.packages.append(package)   # all need "C"
                package.id |= part.bit_mask     # adapt package's bit string
            if len(partId) > 2 and partId[2] == "_":  # it's a sub-language -> include main language
                mainlang = partId[:2]
                if mainlang not in newPackages:
                    raise RuntimeError("Locale '%s' specified, but not base locale '%s'" % (partId, mainlang))
                if newPackages[mainlang] not in part.packages:
                    part.packages.append(newPackages[mainlang])   # add main language
                    newPackages[mainlang].id |= part.bit_mask     # adapt package's bit string

        # finally, sort packages
        for part in newParts.values():
            part.packagesSorted

        # - add to script object
        script.parts.update([(x.name, x) for x in newParts.values()])  # TODO: update might overwrite exist. entries!
        script.packages.extend(newPackages.values())

        return globalCodes
Exemple #2
0
    def _findMergeTarget(self, mergePackage, packages):

        ##
        # if another package id has the same bits turned on, it is available
        # in the same parts.
        def areInSameParts(mergePackage, package):
            return (mergePackage.id & package.id) == mergePackage.id

        ##
        # check if any of the deps of mergePackage depend on targetPackage -
        # if merging mergePackage into targetPackage, this would be creating
        # circular dependencies
        def noCircularDeps(mergePackage, targetPackage):
            for package in mergePackage.packageDeps:
                if targetPackage in package.packageDeps:
                    return False
            return True

        ##
        # check that the targetPackage is loaded in those parts
        # where mergePackage's deps are loaded
        def depsAvailWhereTarget(mergePackage, targetPackage):
            for depsPackage in mergePackage.packageDeps:
                if not areInSameParts(targetPackage, depsPackage):
                    return False
            return True

        # ----------------------------------------------------------------------

        allPackages = reversed(Package.sort(packages))
        # sorting and reversing assures we try "smaller" package id's first
        addtl_merge_constraints = self._jobconf.get(
            "packages/additional-merge-constraints", True)

        for targetPackage in allPackages:
            if mergePackage.id == targetPackage.id:  # no self-merging ;)
                continue
            if not areInSameParts(mergePackage, targetPackage):
                self._console.debug("Problematic #%d (different parts using)" %
                                    targetPackage.id)
                continue
            if not noCircularDeps(mergePackage, targetPackage):
                self._console.debug("Problematic #%d (circular dependencies)" %
                                    targetPackage.id)
                if addtl_merge_constraints:
                    continue
                # why accept this by default?
            if not depsAvailWhereTarget(mergePackage, targetPackage):
                self._console.debug(
                    "Problematic #%d (dependencies not always available)" %
                    targetPackage.id)
                if addtl_merge_constraints:
                    continue
                # why accept this by default?

            yield targetPackage

        yield None
Exemple #3
0
    def _getPackages(self, script):
        self._console.indent()

        parts = script.parts
        # Generating list of all classes
        allClasses = {}
        for part in parts.values():
            for classId in part.deps:
                allClasses[classId] = True

        # Check for each class which part is using it;
        # create a package for each set of classes which
        # are used by the same combination of parts;
        # track how many parts are using a particular package
        packages = {}
        for classId in allClasses.keys():
            pkgId = 0

            for part in parts.values():
                if classId in part.deps:
                    pkgId |= part.bit_mask

            if not packages.has_key(pkgId):
                package = Package(pkgId)
                packages[pkgId] = package

            packages[pkgId].classes.append(classId)

        # Which packages does a part use - and vice versa
        for package in packages.values():
            for part in parts.values():
                if package.id & part.bit_mask:
                    #part.packages.append(package.id)
                    part.packages.append(package)
                    #package.parts.append(part.name)
                    #package.parts.append(part)

            #package.part_count = len(package.parts)

        # Register dependencies between Packages
        for package in packages.values():
            # get all direct deps of this package
            allDeps = set(())
            for classId in package.classes:
                classDeps, _ = self._depLoader.getCombinedDeps(
                    classId, script.variants, script.buildType)
                loadDeps = set(x.name for x in classDeps['load'])
                allDeps.update(loadDeps)

            # record the other packages in which these dependencies are located
            for classId in allDeps:
                for otherpackage in packages.values():
                    if otherpackage != package and classId in otherpackage.classes:
                        #print "-- package %s adding dependent package %s" % (package.id, otherpackage.id)
                        package.packageDeps.add(otherpackage)

        self._console.outdent()
        return packages.values()
Exemple #4
0
 def getPackagesFromClasses(allClasses):
     packages = {}
     for classId in allClasses:
         pkgId = allClasses[classId]
         # create a Package if necessary
         if pkgId not in packages:
             package = Package(pkgId)
             packages[pkgId] = package
         # store classId with this package
         packages[pkgId].classes.append(classId)
     return packages.values()
Exemple #5
0
    def _findMergeTarget(self, mergePackage, packages):

        ##
        # if another package id has the same bits turned on, it is available
        # in the same parts.
        def areInSameParts(mergePackage, package):  
            return (mergePackage.id & package.id) == mergePackage.id

        ##
        # check if any of the deps of mergePackage depend on targetPackage - 
        # if merging mergePackage into targetPackage, this would be creating
        # circular dependencies
        def noCircularDeps(mergePackage, targetPackage):
            for package in mergePackage.packageDeps:
                if targetPackage in package.packageDeps:
                    return False
            return True

        ##
        # check that the targetPackage is loaded in those parts
        # where mergePackage's deps are loaded
        def depsAvailWhereTarget (mergePackage, targetPackage):
            for depsPackage in mergePackage.packageDeps:
                if not areInSameParts(targetPackage, depsPackage):
                    return False
            return True

        # ----------------------------------------------------------------------

        allPackages  = reversed(Package.sort(packages))
                                # sorting and reversing assures we try "smaller" package id's first
        addtl_merge_constraints = self._jobconf.get("packages/additional-merge-constraints", False)

        for targetPackage in allPackages:
            if mergePackage.id == targetPackage.id:  # no self-merging ;)
                continue
            if not areInSameParts(mergePackage, targetPackage):
                self._console.debug("Problematic #%d (different parts using)" % targetPackage.id)
                continue
            if not noCircularDeps(mergePackage, targetPackage):
                self._console.debug("Problematic #%d (circular dependencies)" % targetPackage.id)
                if addtl_merge_constraints:
                    continue   
                # why accept this by default?
            if not depsAvailWhereTarget(mergePackage, targetPackage):
                self._console.debug("Problematic #%d (dependencies not always available)" % targetPackage.id)
                if addtl_merge_constraints:
                    continue   
                # why accept this by default?

            yield targetPackage

        yield None
 def packagesSortedSimple(self):
     return Package.simpleSort(self.packages)
Exemple #7
0
    def generateI18NParts(self, script, globalCodes):

        # for each locale code, collect mappings
        transKeys  = globalCodes['Translations'].keys()
        localeKeys = globalCodes['Locales'].keys()
        newParts   = {}    # language codes to part objects,    {"C": part}
        newPackages= {}    # language codes to private package objects, {"C": package}
        for localeCode in set(transKeys + localeKeys):
            # new: also provide a localeCode "part" with corresponding packages
            part = Part(localeCode)
            part.bit_mask = script.getPartBitMask()
            newParts[localeCode] = part
            package = Package(part.bit_mask)  # this might be modified later
            newPackages[localeCode] = package
            part.packages.append(package)

            data = {}
            data[localeCode] = { 'Translations': {}, 'Locales': {} }  # we want to have the locale code in the data
            if localeCode in transKeys:
                data[localeCode]['Translations']     = globalCodes['Translations'][localeCode]
                package.data.translations[localeCode] = globalCodes['Translations'][localeCode]
            if localeCode in localeKeys:
                data[localeCode]['Locales']     = globalCodes['Locales'][localeCode]
                package.data.locales[localeCode] = globalCodes['Locales'][localeCode]

            # file name and hash code
            hash, dataS  = package.packageContent()  # TODO: this currently works only for pure data packages
            dataS        = dataS.replace('\\\\\\', '\\').replace(r'\\', '\\')  # undo damage done by simplejson to raw strings with escapes \\ -> \
            package.compiled = dataS
            package.hash     = hash
            fPath = self._resolveFileName(script.baseScriptPath, script.variants, script.settings, localeCode)
            package.file = os.path.basename(fPath)
            if self._job.get("compile-options/paths/scripts-add-hash", False):
                package.file = self._fileNameWithHash(package.file, package.hash)
            setattr(package,"__localeflag", True)   # TODO: temp. hack for writeI18NPackages()

        # Finalize the new packages and parts
        # - add prerequisite languages to parts; e.g. ["C", "en", "en_EN"]
        for partId, part in newParts.items():
            if newPackages["C"] not in part.packages:
                package = newPackages["C"]
                part.packages.append(package)   # all need "C"
                package.id |= part.bit_mask     # adapt package's bit string
            if len(partId) > 2 and partId[2] == "_":  # it's a sub-language -> include main language
                mainlang = partId[:2]
                if mainlang not in newPackages:
                    raise RuntimeError("Locale '%s' specified, but not base locale '%s'" % (partId, mainlang))
                if newPackages[mainlang] not in part.packages:
                    part.packages.append(newPackages[mainlang])   # add main language
                    newPackages[mainlang].id |= part.bit_mask     # adapt package's bit string

        # finally, sort packages
        for part in newParts.values():
            part.packagesSorted

        # - add to script object
        for partId in newParts:
            if partId in script.parts:
                raise RuntimeError("Name collison between code part and generated I18N part.")
            script.parts[partId] = newParts[partId]
        script.packages.extend(newPackages.values())

        return script
Exemple #8
0
    def _getPreviousCommonPackage(self, searchPackage, packages):
        # get the "smallest" package (in the sense of _sortPackages()) that is
        # in all parts searchPackage is in, and is earlier in the corresponding
        # packages lists

        def isCommonAndGreaterPackage(searchPackage, package):
            # the next takes advantage of the fact that the package id encodes
            # the parts a package is used by. if another package id has the
            # same bits turned on, it is in the same packages. this is only
            # true for the searchId package itself and package id's that have
            # more bits turned on (ie. are "greater"); hence, and due to
            # _sortPackages, they are earlier in the packages list of the
            # corresponding parts
            if searchPackage.id & package.id == searchPackage.id:
                return True
            return False

        ##
        # check if the deps of searchPackage have deps to targetPackage -
        # if merging searchPackage into targetPackage, this would be creating
        # circular dependencies

        def noCircularDeps(searchPackage, targetPackage):
            for package in searchPackage.packageDeps:
                if targetPackage in package.packageDeps:
                    return False
            return True

        ##
        # check that the targetPackage is loaded in (at least) those parts
        # where searchPackage's deps are also loaded

        def depsAvailWhereTarget(searchPackage, targetPackage):
            for depsPackage in searchPackage.packageDeps:
                if not isCommonAndGreaterPackage(targetPackage, depsPackage):
                    #if not targetPackage.id & depsPackage.id == targetPackage.id:
                    return False
            return True

        # ----------------------------------------------------------------------

        allPackages = reversed(Package.simpleSort(packages))
        # sorting and reversing assures we try "smaller" package id's first
        additional_constraints = self._jobconf.get(
            "packages/additional-merge-constraints", False)

        for targetPackage in allPackages:
            if searchPackage.id == targetPackage.id:  # no self-merging ;)
                continue
            if not isCommonAndGreaterPackage(searchPackage, targetPackage):
                self._console.debug("Problematic #%d (different parts using)" %
                                    targetPackage.id)
                continue
            if not noCircularDeps(searchPackage, targetPackage):
                self._console.debug("Problematic #%d (circular dependencies)" %
                                    targetPackage.id)
                if additional_constraints:
                    continue
            if not depsAvailWhereTarget(searchPackage, targetPackage):
                self._console.debug(
                    "Problematic #%d (dependencies not always available)" %
                    targetPackage.id)
                if additional_constraints:
                    continue
            yield targetPackage

        yield None
Exemple #9
0
 def packagesSorted(self):
     return Package.sort(self.packages)
Exemple #10
0
    def runCompiled(self, script, treeCompiler, version="build"):

        def getOutputFile(compileType):
            filePath = compConf.get("paths/file")
            if not filePath:
                filePath = os.path.join(compileType, "script", self.getAppName() + ".js")
            return filePath

        def getFileUri(scriptUri):
            appfile = os.path.basename(fileRelPath)
            fileUri = os.path.join(scriptUri, appfile)  # make complete with file name
            fileUri = Path.posifyPath(fileUri)
            return fileUri

        def generateBootScript(globalCodes, script, bootPackage="", compileType="build"):

            def packagesOfFiles(fileUri, packages):
                # returns list of lists, each containing destination file name of the corresp. part
                # npackages = [['script/gui-0.js'], ['script/gui-1.js'],...]
                npackages = []
                file = os.path.basename(fileUri)
                if self._job.get("packages/loader-with-boot", True):
                    totalLen = len(packages)
                else:
                    totalLen = len(packages) + 1
                for packageId, packageFileName in enumerate(self.packagesFileNames(file, totalLen, classPackagesOnly=True)):
                    npackages.append((packageFileName,))
                    packages[packageId].file = packageFileName  # TODO: very unnice to fix this here
                return npackages

            # besser: fixPackagesFiles()
            def packagesOfFilesX(fileUri, packages):
                # returns list of lists, each containing destination file name of the corresp. package
                # npackages = [['script/gui-0.js'], ['script/gui-1.js'],...]
                file = os.path.basename(fileUri)
                loader_with_boot = self._job.get("packages/loader-with-boot", True)
                for packageId, package in enumerate(packages):
                    if loader_with_boot:
                        suffix = packageId - 1
                        if suffix < 0:
                            suffix = ""
                    else:
                        suffix = packageId
                    packageFileName = self._resolveFileName(file, self._variants, self._settings, suffix)
                    package.file = packageFileName

                return packages

            # ----------------------------------------------------------------------------
            self._console.info("Generating boot script...")

            if not self._job.get("packages/i18n-with-boot", True):
                globalCodes = self.writeI18NFiles(globalCodes, script)
                # remove I18N info from globalCodes, so they don't go into the loader
                globalCodes["Translations"] = {}
                globalCodes["Locales"]      = {}
            else:
                if compileType == "build":
                    # also remove them here, as this info is now with the packages
                    globalCodes["Translations"] = {}
                    globalCodes["Locales"]      = {}

            plugCodeFile = compConf.get("code/decode-uris-plug", False)
            if compileType == "build":
                filepackages = packagesOfFiles(fileUri, packages)
                bootContent = self.generateBootCode(parts, filepackages, boot, script, compConf, variants, settings, bootPackage, globalCodes, compileType, plugCodeFile, format)
            else:
                filepackages = [x.classes for x in packages]
                bootContent = self.generateBootCode(parts, filepackages, boot, script, compConf, variants={}, settings={}, bootCode=None, globalCodes=globalCodes, version=compileType, decodeUrisFile=plugCodeFile, format=format)


            return bootContent


        def getPackageData(package):
            data = {}
            data["resources"]    = package.data.resources
            data["translations"] = package.data.translations
            data["locales"]      = package.data.locales
            data = json.dumpsCode(data)
            data += ';\n'
            return data

        def compilePackage(packageIndex, package):
            self._console.info("Compiling package #%s:" % packageIndex, False)
            self._console.indent()

            # Compile file content
            pkgCode = self._treeCompiler.compileClasses(package.classes, variants, optimize, format)
            pkgData = getPackageData(package)
            hash    = sha.getHash(pkgData + pkgCode)[:12]  # first 12 chars should be enough

            isBootPackage = packageIndex == 0
            if isBootPackage:
                compiledContent = ("qx.$$packageData['%s']=" % hash) + pkgData + pkgCode
            else:
                compiledContent  = u'''qx.$$packageData['%s']=%s\n''' % (hash, pkgData)
                compiledContent += u'''qx.Part.$$notifyLoad("%s", function() {\n%s\n});''' % (hash, pkgCode)
            
            #
            package.hash = hash  # to fill qx.$$loader.packageHashes in generateBootScript()

            self._console.debug("Done: %s" % self._computeContentSize(compiledContent))
            self._console.outdent()

            return compiledContent

        # -- Main --------------------------------------------------------------

        # Early return
        compileType = self._job.get("compile/type", "")
        if compileType not in ("build", "source"):
            return

        packages   = script.packagesSortedSimple()
        parts      = script.parts
        boot       = script.boot
        variants   = script.variants

        self._classList    = script.classes
        self._treeCompiler = treeCompiler
        self._variants     = variants

        self._console.info("Generate %s version..." % compileType)
        self._console.indent()

        # - Evaluate job config ---------------------
        # Compile config
        compConf = self._job.get("compile-options")
        compConf = ExtMap(compConf)

        # Whether the code should be formatted
        format = compConf.get("code/format", False)
        script.scriptCompress = compConf.get("paths/gzip", False)

        # Read in settings
        settings = self.getSettings()
        script.settings = settings

        # Read libraries
        libs = self._job.get("library", [])

        # Get translation maps
        locales = compConf.get("code/locales", [])
        translationMaps = self.getTranslationMaps(packages, variants, locales)

        # Read in base file name
        fileRelPath = getOutputFile(compileType)
        filePath    = self._config.absPath(fileRelPath)
        script.baseScriptPath = filePath

        if compileType == "build":
            # read in uri prefixes
            scriptUri = compConf.get('uris/script', 'script')
            scriptUri = Path.posifyPath(scriptUri)
            fileUri   = getFileUri(scriptUri)
            # for resource list
            resourceUri = compConf.get('uris/resource', 'resource')
            resourceUri = Path.posifyPath(resourceUri)
        else:
            # source version needs place where the app HTML ("index.html") lives
            self.approot = self._config.absPath(compConf.get("paths/app-root", ""))
            resourceUri = None
            scriptUri   = None

        # Get global script data (like qxlibraries, qxresources,...)
        globalCodes = self.generateGlobalCodes(script, libs, translationMaps, settings, variants, format, resourceUri, scriptUri)

        if compileType == "build":

            # - Specific job config ---------------------
            # read in compiler options
            optimize = compConf.get("code/optimize", [])
            self._treeCompiler.setOptimize(optimize)

            # - Generating packages ---------------------
            self._console.info("Generating packages...")
            self._console.indent()

            bootPackage = ""
            for packageIndex, package in enumerate(packages):
                package.compiled = compilePackage(packageIndex, package)

            self._console.outdent()
            if not len(packages):
                raise RuntimeError("No valid boot package generated.")

            # - Put loader and packages together -------
            loader_with_boot = self._job.get("packages/loader-with-boot", True)
            # handle loader and boot package
            if loader_with_boot:
                bootCode = generateBootScript(globalCodes, script, packages[0].compiled)
                packages[0].compiled = bootCode
            else:
                loaderCode = generateBootScript(globalCodes, script)
                loadPackage = Package(0)            # make a dummy Package for the loader
                loadPackage.compiled = loaderCode
                packages.insert(0, loadPackage)

            # attach file names
            for package, fileName in zip(packages, self.packagesFileNames(script.baseScriptPath, len(packages))):
                package.file = fileName

            # write packages
            self.writePackages(packages, script)

        # ---- 'source' version ------------------------------------------------
        else:

            sourceContent = generateBootScript(globalCodes, script, bootPackage="", compileType=compileType)

            # Construct file name
            resolvedFilePath = self._resolveFileName(filePath, variants, settings)

            # Save result file
            filetool.save(resolvedFilePath, sourceContent)

            if compConf.get("paths/gzip"):
                filetool.gzip(resolvedFilePath, sourceContent)

            self._console.outdent()
            self._console.debug("Done: %s" % self._computeContentSize(sourceContent))
            self._console.outdent()

        self._console.outdent()

        return  # runCompiled()
    def _getPackages(self, script):
        parts = script.parts
        # Generating list of all classes
        allClasses = {}
        for part in parts.values():
            for classId in part.deps:
                allClasses[classId] = True

        # Check for each class which part is using it;
        # create a package for each set of classes which
        # are used by the same combination of parts;
        # track how many parts are using a particular package
        packages = {}
        for classId in allClasses.keys():
            pkgId     = 0

            for part in parts.values():
                if classId in part.deps:
                    pkgId     |= part.bit_mask

            if not packages.has_key(pkgId):
                package            = Package(pkgId)
                packages[pkgId]    = package

            packages[pkgId].classes.append(classId)

        # Which packages does a part use - and vice versa
        for package in packages.values():
            for part in parts.values():
                if package.id & part.bit_mask:
                    #part.packages.append(package.id)
                    part.packages.append(package)
                    #package.parts.append(part.name)
                    package.parts.append(part)
                    
            package.part_count = len(package.parts)

        # Sorting packages of parts
        for part in parts.values():
            #part.packageIdsSorted = self._sortPackages([x.id for x in part.packages], packages)
            ## re-map sorting to part.packages
            #packObjs = []
            #for pkgId in part.packageIdsSorted:
            #    packObjs.append(packages[pkgId])
            #part.packages = packObjs
            self._sortPartPackages(part)

        # Register dependencies between Packages
        for package in packages.values():
            # get all direct deps of this package
            allDeps = set(())
            for classId in package.classes:
                classDeps   = self._depLoader.getCombinedDeps(classId, script.variants)
                loadDeps    = set(x.name for x in classDeps['load'])
                allDeps.update(loadDeps)

            # record the other packages in which these dependencies are located
            for classId in allDeps:
                for otherpackage in packages.values():
                    if otherpackage != package and classId in otherpackage.classes:
                        #print "-- package %s adding dependent package %s" % (package.id, otherpackage.id)
                        package.packageDeps.add(otherpackage)
         
        return packages
Exemple #12
0
    def generateI18NParts(self, script, locales):

        ##
        # collect translation and locale info from the packages
        def getTranslationMaps(packages):
            packageTranslations = []
            for package in packages:
                trans_dat = package.data.translations
                loc_dat   = package.data.locales
                packageTranslations.append((trans_dat,loc_dat))
            return packageTranslations

        ##
        # takes an array of (po-data, locale-data) dict pairs
        # merge all po data and all cldr data in a single dict each
        def mergeTranslationMaps(transMaps):
            poData = {}
            cldrData = {}

            for pac_dat, loc_dat in transMaps:
                for loc in pac_dat:
                    if loc not in poData:
                        poData[loc] = {}
                    poData[loc].update(pac_dat[loc])
                for loc in loc_dat:
                    if loc not in cldrData:
                        cldrData[loc] = {}
                    cldrData[loc].update(loc_dat[loc])

            return (poData, cldrData)

        # ----------------------------------------------------------------------

        translationMaps = getTranslationMaps(script.packages)
        translationData ,                                      \
        localeData      = mergeTranslationMaps(translationMaps)
        # for each locale code, collect mappings
        transKeys  = translationData.keys()
        localeKeys = localeData.keys()
        newParts   = {}    # language codes to part objects,    {"C": part}
        newPackages= {}    # language codes to private package objects, {"C": package}
        for localeCode in set(transKeys + localeKeys):
            # also provide a localeCode "part" with corresponding packages
            intpart = Part(localeCode)
            intpart.bit_mask = script.getPartBitMask()
            newParts[localeCode] = intpart
            intpackage = Package(intpart.bit_mask)  # this might be modified later
            newPackages[localeCode] = intpackage
            intpart.packages.append(intpackage)

            data = {}
            data[localeCode] = { 'Translations': {}, 'Locales': {} }  # we want to have the locale code in the data
            if localeCode in transKeys:
                data[localeCode]['Translations']     = translationData[localeCode]
                intpackage.data.translations[localeCode] = translationData[localeCode]
            if localeCode in localeKeys:
                data[localeCode]['Locales']     = localeData[localeCode]
                intpackage.data.locales[localeCode] = localeData[localeCode]

            # file name and hash code
            hash_, dataS  = intpackage.packageContent()  # TODO: this currently works only for pure data packages
            dataS        = dataS.replace('\\\\\\', '\\').replace(r'\\', '\\')  # undo damage done by simplejson to raw strings with escapes \\ -> \
            intpackage.compiled.append(dataS)
            intpackage.hash     = hash_
            fPath = self._resolveFileName(script.baseScriptPath, script.variants, script.settings, localeCode)
            intpackage.file = os.path.basename(fPath)
            if self._job.get("compile-options/paths/scripts-add-hash", False):
                intpackage.file = self._fileNameWithHash(intpackage.file, intpackage.hash)
            intpackage.files = ["%s:%s" % ("__out__", intpackage.file)]
            setattr(intpackage,"__localeflag", True)   # TODO: temp. hack for writeI18NPackages()

        # Finalize the new packages and parts
        # - add prerequisite languages to parts; e.g. ["C", "en", "en_EN"]
        for partId, intpart in newParts.items():
            if newPackages["C"] not in intpart.packages:
                intpackage = newPackages["C"]
                intpart.packages.append(intpackage)   # all need "C"
                intpackage.part_mask |= intpart.bit_mask     # adapt package's bit string
            if len(partId) > 2 and partId[2] == "_":  # it's a sub-language -> include main language
                mainlang = partId[:2]
                if mainlang not in newPackages:
                    raise RuntimeError("Locale '%s' specified, but not base locale '%s'" % (partId, mainlang))
                if newPackages[mainlang] not in intpart.packages:
                    intpart.packages.append(newPackages[mainlang])   # add main language
                    newPackages[mainlang].part_mask |= intpart.bit_mask     # adapt package's bit string

        # finally, sort packages
        for intpart in newParts.values():
            intpart.packagesSorted

        # - add to script object
        for partId in newParts:
            if partId in script.parts:
                raise RuntimeError("Name collison between code part and generated I18N part.")
            script.parts[partId] = newParts[partId]
        script.packages.extend(newPackages.values())

        return script
Exemple #13
0
    def generateI18NParts(self, script, globalCodes):

        # for each locale code, collect mappings
        transKeys  = globalCodes['Translations'].keys()
        localeKeys = globalCodes['Locales'].keys()
        newParts   = {}    # language codes to part objects,    {"C": part}
        newPackages= {}    # language codes to private package objects, {"C": package}
        for localeCode in set(transKeys + localeKeys):
            # new: also provide a localeCode "part" with corresponding packages
            part = Part(localeCode)
            part.bit_mask = script.getPartBitMask()
            newParts[localeCode] = part
            package = Package(part.bit_mask)  # this might be modified later
            newPackages[localeCode] = package
            part.packages.append(package)

            data = {}
            data[localeCode] = { 'Translations': {}, 'Locales': {} }  # we want to have the locale code in the data
            if localeCode in transKeys:
                data[localeCode]['Translations']     = globalCodes['Translations'][localeCode]
                package.data.translations[localeCode] = globalCodes['Translations'][localeCode]
            if localeCode in localeKeys:
                data[localeCode]['Locales']     = globalCodes['Locales'][localeCode]
                package.data.locales[localeCode] = globalCodes['Locales'][localeCode]

            # file name and hash code
            hash, dataS  = package.packageContent()  # TODO: this currently works only for pure data packages
            dataS        = dataS.replace('\\\\\\', '\\').replace(r'\\', '\\')  # undo damage done by simplejson to raw strings with escapes \\ -> \
            package.compiled = dataS
            package.hash     = hash
            fPath = self._resolveFileName(script.baseScriptPath, script.variants, script.settings, localeCode)
            package.file = os.path.basename(fPath)
            if self._job.get("compile-options/paths/scripts-add-hash", False):
                package.file = self._fileNameWithHash(package.file, package.hash)
            setattr(package,"__localeflag", True)   # TODO: temp. hack for writeI18NPackages()

        # Finalize the new packages and parts
        # - add prerequisite languages to parts; e.g. ["C", "en", "en_EN"]
        for partId, part in newParts.items():
            if newPackages["C"] not in part.packages:
                package = newPackages["C"]
                part.packages.append(package)   # all need "C"
                package.id |= part.bit_mask     # adapt package's bit string
            if len(partId) > 2 and partId[2] == "_":  # it's a sub-language -> include main language
                mainlang = partId[:2]
                if mainlang not in newPackages:
                    raise RuntimeError("Locale '%s' specified, but not base locale '%s'" % (partId, mainlang))
                if newPackages[mainlang] not in part.packages:
                    part.packages.append(newPackages[mainlang])   # add main language
                    newPackages[mainlang].id |= part.bit_mask     # adapt package's bit string

        # finally, sort packages
        for part in newParts.values():
            part.packagesSorted

        # - add to script object
        for partId in newParts:
            if partId in script.parts:
                raise RuntimeError("Name collison between code part and generated I18N part.")
            script.parts[partId] = newParts[partId]
        script.packages.extend(newPackages.values())

        return script
Exemple #14
0
    def runCompiled(self, script, treeCompiler, version="build"):

        def getOutputFile(compileType):
            filePath = compConf.get("paths/file")
            if not filePath:
                filePath = os.path.join(compileType, "script", script.namespace + ".js")
            return filePath

        def getFileUri(scriptUri):
            appfile = os.path.basename(fileRelPath)
            fileUri = os.path.join(scriptUri, appfile)  # make complete with file name
            fileUri = Path.posifyPath(fileUri)
            return fileUri

        ##
        # returns the Javascript code for the initial ("boot") script as a string,
        #  using the loader.tmpl template and filling its placeholders
        def generateBootCode(parts, packages, boot, script, compConf, variants, settings, bootCode, globalCodes, version="source", decodeUrisFile=None, format=False):

            ##
            # create a map with part names as key and array of package id's and
            # return as string
            def partsMap(script):
                partData = {}
                packages = script.packagesSortedSimple()
                #print "packages: %r" % packages
                for part in script.parts:
                    partData[part] = script.parts[part].packagesAsIndices(packages)
                    #print "part '%s': %r" % (part, script.parts[part].packages)
                partData = json.dumpsCode(partData)

                return partData

            def fillTemplate(vals, template):
                # Fill the code template with various vals 
                templ  = MyTemplate(template)
                result = templ.safe_substitute(vals)

                return result

            def packageUrisToJS1(packages, version, namespace=None):
                # Translate URI data to JavaScript
                
                allUris = []
                for packageId, package in enumerate(packages):
                    packageUris = []
                    for fileId in package:

                        if version == "build":
                            # TODO: gosh, the next is an ugly hack!
                            #namespace  = self._resourceHandler._genobj._namespaces[0]  # all name spaces point to the same paths in the libinfo struct, so any of them will do
                            if not namespace:
                                namespace  = script.namespace  # all name spaces point to the same paths in the libinfo struct, so any of them will do
                            relpath    = OsPath(fileId)
                        else:
                            namespace  = self._classes[fileId]["namespace"]
                            relpath    = OsPath(self._classes[fileId]["relpath"])

                        shortUri = Uri(relpath.toUri())
                        packageUris.append("%s:%s" % (namespace, shortUri.encodedValue()))
                    allUris.append(packageUris)

                return allUris

            ##
            # Translate URI data to JavaScript
            # using Package objects
            def packageUrisToJS(packages, version):

                allUris = []
                for packageId, package in enumerate(packages):
                    packageUris = []
                    if package.file: # build
                        namespace = "__out__"
                        fileId    = package.file
                        relpath    = OsPath(fileId)
                        shortUri   = Uri(relpath.toUri())
                        packageUris.append("%s:%s" % (namespace, shortUri.encodedValue()))
                    else: # "source" :
                        for clazz in package.classes:
                            namespace  = self._classes[clazz]["namespace"]
                            relpath    = OsPath(self._classes[clazz]["relpath"])
                            shortUri   = Uri(relpath.toUri())
                            packageUris.append("%s:%s" % (namespace, shortUri.encodedValue()))
                    allUris.append(packageUris)

                return allUris


            def loadTemplate(bootCode):
                # try custom loader templates
                loaderFile = compConf.get("paths/loader-template", None)
                if not loaderFile:
                    # use default templates
                    if version=="build":
                        #loaderFile = os.path.join(filetool.root(), os.pardir, "data", "generator", "loader-build.tmpl.js")
                        # TODO: test-wise using generic template
                        loaderFile = os.path.join(filetool.root(), os.pardir, "data", "generator", "loader.tmpl.js")
                    else:
                        #loaderFile = os.path.join(filetool.root(), os.pardir, "data", "generator", "loader-source.tmpl.js")
                        loaderFile = os.path.join(filetool.root(), os.pardir, "data", "generator", "loader.tmpl.js")
                
                template = filetool.read(loaderFile)

                return template

            # ---------------------------------------------------------------

            if not parts:
                return ""

            result           = ""
            vals             = {}
            packages         = script.packagesSortedSimple()
            loader_with_boot = self._job.get("packages/loader-with-boot", True)

            # stringify data in globalCodes
            for entry in globalCodes:
                globalCodes[entry] = json.dumpsCode(globalCodes[entry])
                # undo damage done by simplejson to raw strings with escapes \\ -> \
                globalCodes[entry] = globalCodes[entry].replace('\\\\\\', '\\').replace(r'\\', '\\')  # " gets tripple escaped, therefore the first .replace()

            vals.update(globalCodes)

            if version=="build":
                vals["Resources"] = json.dumpsCode({})  # TODO: undo Resources from globalCodes!!!
            vals["Boot"] = '"%s"' % boot
            if version == "build":
                vals["BootPart"] = bootCode
            else:
                vals["BootPart"] = ""
                # fake package data
                for key, package in enumerate(packages): 
                    vals["BootPart"] += "qx.$$packageData['%d']={};\n" % key

            # Translate part information to JavaScript
            vals["Parts"] = partsMap(script)

            # Translate URI data to JavaScript
            #vals["Uris"] = packageUrisToJS1(packages, version)
            vals["Uris"] = packageUrisToJS(packages, version)
            vals["Uris"] = json.dumpsCode(vals["Uris"])

            # Add potential extra scripts
            vals["UrisBefore"] = []
            if self._job.get("add-script", False):
                additional_scripts = self._job.get("add-script",[])
                for additional_script in additional_scripts:
                    vals["UrisBefore"].append(additional_script["uri"])
            vals["UrisBefore"] = json.dumpsCode(vals["UrisBefore"])

            # Whether boot package is inline
            if version == "source":
                vals["BootIsInline"] = json.dumpsCode(False)
            else:
                vals["BootIsInline"] = json.dumpsCode(loader_with_boot)
                
            # Closure package information
            cParts = {}
            if version == "build":
                for part in script.parts:
                    if not loader_with_boot or part != "boot":
                        cParts[part] = True
            vals["ClosureParts"] = json.dumpsCode(cParts)

            # Package Hashes
            vals["PackageHashes"] = {}
            for key, package in enumerate(packages):
                if package.hash:
                    vals["PackageHashes"][key] = package.hash
                else:
                    vals["PackageHashes"][key] = "%d" % key  # fake code package hashes in source ver.
            vals["PackageHashes"] = json.dumpsCode(vals["PackageHashes"])

            # Script hook for qx.$$loader.decodeUris() function
            vals["DecodeUrisPlug"] = ""
            if decodeUrisFile:
                plugCode = filetool.read(self._config.absPath(decodeUrisFile))  # let it bomb if file can't be read
                vals["DecodeUrisPlug"] = plugCode.strip()
            
            # Enable "?nocache=...." for script loading?
            vals["NoCacheParam"] = "true" if self._job.get("compile-options/uris/add-nocache-param", True) else "false"

            # Locate and load loader basic script
            template = loadTemplate(bootCode)

            # Fill template gives result
            result = fillTemplate(vals, template)

            return result


        ##
        # shallow layer above generateBootCode(), and its only client
        def generateBootScript(globalCodes, script, bootPackage="", compileType="build"):

            self._console.info("Generating boot script...")

            if not self._job.get("packages/i18n-with-boot", True):
                # remove I18N info from globalCodes, so they don't go into the loader
                globalCodes["Translations"] = {}
                globalCodes["Locales"]      = {}
            else:
                if compileType == "build":
                    # also remove them here, as this info is now with the packages
                    globalCodes["Translations"] = {}
                    globalCodes["Locales"]      = {}

            plugCodeFile = compConf.get("code/decode-uris-plug", False)
            if compileType == "build":
                filepackages = [(x.file,) for x in packages]
                bootContent  = generateBootCode(parts, filepackages, boot, script, compConf, variants, settings, bootPackage, globalCodes, compileType, plugCodeFile, format)
            else:
                filepackages = [x.classes for x in packages]
                bootContent  = generateBootCode(parts, filepackages, boot, script, compConf, variants={}, settings={}, bootCode=None, globalCodes=globalCodes, version=compileType, decodeUrisFile=plugCodeFile, format=format)


            return bootContent


        def getPackageData(package):
            data = {}
            data["resources"]    = package.data.resources
            data["translations"] = package.data.translations
            data["locales"]      = package.data.locales
            data = json.dumpsCode(data)
            data += ';\n'
            return data


        def compilePackage(packageIndex, package):
            self._console.info("Compiling package #%s:" % packageIndex, False)
            self._console.indent()

            # Compile file content
            pkgCode = self._treeCompiler.compileClasses(package.classes, variants, optimize, format)
            pkgData = getPackageData(package)
            hash    = sha.getHash(pkgData + pkgCode)[:12]  # first 12 chars should be enough

            isBootPackage = packageIndex == 0
            if isBootPackage:
                compiledContent = ("qx.$$packageData['%s']=" % hash) + pkgData + pkgCode
            else:
                compiledContent  = u'''qx.$$packageData['%s']=%s\n''' % (hash, pkgData)
                compiledContent += u'''qx.Part.$$notifyLoad("%s", function() {\n%s\n});''' % (hash, pkgCode)
            
            #
            package.hash = hash  # to fill qx.$$loader.packageHashes in generateBootScript()

            self._console.debug("Done: %s" % self._computeContentSize(compiledContent))
            self._console.outdent()

            return compiledContent


        ##
        # takes an array of (po-data, locale-data) dict pairs
        # merge all po data and all cldr data in a single dict each
        def mergeTranslationMaps(transMaps):
            poData = {}
            cldrData = {}

            for pac_dat, loc_dat in transMaps:
                for loc in pac_dat:
                    if loc not in poData:
                        poData[loc] = {}
                    poData[loc].update(pac_dat[loc])
                for loc in loc_dat:
                    if loc not in cldrData:
                        cldrData[loc] = {}
                    cldrData[loc].update(loc_dat[loc])

            return (poData, cldrData)


        # -- Main - runCompiled ------------------------------------------------

        # Early return
        compileType = self._job.get("compile/type", "")
        if compileType not in ("build", "source"):
            return

        packages   = script.packagesSortedSimple()
        parts      = script.parts
        boot       = script.boot
        variants   = script.variants
        libraries  = script.libraries

        self._treeCompiler = treeCompiler
        self._variants     = variants
        self._script       = script

        self._console.info("Generate %s version..." % compileType)
        self._console.indent()

        # - Evaluate job config ---------------------
        # Compile config
        compConf = self._job.get("compile-options")
        compConf = ExtMap(compConf)

        # Whether the code should be formatted
        format = compConf.get("code/format", False)
        script.scriptCompress = compConf.get("paths/gzip", False)

        # Read in settings
        settings = self.getSettings()
        script.settings = settings

        # Read libraries
        libs = self._job.get("library", [])

        # Get translation maps
        locales = compConf.get("code/locales", [])
        translationMaps = self.getTranslationMaps(packages, variants, locales)

        # Read in base file name
        fileRelPath = getOutputFile(compileType)
        filePath    = self._config.absPath(fileRelPath)
        script.baseScriptPath = filePath

        if compileType == "build":
            # read in uri prefixes
            scriptUri = compConf.get('uris/script', 'script')
            scriptUri = Path.posifyPath(scriptUri)
            fileUri   = getFileUri(scriptUri)
            # for resource list
            resourceUri = compConf.get('uris/resource', 'resource')
            resourceUri = Path.posifyPath(resourceUri)
        else:
            # source version needs place where the app HTML ("index.html") lives
            self.approot = self._config.absPath(compConf.get("paths/app-root", ""))
            resourceUri = None
            scriptUri   = None

        # Get global script data (like qxlibraries, qxresources,...)
        globalCodes                = {}
        globalCodes["Settings"]    = settings
        globalCodes["Variants"]    = self.generateVariantsCode(variants)
        globalCodes["Libinfo"]     = self.generateLibInfoCode(libs, format, resourceUri, scriptUri)
        # add synthetic output lib
        if scriptUri: out_sourceUri= scriptUri
        else:
            out_sourceUri = self._computeResourceUri({'class': ".", 'path': os.path.dirname(script.baseScriptPath)}, OsPath(""), rType="class", appRoot=self.approot)
            out_sourceUri = os.path.normpath(out_sourceUri.encodedValue())
        globalCodes["Libinfo"]['__out__'] = { 'sourceUri': out_sourceUri }
        globalCodes["Resources"]    = self.generateResourceInfoCode(script, settings, libraries, format)
        globalCodes["Translations"],\
        globalCodes["Locales"]      = mergeTranslationMaps(translationMaps)

        # Potentally create dedicated I18N packages
        i18n_as_parts = not self._job.get("packages/i18n-with-boot", True)
        if i18n_as_parts:
            script = self.generateI18NParts(script, globalCodes)
            self.writePackages([p for p in script.packages if getattr(p, "__localeflag", False)], script)

        if compileType == "build":

            # - Specific job config ---------------------
            # read in compiler options
            optimize = compConf.get("code/optimize", [])
            self._treeCompiler.setOptimize(optimize)

            # - Generating packages ---------------------
            self._console.info("Generating packages...")
            self._console.indent()

            bootPackage = ""
            for packageIndex, package in enumerate(packages):
                package.compiled = compilePackage(packageIndex, package)

            self._console.outdent()
            if not len(packages):
                raise RuntimeError("No valid boot package generated.")

            # - Put loader and packages together -------
            loader_with_boot = self._job.get("packages/loader-with-boot", True)
            # handle loader and boot package
            if not loader_with_boot:
                loadPackage = Package(0)            # make a dummy Package for the loader
                packages.insert(0, loadPackage)

            # attach file names (do this before calling generateBootScript)
            for package, fileName in zip(packages, self.packagesFileNames(script.baseScriptPath, len(packages))):
                package.file = os.path.basename(fileName)
                if self._job.get("compile-options/paths/scripts-add-hash", False):
                    package.file = self._fileNameWithHash(package.file, package.hash)

            # generate and integrate boot code
            if loader_with_boot:
                # merge loader code with first package
                bootCode = generateBootScript(globalCodes, script, packages[0].compiled)
                packages[0].compiled = bootCode
            else:
                loaderCode = generateBootScript(globalCodes, script)
                packages[0].compiled = loaderCode

            # write packages
            self.writePackages(packages, script)

        # ---- 'source' version ------------------------------------------------
        else:

            sourceContent = generateBootScript(globalCodes, script, bootPackage="", compileType=compileType)

            # Construct file name
            resolvedFilePath = self._resolveFileName(filePath, variants, settings)

            # Save result file
            filetool.save(resolvedFilePath, sourceContent)

            if compConf.get("paths/gzip"):
                filetool.gzip(resolvedFilePath, sourceContent)

            self._console.outdent()
            self._console.debug("Done: %s" % self._computeContentSize(sourceContent))
            self._console.outdent()

        self._console.outdent()

        return  # runCompiled()
 def packagesSorted(self):
     return Package.sort(self.packages)
Exemple #16
0
 def packagesSortedSimple(self):
     return Package.simpleSort(self.packages)
Exemple #17
0
        def partsConfigFromClassList(includeWithDeps, excludeWithDeps, script):
            def evalPackagesConfig(excludeWithDeps, classList, variants):

                # Reading configuration
                partsCfg = self._job.get("packages/parts", {})

                # Expanding expressions
                self._console.debug("Expanding include expressions...")
                partIncludes = {}
                for partId in partsCfg:
                    partIncludes[partId] = textutil.expandGlobs(
                        partsCfg[partId]['include'], self._classesObj)

                # Computing packages
                #boot, partPackages, packageClasses = self._partBuilder.getPackages(partIncludes, excludeWithDeps, self._context, script)
                partPackages, _ = self._partBuilder.getPackages(
                    partIncludes, excludeWithDeps, self._context, script)
                packageClasses = script.packagesSorted()

                #return boot, partPackages, packageClasses
                return script.boot, script.parts, packageClasses

            # -----------------------------------------------------------
            classList = script.classes
            variants = script.variants
            self._partBuilder = PartBuilder(self._console, self._depLoader)

            # Check for a 'packages' configuration in the job
            if 0:
                # this branch should work, but doesn't;
                # create a synthetic job key and let evalPackagesConfig do the rest
                if not self._job.get("packages"):
                    package_config = {
                        "parts": {
                            "boot": {
                                "include": includeWithDeps
                            }
                        },
                        "init": "boot"
                    }
                    self._job.setFeature("packages", package_config)
                (
                    boot,
                    partPackages,  # partPackages[partId]=[0,1,3]
                    packageClasses  # packageClasses[0]=['qx.Class','qx.bom.Stylesheet',...]
                ) = evalPackagesConfig(excludeWithDeps, classList, variants)
            else:
                if self._job.get("packages"):
                    (
                        boot,
                        partPackages,  # partPackages[partId]=[0,1,3]
                        packageClasses  # packageClasses[0]=['qx.Class','qx.bom.Stylesheet',...]
                    ) = evalPackagesConfig(excludeWithDeps, classList,
                                           variants)
                else:
                    # Emulate a 'boot' part
                    boot = "boot"
                    partPackages = {"boot": [0]}
                    packageClasses = [classList]
                    # patch script object
                    script.boot = boot
                    packageObj = Package(0)
                    packageObj.classes = script.classesObj
                    script.packages.append(packageObj)
                    partObj = Part("boot")
                    partObj.packages.append(packageObj)
                    initial_deps = list(
                        set(includeWithDeps).difference(script.excludes)
                    )  # defining classes from config minus expanded excludes
                    partObj.initial_deps = initial_deps
                    partObj.deps = initial_deps[:]
                    script.parts = {"boot": partObj}

            return boot, partPackages, packageClasses
Exemple #18
0
    def _getPreviousCommonPackage(self, searchPackage, packages):
        # get the "smallest" package (in the sense of _sortPackages()) that is 
        # in all parts searchPackage is in, and is earlier in the corresponding
        # packages lists

        def isCommonAndGreaterPackage(searchPackage, package):  
            # the next takes advantage of the fact that the package id encodes
            # the parts a package is used by. if another package id has the
            # same bits turned on, it is in the same packages. this is only
            # true for the searchId package itself and package id's that have
            # more bits turned on (ie. are "greater"); hence, and due to 
            # _sortPackages, they are earlier in the packages list of the
            # corresponding parts
            if searchPackage.id & package.id == searchPackage.id:
                return True
            return False

        ##
        # check if the deps of searchPackage have deps to targetPackage - 
        # if merging searchPackage into targetPackage, this would be creating
        # circular dependencies

        def noCircularDeps(searchPackage, targetPackage):
            for package in searchPackage.packageDeps:
                if targetPackage in package.packageDeps:
                    return False
            return True

        ##
        # check that the targetPackage is loaded in (at least) those parts
        # where searchPackage's deps are also loaded

        def depsAvailWhereTarget (searchPackage, targetPackage):
            for depsPackage in searchPackage.packageDeps:
                if not isCommonAndGreaterPackage(targetPackage, depsPackage):
                #if not targetPackage.id & depsPackage.id == targetPackage.id:
                    return False
            return True

        # ----------------------------------------------------------------------

        allPackages  = reversed(Package.simpleSort(packages))
                                # sorting and reversing assures we try "smaller" package id's first
        additional_constraints = self._jobconf.get("packages/additional-merge-constraints", False)

        for targetPackage in allPackages:
            if searchPackage.id == targetPackage.id:  # no self-merging ;)
                continue
            if not isCommonAndGreaterPackage(searchPackage, targetPackage):
                self._console.debug("Problematic #%d (different parts using)" % targetPackage.id)
                continue
            if not noCircularDeps(searchPackage, targetPackage):
                self._console.debug("Problematic #%d (circular dependencies)" % targetPackage.id)
                if additional_constraints:
                    continue
            if not depsAvailWhereTarget(searchPackage, targetPackage):
                self._console.debug("Problematic #%d (dependencies not always available)" % targetPackage.id)
                if additional_constraints:
                    continue
            yield targetPackage

        yield None
Exemple #19
0
        def partsConfigFromClassList(includeWithDeps, excludeWithDeps, script):

            def evalPackagesConfig(excludeWithDeps, classList, variants):

                # Reading configuration
                partsCfg = self._job.get("packages/parts", {})

                # Expanding expressions
                self._console.debug("Expanding include expressions...")
                partIncludes = {}
                for partId in partsCfg:
                    partIncludes[partId] = textutil.expandGlobs(partsCfg[partId]['include'], self._classesObj)

                # Computing packages
                #boot, partPackages, packageClasses = self._partBuilder.getPackages(partIncludes, excludeWithDeps, self._context, script)
                partPackages, _ = self._partBuilder.getPackages(partIncludes, excludeWithDeps, self._context, script)
                packageClasses = script.packagesSorted()

                #return boot, partPackages, packageClasses
                return script.boot, script.parts, packageClasses


            # -----------------------------------------------------------
            classList  = script.classes
            variants   = script.variants
            self._partBuilder = PartBuilder(self._console, self._depLoader)

            # Check for a 'packages' configuration in the job
            if 0:
                # this branch should work, but doesn't;
                # create a synthetic job key and let evalPackagesConfig do the rest
                if not self._job.get("packages"):
                    package_config = {
                        "parts" : {
                            "boot" : {
                                "include" : includeWithDeps
                            }
                        },
                        "init" : "boot"
                    }
                    self._job.setFeature("packages", package_config)
                (boot,
                partPackages,           # partPackages[partId]=[0,1,3]
                packageClasses          # packageClasses[0]=['qx.Class','qx.bom.Stylesheet',...]
                )   = evalPackagesConfig(excludeWithDeps, classList, variants)
            else:
                if self._job.get("packages"):
                    (boot,
                    partPackages,           # partPackages[partId]=[0,1,3]
                    packageClasses          # packageClasses[0]=['qx.Class','qx.bom.Stylesheet',...]
                    )   = evalPackagesConfig(excludeWithDeps, classList, variants)
                else:
                    # Emulate a 'boot' part
                    boot           = "boot"
                    partPackages   = { "boot" : [0] }
                    packageClasses = [classList]
                    # patch script object
                    script.boot        = boot
                    packageObj         = Package(0)
                    packageObj.classes = script.classesObj
                    script.packages.append(packageObj)
                    partObj            = Part("boot")
                    partObj.packages.append(packageObj)
                    initial_deps = list(set(includeWithDeps).difference(script.excludes)) # defining classes from config minus expanded excludes
                    partObj.initial_deps = initial_deps
                    partObj.deps       = initial_deps[:]
                    script.parts       = { "boot" : partObj }

            return boot, partPackages, packageClasses