Exemple #1
0
    def storeKernel(self, fileName, bootCode=""):

        Console.info("Storing kernel...")
        Console.indent()

        # Export all field data for the kernel
        classes = []
        fieldSetupClasses = self.__session.getFieldSetupClasses()
        for fieldName in fieldSetupClasses:
            classes.append(fieldSetupClasses[fieldName])

        # Transfer all hard-wired fields into a permutation
        self.__session.setStaticPermutation()

        # Sort and compress
        sortedClasses = self.__buildClassList(classes, bootCode, inlineTranslations=True)
        
        Console.info("Compressing %s classes...", len(sortedClasses))
        compressedCode = self.__compressClasses(sortedClasses)

        # Write file to disk
        self.__fileManager.writeFile(fileName, compressedCode)

        # Remember kernel level classes
        self.__kernelClasses = sortedClasses

        Console.outdent()
Exemple #2
0
def compute(tree):
    Console.info("Resolving variables...")
    Console.indent()

    __computeRecurser(tree, None, {})

    Console.outdent()
    def __generateFeed(self):
        if not self.__posts:
            return

        Console.info("Generating feed...")
        Console.indent()

        itemsInFeed = self.config["blog"]["itemsInFeed"]
        destinationPath = self.__profile.getDestinationPath()

        for language in self.__languages:
            sortedPosts = self.__getSortedPosts(language)

            # Feed Render Model
            renderModel = {
                'config' : self.config,
                'site' : {
                    'name' : self.__siteName,
                    'url' : self.__siteUrl
                },
                "current" : {
                    "lang" : language
                },
                "feedUrl" : self.__feedUrl,
                "now" : datetime.datetime.now(tz=dateutil.tz.tzlocal()).replace(microsecond=0).isoformat(),
                "posts" : sortedPosts[0:itemsInFeed]
            }

            template = self.__templates["%s.Feed" % self.__theme]
            outputContent = template.render(renderModel)
            outputFilename = os.path.join(destinationPath, self.__feedUrl)
            self.__fileManager.writeFile(outputFilename, outputContent)

        Console.outdent()
Exemple #4
0
 def checkSingleInstallation(keys, versions, packageName, minVersion,
                             installPath, updatePath):
     Console.info('%s:' % packageName)
     Console.indent()
     if packageName.lower() in keys:
         Console.info(Console.colorize('Found installation', "green"))
         if LooseVersion(minVersion) > LooseVersion("0.0"):
             if LooseVersion(versions[packageName.lower()]) >= LooseVersion(
                     minVersion):
                 Console.info(
                     Console.colorize(
                         'Version is OK (needed: %s installed: %s)' %
                         (minVersion, versions[packageName.lower()]),
                         "green"))
             else:
                 Console.info(
                     Console.colorize(
                         Console.colorize(
                             '- Version is NOT OK (needed: %s installed: %s)'
                             % (minVersion, versions[packageName.lower()]),
                             "red"), "bold"))
                 Console.info(
                     'Update to the newest version of %s using %s' %
                     (packageName, updatePath))
     else:
         Console.info(
             Console.colorize(
                 Console.colorize('Did NOT find installation', "red"),
                 "bold"))
         Console.info('Install the newest version of %s using %s' %
                      (packageName, installPath))
     Console.outdent()
Exemple #5
0
    def __addDir(self, directory, regex, type, package):
        check = re.compile(regex)

        path = os.path.join(self.__path, directory)
        if not os.path.exists(path):
            return

        Console.debug("Scanning directory: %s" % directory)
        Console.indent()

        for dirPath, dirNames, fileNames in os.walk(path):
            for dirName in dirNames:
                # Filter dotted directories like .git, .bzr, .hg, .svn, etc.
                if dirName.startswith("."):
                    dirNames.remove(dirName)

            relDirPath = os.path.relpath(dirPath, path)

            for fileName in fileNames:

                if fileName[0] == ".":
                    continue

                relPath = os.path.normpath(os.path.join(relDirPath, fileName)).replace(os.sep, "/")

                if not check.match(os.path.join(directory, relPath).replace(os.sep, "/")):
                    continue

                fullPath = os.path.join(dirPath, fileName)
                self.addFile(relPath, fullPath, type, package)

        Console.outdent()
Exemple #6
0
    def __getOptimizedTree(self, permutation=None, context=None):
        """Returns an optimized tree with permutations applied"""

        field = "opt-tree[%s]-%s" % (self.id, permutation)
        tree = self.project.getCache().read(field, self.mtime)
        if not tree:
            tree = copy.deepcopy(self.__getTree("%s:plain" % context))

            # Logging
            msg = "Processing class %s" % Console.colorize(self.id, "bold")
            if permutation:
                msg += Console.colorize(" (%s)" % permutation, "grey")
            if context:
                msg += Console.colorize(" [%s]" % context, "cyan")
                
            Console.info("%s..." % msg)
            Console.indent()

            # Apply permutation
            if permutation:
                Console.debug("Patching tree with permutation: %s", permutation)
                Console.indent()
                jasy.js.clean.Permutate.patch(tree, permutation)
                Console.outdent()

            # Cleanups
            jasy.js.clean.DeadCode.cleanup(tree)
            ScopeScanner.scan(tree)
            jasy.js.clean.Unused.cleanup(tree)
        
            self.project.getCache().store(field, tree, self.mtime, True)
            Console.outdent()

        return tree
Exemple #7
0
    def __resolve(project):

        name = project.getName()

        # List of required projects
        Console.info("Getting requirements of %s...", Console.colorize(name, "bold"))
        Console.indent()
        requires = project.getRequires(checkoutDirectory, updateRepositories)
        Console.outdent()

        if not requires:
            return

        Console.debug("Processing %s requirements...", len(requires))
        Console.indent()

        # Adding all project in reverse order.
        # Adding all local ones first before going down to their requirements
        for requiredProject in reversed(requires):
            requiredName = requiredProject.getName()
            if not requiredName in names:
                Console.debug("Adding: %s %s (via %s)", requiredName, requiredProject.version, project.getName())
                names[requiredName] = True
                result.append(requiredProject)
            else:
                Console.debug("Blocking: %s %s (via %s)", requiredName, requiredProject.version, project.getName())

        # Process all requirements of added projects
        for requiredProject in requires:
            if requiredProject.hasRequires():
                __resolve(requiredProject)

        Console.outdent()
Exemple #8
0
    def __addContent(self, content):
        Console.info("Adding manual content")

        Console.indent()
        for fileId in content:
            entry = content[fileId]
            if not isinstance(entry, dict):
                raise UserError("Invalid manual content section for file %s. Requires a dict with type and source definition!" % fileId)

            itemType = entry["type"]
            fileContent = entry["source"]

            if len(fileContent) == 0:
                raise UserError("Empty content!")

            # Support for joining text content
            if len(fileContent) == 1:
                filePath = os.path.join(self.__path, fileContent[0])
            else:
                filePath = [os.path.join(self.__path, filePart) for filePart in fileContent]

            name, construct = self.__resolveConstructor(itemType)
            item = construct(self, fileId).attach(filePath)
            Console.debug("Registering %s %s" % (item.kind, fileId))

            if not itemType in self.items:
                self.items[itemType] = {}

            # Check for duplication
            if fileId in self.items[itemType]:
                raise UserError("Item ID was registered before: %s" % fileId)

            self.items[itemType][fileId] = item

        Console.outdent()
Exemple #9
0
def cleanup(node):
    """
    """
    
    if not hasattr(node, "variables"):
        ScopeScanner.scan(node)

    # Re cleanup until nothing to remove is found
    iteration = 0
    cleaned = False
    
    Console.info("Removing unused variables...")
    Console.indent()

    while True:
        iteration += 1

        modified = __cleanup(node)
        if modified > 0:
            Console.info("Removed %s unused variables", modified)
            ScopeScanner.scan(node)
            cleaned = True
        else:
            break
        
    Console.outdent()

    return cleaned
Exemple #10
0
def cleanup(node):
    """"""

    if not hasattr(node, "variables"):
        ScopeScanner.scan(node)

    # Re cleanup until nothing to remove is found
    x = 0
    cleaned = False

    Console.debug("Removing unused variables...")
    while True:
        x = x + 1
        #debug("Removing unused variables [Iteration: %s]...", x)
        Console.indent()

        if __cleanup(node):
            ScopeScanner.scan(node)
            cleaned = True
            Console.outdent()
        else:
            Console.outdent()
            break

    return cleaned
    def attach(self, path):

        # Call AbstractItem's attach method first
        super().attach(path)

        Console.debug("Loading translation file: %s", path)
        Console.indent()

        # Flat data strucuture where the keys are unique
        table = {}
        path = self.getPath()

        # Decide infrastructure/parser to use based on file name
        po = polib.pofile(path)
        Console.debug("Translated messages: %s=%s%%", self.language, po.percent_translated())

        for entry in po.translated_entries():
            entryId = generateMessageId(entry.msgid, entry.msgid_plural, entry.msgctxt)
            if entryId not in table:
                if entry.msgstr != "":
                    table[entryId] = entry.msgstr
                elif entry.msgstr_plural:
                    # This field contains all different plural cases (type=dict)
                    table[entryId] = entry.msgstr_plural

        Console.debug("Translation of %s entries ready" % len(table))
        Console.outdent()

        self.table = table

        return self
Exemple #12
0
    def getTranslationBundle(self, language=None):
        """Returns a translation object for the given language containing all relevant translation files for the current
        project set."""

        if language is None:
            return None

        if language in self.__translationBundles:
            return self.__translationBundles[language]

        Console.info("Creating translation bundle: %s", language)
        Console.indent()

        # Initialize new Translation object with no project assigned
        # This object is used to merge all seperate translation instances later on.
        combined = jasy.item.Translation.TranslationItem(None, id=language)
        relevantLanguages = self.__expandLanguage(language)

        # Loop structure is build to prefer finer language matching over project priority
        for currentLanguage in reversed(relevantLanguages):
            for project in self.__projects:
                for translation in project.getTranslations().values():
                    if translation.getLanguage() == currentLanguage:
                        Console.debug("Adding %s entries from %s @ %s...", len(translation.getTable()), currentLanguage, project.getName())
                        combined += translation

        Console.info("Combined number of translations: %s", len(combined.getTable()))
        Console.outdent()

        self.__translationBundles[language] = combined
        return combined
Exemple #13
0
    def init(self, autoInitialize=True, updateRepositories=True, scriptEnvironment=None):
        """
        Initialize the actual session with projects

        :param autoInitialize: Whether the projects should be automatically added when the current folder contains a valid Jasy project.
        :param updateRepositories: Whether to update repositories of all project dependencies.
        :param scriptEnvironment: API object as being used for loadLibrary to add Python features offered by projects.
        """

        self.__scriptEnvironment = scriptEnvironment
        self.__updateRepositories = updateRepositories

        if autoInitialize and jasy.core.Config.findConfig("jasyproject"):

            try:
                self.addProject(jasy.core.Project.getProjectFromPath("."))

            except UserError as err:
                Console.outdent(True)
                Console.error(err)
                raise UserError("Critical: Could not initialize session!")

            Console.info("Active projects (%s):", len(self.__projects))
            Console.indent()

            for project in self.__projects:
                if project.version:
                    Console.info("%s @ %s", Console.colorize(project.getName(), "bold"), Console.colorize(project.version, "magenta"))
                else:
                    Console.info(Console.colorize(project.getName(), "bold"))

            Console.outdent()        
Exemple #14
0
    def __generateTranslationBundle(self):
        """ 
        Returns a translation object for the given language containing 
        all relevant translation files for the current project set. 
        """

        language = self.getCurrentPermutation().get("locale")
        if language is None:
            return None

        if language in self.__translationBundles:
            return self.__translationBundles[language]

        Console.info("Creating translation bundle: %s", language)
        Console.indent()

        # Initialize new Translation object with no project assigned
        # This object is used to merge all seperate translation instances later on.
        combined = jasy.item.Translation.TranslationItem(None, id=language)
        relevantLanguages = self.__expandLanguage(language)

        # Loop structure is build to prefer finer language matching over project priority
        for currentLanguage in reversed(relevantLanguages):
            for project in self.__projects:
                for translation in project.getTranslations().values():
                    if translation.getLanguage() == currentLanguage:
                        Console.debug("Adding %s entries from %s @ %s...", len(translation.getTable()), currentLanguage, project.getName())
                        combined += translation

        Console.debug("Combined number of translations: %s", len(combined.getTable()))
        Console.outdent()

        self.__translationBundles[language] = combined
        return combined
Exemple #15
0
    def getApi(self, highlight=True):
        field = "api[%s]-%s" % (self.id, highlight)
        apidata = self.project.getCache().read(field,
                                               self.mtime,
                                               inMemory=False)
        if apidata is None:
            apidata = jasy.js.api.Data.ApiData(self.id, highlight)

            tree = self.__getTree(context="api")
            Console.indent()
            apidata.scanTree(tree)
            Console.outdent()

            metaData = self.getMetaData()
            apidata.addAssets(metaData.assets)
            for require in metaData.requires:
                apidata.addUses(require)
            for optional in metaData.optionals:
                apidata.removeUses(optional)

            apidata.addSize(self.getSize())
            apidata.addFields(self.getFields())

            self.project.getCache().store(field,
                                          apidata,
                                          self.mtime,
                                          inMemory=False)

        return apidata
Exemple #16
0
    def __addDir(self, directory, distname):
        
        Console.debug("Scanning directory: %s" % directory)
        Console.indent()
        
        path = os.path.join(self.__path, directory)
        if not os.path.exists(path):
            return
            
        for dirPath, dirNames, fileNames in os.walk(path):
            for dirName in dirNames:
                # Filter dotted directories like .git, .bzr, .hg, .svn, etc.
                if dirName.startswith("."):
                    dirNames.remove(dirName)

                # Filter sub projects
                if os.path.exists(os.path.join(dirPath, dirName, "jasyproject.json")):
                    dirNames.remove(dirName)
                    
            relDirPath = os.path.relpath(dirPath, path)

            for fileName in fileNames:
                
                if fileName[0] == ".":
                    continue
                    
                relPath = os.path.normpath(os.path.join(relDirPath, fileName)).replace(os.sep, "/")
                fullPath = os.path.join(dirPath, fileName)
                
                self.addFile(relPath, fullPath, distname)
        
        Console.outdent()
Exemple #17
0
    def __addDir(self, directory, distname):

        Console.debug("Scanning directory: %s" % directory)
        Console.indent()

        path = os.path.join(self.__path, directory)
        if not os.path.exists(path):
            return

        for dirPath, dirNames, fileNames in os.walk(path):
            for dirName in dirNames:
                # Filter dotted directories like .git, .bzr, .hg, .svn, etc.
                if dirName.startswith("."):
                    dirNames.remove(dirName)

                # Filter sub projects
                if os.path.exists(
                        os.path.join(dirPath, dirName, "jasyproject.json")):
                    dirNames.remove(dirName)

            relDirPath = os.path.relpath(dirPath, path)

            for fileName in fileNames:

                if fileName[0] == ".":
                    continue

                relPath = os.path.normpath(os.path.join(relDirPath,
                                                        fileName)).replace(
                                                            os.sep, "/")
                fullPath = os.path.join(dirPath, fileName)

                self.addFile(relPath, fullPath, distname)

        Console.outdent()
Exemple #18
0
    def generate(self, path='', autorotate=False, debug=False):
        """Generate sheets/variants"""

        Console.info('Generating sprite sheet variants...')
        Console.indent()

        sheets, count = self.packBest(autorotate)

        # Write PNG files
        data = {}
        for pos, sheet in enumerate(sheets):

            Console.info('Writing image (%dx%dpx) with %d images' %
                         (sheet.width, sheet.height, len(sheet)))
            name = 'jasysprite_%d.png' % pos

            # Export
            sheet.write(os.path.join(self.base, path, name), debug)
            data[name] = sheet.export()

        Console.outdent()

        # Generate JSON/YAML
        Console.info('Exporting data...')
        script = os.path.join(self.base, path,
                              'jasysprite.%s' % self.dataFormat)
        writeConfig(data, script)
Exemple #19
0
def cleanup(node):
    """"""

    if not hasattr(node, "variables"):
        ScopeScanner.scan(node)

    # Re cleanup until nothing to remove is found
    iteration = 0
    cleaned = False

    Console.debug("Removing unused variables...")
    Console.indent()

    while True:
        iteration += 1

        modified = __cleanup(node)
        if modified > 0:
            Console.debug("Removed %s unused variables", modified)
            ScopeScanner.scan(node)
            cleaned = True
        else:
            break

    Console.outdent()

    return cleaned
Exemple #20
0
    def __init__(self, session, assetManager=None, compressionLevel=1, formattingLevel=0):

        Console.info("Initializing OutputManager...")
        Console.indent()
        Console.info("Formatting Level: %s", formattingLevel)
        Console.info("Compression Level: %s", compressionLevel)

        self.__session = session

        self.__assetManager = assetManager
        self.__fileManager = FileManager(session)

        self.__scriptOptimization = Optimization()

        self.__compressGeneratedCode = False

        self.__kernelClasses = []

        if compressionLevel > 0:
            self.__scriptOptimization.enable("variables")
            self.__scriptOptimization.enable("declarations")

            self.__compressGeneratedCode = True

        if compressionLevel > 1:
            self.__scriptOptimization.enable("blocks")
            self.__scriptOptimization.enable("privates")

        self.__scriptFormatting = Formatting()

        if formattingLevel > 0:
            self.__scriptFormatting.enable("semicolon")
            self.__scriptFormatting.enable("comma")

        Console.outdent()
Exemple #21
0
    def __getOptimizedTree(self, permutation=None, context=None):
        """Returns an optimized tree with permutations applied"""

        field = "opt-tree[%s]-%s" % (self.id, permutation)
        tree = self.project.getCache().read(field, self.mtime)
        if not tree:
            tree = copy.deepcopy(self.__getTree("%s:plain" % context))

            # Logging
            msg = "Processing class %s" % Console.colorize(self.id, "bold")
            if permutation:
                msg += Console.colorize(" (%s)" % permutation, "grey")
            if context:
                msg += Console.colorize(" [%s]" % context, "cyan")

            Console.info("%s..." % msg)
            Console.indent()

            # Apply permutation
            if permutation:
                Console.debug("Patching tree with permutation: %s",
                              permutation)
                Console.indent()
                jasy.js.clean.Permutate.patch(tree, permutation)
                Console.outdent()

            # Cleanups
            jasy.js.clean.DeadCode.cleanup(tree)
            ScopeScanner.scan(tree)
            jasy.js.clean.Unused.cleanup(tree)

            self.project.getCache().store(field, tree, self.mtime, True)
            Console.outdent()

        return tree
Exemple #22
0
    def attach(self, path):

        # Call AbstractItem's attach method first
        super().attach(path)

        Console.debug("Loading translation file: %s", path)
        Console.indent()

        # Flat data strucuture where the keys are unique
        table = {}
        path = self.getPath()

        # Decide infrastructure/parser to use based on file name
        po = polib.pofile(path)
        Console.debug("Translated messages: %s=%s%%", self.language,
                      po.percent_translated())

        for entry in po.translated_entries():
            entryId = generateMessageId(entry.msgid, entry.msgid_plural,
                                        entry.msgctxt)
            if entryId not in table:
                if entry.msgstr != "":
                    table[entryId] = entry.msgstr
                elif entry.msgstr_plural:
                    # This field contains all different plural cases (type=dict)
                    table[entryId] = entry.msgstr_plural

        Console.debug("Translation of %s entries ready" % len(table))
        Console.outdent()

        self.table = table

        return self
Exemple #23
0
def cleanup(node):
    """"""

    if not hasattr(node, "variables"):
        ScopeScanner.scan(node)

    # Re cleanup until nothing to remove is found
    x = 0
    cleaned = False

    Console.debug("Removing unused variables...")
    while True:
        x = x + 1
        #debug("Removing unused variables [Iteration: %s]...", x)
        Console.indent()

        if __cleanup(node):
            ScopeScanner.scan(node)
            cleaned = True
            Console.outdent()
        else:
            Console.outdent()
            break

    return cleaned
Exemple #24
0
    def __init__(self, locale):
        Console.info("Parsing CLDR files for %s..." % locale)
        Console.indent()

        splits = locale.split("_")

        # Store for internal usage
        self.__locale = locale
        self.__language = splits[0]
        self.__territory = splits[1] if len(splits) > 1 else None

        # This will hold all data extracted data
        self.__data = {}

        # Add info section
        self.__data["info"] = {"LOCALE": self.__locale, "LANGUAGE": self.__language, "TERRITORY": self.__territory}

        # Add keys (fallback to C-default locale)
        path = "%s.xml" % os.path.join(CLDR_DIR, "keys", self.__language)
        try:
            Console.info("Processing %s..." % os.path.relpath(path, CLDR_DIR))
            tree = xml.etree.ElementTree.parse(path)
        except IOError:
            path = "%s.xml" % os.path.join(CLDR_DIR, "keys", "C")
            Console.info("Processing %s..." % os.path.relpath(path, CLDR_DIR))
            tree = xml.etree.ElementTree.parse(path)

        self.__data["key"] = {
            "Short": {key.get("type"): key.text for key in tree.findall("./keys/short/key")},
            "Full": {key.get("type"): key.text for key in tree.findall("./keys/full/key")},
        }

        # Add main CLDR data: Fallback chain for locales
        main = os.path.join(CLDR_DIR, "main")
        files = []
        while True:
            files.append("%s.xml" % os.path.join(main, locale))

            if "_" in locale:
                locale = locale[: locale.rindex("_")]
            else:
                break

        # Extend data with root data
        files.append(os.path.join(main, "root.xml"))

        # Finally import all these files in order
        for path in reversed(files):
            Console.info("Processing %s..." % os.path.relpath(path, CLDR_DIR))
            tree = xml.etree.ElementTree.parse(path)

            self.__addDisplayNames(tree)
            self.__addDelimiters(tree)
            self.__addCalendars(tree)
            self.__addNumbers(tree)

        # Add supplemental CLDR data
        self.__addSupplementals(self.__territory)

        Console.outdent()
    def generate(self, path='', debug=False):
        """Generate sheets/variants."""

        Console.info('Generating sprite sheet variants...')
        Console.indent()

        sheets, count = self.packBest()

        # Write PNG files
        data = {}
        for pos, sheet in enumerate(sheets):

            Console.info('Writing image (%dx%dpx) with %d images' % (sheet.width, sheet.height, len(sheet)))
            name = 'jasysprite_%d.png' % pos

            # Export
            sheet.write(os.path.join(self.base, path, name), debug)
            data[name] = sheet.export()

        Console.outdent()

        # Generate config file
        Console.info('Exporting data...')
        script = os.path.join(self.base, path, 'jasysprite.%s' % self.dataFormat)
        writeConfig(data, script)
Exemple #26
0
    def __addDir(self, directory, regex, type, package):
        check = re.compile(regex)

        path = os.path.join(self.__path, directory)
        if not os.path.exists(path):
            return

        Console.debug("Scanning directory: %s" % directory)
        Console.indent()

        for dirPath, dirNames, fileNames in os.walk(path):
            for dirName in dirNames:
                # Filter dotted directories like .git, .bzr, .hg, .svn, etc.
                if dirName.startswith("."):
                    dirNames.remove(dirName)

            relDirPath = os.path.relpath(dirPath, path)

            for fileName in fileNames:

                if fileName[0] == ".":
                    continue

                relPath = os.path.normpath(os.path.join(relDirPath,
                                                        fileName)).replace(
                                                            os.sep, "/")

                if not check.match(
                        os.path.join(directory, relPath).replace(os.sep, "/")):
                    continue

                fullPath = os.path.join(dirPath, fileName)
                self.addFile(relPath, fullPath, type, package)

        Console.outdent()
Exemple #27
0
    def processSprites(self):
        """Processes jasysprite files to merge sprite data into asset registry."""

        assets = self.__assets
        configs = [fileId for fileId in assets if assets[fileId].isImageSpriteConfig()]

        if configs:
            Console.info("Processing %s...", Console.colorize("%s sprites", "magenta") % len(configs))

        sprites = []
        Console.indent()
        for fileId in configs:
            Console.debug("Processing %s...", fileId)

            asset = assets[fileId]
            spriteBase = os.path.dirname(fileId)

            try:
                spriteConfig = asset.getParsedObject()
            except ValueError as err:
                raise UserError("Could not parse jasysprite at %s: %s" % (fileId, err))

            Console.indent()
            for spriteImage in spriteConfig:
                spriteImageId = "%s/%s" % (spriteBase, spriteImage)

                singleRelPaths = spriteConfig[spriteImage]
                Console.debug("Image %s combines %s images", spriteImageId, len(singleRelPaths))

                for singleRelPath in singleRelPaths:
                    singleId = "%s/%s" % (spriteBase, singleRelPath)
                    singleData = singleRelPaths[singleRelPath]
                    singleItem = assets[singleId]

                    # Verify that sprite sheet is up-to-date
                    fileChecksum = singleItem.getChecksum()
                    storedChecksum = singleData["checksum"]

                    Console.debug("Checksum Compare: %s <=> %s", fileChecksum, storedChecksum)
                    if storedChecksum != fileChecksum:
                        raise UserError("Sprite Sheet is not up-to-date. Checksum of %s differs." % singleId)

                    if spriteImageId not in sprites:
                        spriteImageIndex = len(sprites)
                        sprites.append(spriteImageId)
                    else:
                        spriteImageIndex = sprites.index(spriteImageId)

                    # Add relevant data to find image on sprite sheet
                    singleItem.addImageSpriteData(spriteImageIndex, singleData["left"], singleData["top"])

            Console.outdent()

            # The config file does not make any sense on the client side
            Console.debug("Deleting sprite config from assets: %s", fileId)
            del assets[fileId]

        Console.outdent()
        self.__sprites = sprites
Exemple #28
0
def executeCommand(args, failMessage=None, path=None, wrapOutput=True):
    """
    Executes the given process and outputs failMessage when errors happen.

    :param args:
    :type args: str or list
    :param failMessage: Message for exception when command fails
    :type failMessage: str
    :param path: Directory path where the command should be executed
    :type path: str
    :raise Exception: Raises an exception whenever the shell command fails in execution
    :type wrapOutput: bool
    :param wrapOutput: Whether shell output should be wrapped and returned (and passed through to Console.debug())

    """

    if isinstance(args, str):
        args = shlex.split(args)

    prevpath = os.getcwd()

    # Execute in custom directory
    if path:
        path = os.path.abspath(os.path.expanduser(path))
        os.chdir(path)

    Console.debug("Executing command: %s", " ".join(args))
    Console.indent()

    # Using shell on Windows to resolve binaries like "git"
    if not wrapOutput:
        returnValue = subprocess.call(args, shell=sys.platform == "win32")
        result = returnValue

    else:
        output = tempfile.TemporaryFile(mode="w+t")
        returnValue = subprocess.call(args,
                                      stdout=output,
                                      stderr=output,
                                      shell=sys.platform == "win32")

        output.seek(0)
        result = output.read().strip("\n\r")
        output.close()

    # Change back to previous path
    os.chdir(prevpath)

    if returnValue != 0 and failMessage:
        raise Exception("Error during executing shell command: %s (%s)" %
                        (failMessage, result))

    if wrapOutput:
        for line in result.splitlines():
            Console.debug(line)

    Console.outdent()

    return result
Exemple #29
0
    def storeKernel(self, fileName, classes=None, debug=False):
        """
        Writes a so-called kernel script to the given location. This script contains
        data about possible permutations based on current session values. It optionally
        might include asset data (useful when boot phase requires some assets) and 
        localization data (if only one locale is built).
        
        Optimization of the script is auto-enabled when no other information is given.
        
        This method returns the classes which are included by the script so you can 
        exclude it from the real other generated output files.
        """

        Console.info("Storing kernel...")
        Console.indent()

        # Use a new permutation based on debug settings and statically configured fields
        self.__session.setStaticPermutation(debug=debug)

        # Build resolver
        # We need the permutation here because the field configuration might rely on detection classes
        resolver = Resolver(self.__session)

        detectionClasses = self.__session.getFieldDetectionClasses()
        for className in detectionClasses:
            resolver.addClassName(className)

        # Jasy client side classes to hold data
        resolver.addClassName("jasy.Env")
        resolver.addClassName("jasy.Asset")
        resolver.addClassName("jasy.Translate")

        # Allow kernel level mass loading of scripts (required for source, useful for build)
        resolver.addClassName("core.io.Script")
        resolver.addClassName("core.io.Queue")

        if classes:
            for className in classes:
                resolver.addClassName(className)

        # Generate boot code
        bootCode = "jasy.Env.setFields(%s);" % self.__session.exportFields()

        if self.__compressGeneratedCode:
            bootCode = packCode(bootCode)

        # Sort resulting class list
        sortedClasses = resolver.getSortedClasses()
        self.storeCompressed(sortedClasses, fileName, bootCode)

        # Remember classes for filtering in storeLoader/storeCompressed
        self.__kernelClasses = set(sortedClasses)

        # Reset static permutation
        self.__session.resetCurrentPermutation()

        Console.outdent()
Exemple #30
0
    def storeKernel(self, fileName, classes=None, debug=False):
        """
        Writes a so-called kernel script to the given location. This script contains
        data about possible permutations based on current session values. It optionally
        might include asset data (useful when boot phase requires some assets) and 
        localization data (if only one locale is built).
        
        Optimization of the script is auto-enabled when no other information is given.
        
        This method returns the classes which are included by the script so you can 
        exclude it from the real other generated output files.
        """

        Console.info("Storing kernel...")
        Console.indent()

        # Use a new permutation based on debug settings and statically configured fields
        self.__session.setStaticPermutation(debug=debug)

        # Build resolver
        # We need the permutation here because the field configuration might rely on detection classes
        resolver = Resolver(self.__session)

        detectionClasses = self.__session.getFieldDetectionClasses()
        for className in detectionClasses:
            resolver.addClassName(className)

        # Jasy client side classes to hold data
        resolver.addClassName("jasy.Env")
        resolver.addClassName("jasy.Asset")
        resolver.addClassName("jasy.Translate")

        # Allow kernel level mass loading of scripts (required for source, useful for build)
        resolver.addClassName("core.io.Script")
        resolver.addClassName("core.io.Queue")

        if classes:
            for className in classes:
                resolver.addClassName(className)

        # Generate boot code
        bootCode = "jasy.Env.setFields(%s);" % self.__session.exportFields()

        if self.__compressGeneratedCode:
            bootCode = packCode(bootCode)

        # Sort resulting class list
        sortedClasses = resolver.getSortedClasses()
        self.storeCompressed(sortedClasses, fileName, bootCode)

        # Remember classes for filtering in storeLoader/storeCompressed
        self.__kernelClasses = set(sortedClasses)

        # Reset static permutation
        self.__session.resetCurrentPermutation()

        Console.outdent()
Exemple #31
0
    def export(self, path):
        Console.info("Writing result...")
        Console.info("Target directory: %s", path)
        Console.indent()

        jasy.core.File.write(os.path.join(path, "jasyproject.yaml"), 'name: locale\npackage: ""\n')
        count = self.__exportRecurser(self.__data, "locale", path)

        Console.info("Created %s classes", count)
        Console.outdent()
Exemple #32
0
def processSelectors(tree):
    """Processes all mixin includes inside selectors."""

    Console.info("Merging mixins into selectors")
    Console.indent()
    modified = __process(tree, scanMixins=False)
    Console.debug("Merged %s mixins", modified)
    Console.outdent()

    return modified
Exemple #33
0
def processMixins(tree):
    """Processes all mixin includes inside mixins."""

    Console.info("Merging mixins with each other...")
    Console.indent()
    modified = __process(tree, scanMixins=True)
    Console.debug("Merged %s mixins", modified)
    Console.outdent()

    return modified
Exemple #34
0
def processExtends(tree):
    """Processes all requests for mixin extends."""

    Console.info("Processing extend requests...")
    Console.indent()
    modified = __extend(tree)
    Console.debug("Processed %s selectors", modified)
    Console.outdent()

    return modified
Exemple #35
0
def processExtends(tree):
    """Processes all requests for mixin extends."""

    Console.info("Processing extend requests...")
    Console.indent()
    modified = __extend(tree)
    Console.debug("Processed %s selectors", modified)
    Console.outdent()

    return modified
Exemple #36
0
def processMixins(tree):
    """Processes all mixin includes inside mixins."""

    Console.info("Merging mixins with each other...")
    Console.indent()
    modified = __process(tree, scanMixins=True)
    Console.debug("Merged %s mixins", modified)
    Console.outdent()

    return modified
Exemple #37
0
def processSelectors(tree):
    """Processes all mixin includes inside selectors."""

    Console.info("Merging mixins into selectors")
    Console.indent()
    modified = __process(tree, scanMixins=False)
    Console.debug("Merged %s mixins", modified)
    Console.outdent()

    return modified
Exemple #38
0
def cleanup(node):
    """Reprocesses JavaScript to remove dead paths."""

    Console.debug("Removing dead code branches...")

    Console.indent()
    result = __cleanup(node)
    Console.outdent()

    return result
Exemple #39
0
    def storeCompressedScript(self, items, fileName, bootCode=""):

        Console.info("Generating compressed script...")
        Console.indent()

        sortedScripts = self.__sortScriptItems(items, bootCode, filterBy=self.__kernelScripts, inlineTranslations=True)
        compressedCode = self.__compressScripts(sortedScripts)
        self.__fileManager.writeFile(os.path.join(self.__outputPath, fileName), compressedCode)

        Console.outdent()
Exemple #40
0
    def storeLoaderScript(self, items, fileName, bootCode=""):

        Console.info("Generating loader script...")
        Console.indent()

        sortedScripts = self.__sortScriptItems(items, bootCode, filterBy=self.__kernelScripts)
        loaderCode = self.__generateScriptLoader(sortedScripts)
        self.__fileManager.writeFile(os.path.join(self.__outputPath, fileName), loaderCode)

        Console.outdent()
Exemple #41
0
    def clean(self):
        """Clears all caches of all registered projects"""

        Console.info("Cleaning session...")
        Console.indent()

        for project in self.__projects:
            project.clean()

        Console.outdent()
Exemple #42
0
def executeCommand(args, failMessage=None, path=None, wrapOutput=True):
    """
    Executes the given process and outputs failMessage when errors happen.

    :param args:
    :type args: str or list
    :param failMessage: Message for exception when command fails
    :type failMessage: str
    :param path: Directory path where the command should be executed
    :type path: str
    :raise Exception: Raises an exception whenever the shell command fails in execution
    :type wrapOutput: bool
    :param wrapOutput: Whether shell output should be wrapped and returned (and passed through to Console.debug())

    """

    if isinstance(args, str):
        args = shlex.split(args)

    prevpath = os.getcwd()

    # Execute in custom directory
    if path:
        path = os.path.abspath(os.path.expanduser(path))
        os.chdir(path)

    Console.debug("Executing command: %s", " ".join(args))
    Console.indent()

    # Using shell on Windows to resolve binaries like "git"
    if not wrapOutput:
        returnValue = subprocess.call(args, shell=sys.platform == "win32")
        result = returnValue

    else:
        output = tempfile.TemporaryFile(mode="w+t")
        returnValue = subprocess.call(args, stdout=output, stderr=output, shell=sys.platform == "win32")

        output.seek(0)
        result = output.read().strip("\n\r")
        output.close()

    # Change back to previous path
    os.chdir(prevpath)

    if returnValue != 0 and failMessage:
        raise Exception("Error during executing shell command: %s (%s)" % (failMessage, result))

    if wrapOutput:
        for line in result.splitlines():
            Console.debug(line)

    Console.outdent()

    return result
Exemple #43
0
    def export(self, path):
        Console.info("Writing result...")
        Console.info("Target directory: %s", path)
        Console.indent()

        jasy.core.File.write(os.path.join(path, "jasyproject.yaml"),
                             'name: locale\npackage: ""\n')
        count = self.__exportRecurser(self.__data, "locale", path)

        Console.info("Created %s classes", count)
        Console.outdent()
Exemple #44
0
    def __processAnimations(self):
        """Processes jasyanimation.json files to merge animation data into asset registry"""
        
        assets = self.__assets
        configs = [fileId for fileId in assets if assets[fileId].isImageAnimationConfig()]
        
        if configs:
            Console.info("Processing %s image animation configs...", len(configs))
        
        Console.indent()
        for fileId in configs:
            Console.debug("Processing %s...", fileId)
        
            asset = assets[fileId]
            base = os.path.dirname(fileId)
                
            try:
                config = json.loads(asset.getText())
            except ValueError as err:
                raise UserError("Could not parse jasyanimation.json at %s: %s" % (fileId, err))
            
            for relPath in config:
                imageId = "%s/%s" % (base, relPath)
                data = config[relPath]
                
                if not imageId in assets:
                    raise UserError("Unknown asset %s in %s" % (imageId, fileId))
                
                animationAsset = assets[imageId]
                
                if "rows" in data or "columns" in data:
                    rows = Util.getKey(data, "rows", 1)
                    columns = Util.getKey(data, "columns", 1)
                    frames = Util.getKey(data, "frames")
                    
                    animationAsset.addImageAnimationData(columns, rows, frames)
                    
                    if frames is None:
                        frames = rows * columns
                    
                elif "layout" in data:
                    layout = data["layout"]
                    animationAsset.addImageAnimationData(None, None, layout=layout)
                    frames = len(layout)
                    
                else:
                    raise UserError("Invalid image frame data for: %s" % imageId)

                Console.debug("  - Animation %s has %s frames", imageId, frames)

            Console.debug("  - Deleting animation config from assets: %s", fileId)
            del assets[fileId]
            
        Console.outdent()
Exemple #45
0
    def buildPart(self, partId, fileId):
        if not fileId:
            return

        Console.info("Generating style (%s)...", fileId)
        Console.indent()

        self.__profile.setWorkingPath(self.getWorkingPath())
        styleItems = StyleResolver.Resolver(self.__profile).add(fileId).getSorted()
        self.storeCompressedStylesheet(styleItems, "%s-{{id}}.css" % partId)

        Console.outdent()
Exemple #46
0
    def __outputContent(self):
        """Output processed content to HTML."""

        Console.info("Generating public files...")
        Console.indent()

        # self.__generatePosts()
        # self.__generateArchives()
        self.__generatePages()
        # self.__generateFeed()

        Console.outdent()
Exemple #47
0
    def close(self):
        """Closes the session and stores cache to the harddrive."""

        Console.debug("Closing session...")
        Console.indent()

        for project in self.__projects:
            project.close()

        self.__projects = None

        Console.outdent()
Exemple #48
0
def cleanup(node):
    """
    Reprocesses JavaScript to remove dead paths 
    """
    
    Console.debug("Removing dead code branches...")

    Console.indent()
    result = __cleanup(node)
    Console.outdent()

    return result
Exemple #49
0
    def storeCompressedStylesheet(self, styles, fileName):

        Console.info("Generating compressed stylesheet...")
        Console.indent()

        # Resolve placeholders first
        fileName = self.__profile.expandFileName(fileName)
        relativeToMain = self.__session.getMain().toRelativeUrl(fileName)

        compressedCode = self.__compressStyles(styles)
        self.__fileManager.writeFile(os.path.join(self.__outputPath, fileName), compressedCode)

        Console.outdent()
Exemple #50
0
    def clean(self):
        """Clears all caches of all registered projects"""

        if not self.__projects:
            return

        Console.info("Cleaning session...")
        Console.indent()

        for project in self.__projects:
            project.clean()

        Console.outdent()
Exemple #51
0
    def storeLoaderScript(self, items, fileName, bootCode=""):

        Console.info("Generating loader script...")
        Console.indent()

        sortedScripts = self.__sortScriptItems(items,
                                               bootCode,
                                               filterBy=self.__kernelScripts)
        loaderCode = self.__generateScriptLoader(sortedScripts)
        self.__fileManager.writeFile(os.path.join(self.__outputPath, fileName),
                                     loaderCode)

        Console.outdent()
Exemple #52
0
def executeCommand(args, failmsg=None, path=None):
    """
    Executes the given process and outputs failmsg when errors happen.
    Returns the combined shell output (stdout and strerr combined).

    :param args: 
    :type args: str or list
    :param failmsg: Message for exception when command fails
    :type failmsg: str
    :param path: Directory path where the command should be executed
    :type path: str
    :raise Exception: Raises an exception whenever the shell command fails in execution
    """

    if type(args) == str:
        args = shlex.split(args)

    prevpath = os.getcwd()

    # Execute in custom directory
    if path:
        path = os.path.abspath(os.path.expanduser(path))
        os.chdir(path)

    Console.debug("Executing command: %s", " ".join(args))
    Console.indent()

    # Using shell on Windows to resolve binaries like "git"
    output = tempfile.TemporaryFile(mode="w+t")
    returnValue = subprocess.call(args,
                                  stdout=output,
                                  stderr=output,
                                  shell=sys.platform == "win32")

    output.seek(0)
    result = output.read().strip("\n\r")
    output.close()

    # Change back to previous path
    os.chdir(prevpath)

    if returnValue != 0:
        raise Exception("Error during executing shell command: %s (%s)" %
                        (failmsg, result))

    for line in result.splitlines():
        Console.debug(line)

    Console.outdent()

    return result
Exemple #53
0
    def clear(self):
        """Removes all generated sprite files found in the base directory."""

        Console.info("Cleaning sprite files...")
        Console.indent()

        for dirPath, dirNames, fileNames in os.walk(self.base):
            for fileName in fileNames:
                if fileName.startswith("jasysprite"):
                    filePath = os.path.join(dirPath, fileName)
                    Console.debug("Removing file: %s", filePath)
                    os.remove(filePath)

        Console.outdent()
Exemple #54
0
    def __init__(self, port=8080, host="127.0.0.1", mimeTypes=None):

        Console.info("Initializing server...")
        Console.indent()

        # Shared configuration (global/app)
        self.__config = {
            "global": {
                "environment": "production",
                "log.screen": False,
                "server.socket_port": port,
                "server.socket_host": host,
                "engine.autoreload.on": False,
                "tools.encode.on": True,
                "tools.encode.encoding": "utf-8"
            },
            "/": {
                "log.screen": False
            }
        }

        self.__port = port

        # Build dict of content types to override native mimetype detection
        combinedTypes = {}
        combinedTypes.update(additionalContentTypes)
        if mimeTypes:
            combinedTypes.update(mimeTypes)

        # Update global config
        cherrypy.config.update(self.__config)

        # Somehow this screen disabling does not work
        # This hack to disable all access/error logging works
        def empty(*param, **args):
            pass

        def inspect(*param, **args):
            if args["severity"] > 20:
                Console.error("Critical error occoured:")
                Console.error(param[0])

        cherrypy.log.access = empty
        cherrypy.log.error = inspect
        cherrypy.log.screen = False

        # Basic routing
        self.__root = Static("/", {}, mimeTypes=combinedTypes)

        Console.outdent()
Exemple #55
0
    def storeCompressedScript(self, items, fileName, bootCode=""):

        Console.info("Generating compressed script...")
        Console.indent()

        sortedScripts = self.__sortScriptItems(items,
                                               bootCode,
                                               filterBy=self.__kernelScripts,
                                               inlineTranslations=True)
        compressedCode = self.__compressScripts(sortedScripts)
        self.__fileManager.writeFile(os.path.join(self.__outputPath, fileName),
                                     compressedCode)

        Console.outdent()
Exemple #56
0
    def packDir(self, path='', recursive=True, autorotate=False, debug=False):
        """Pack images inside a dir into sprite sheets"""

        Console.info('Packing sprites in: %s' % os.path.join(self.base, path))
        Console.indent()

        self.files = []
        self.addDir(path, recursive=recursive)
        Console.info('Found %d images' % len(self.files))

        if len(self.files) > 0:
            self.generate(path, autorotate, debug)

        Console.outdent()
Exemple #57
0
    def addProject(self, project):
        """
        Adds the given project to the list of known projects. Projects should be added in order of their priority. This
        adds the field configuration of each project to the session fields. Fields must not conflict between different
        projects (same name).

        :param project: Instance of Project to append to the list
        :type project: object

        """

        result = Project.getProjectDependencies(project, "external", self.__updateRepositories)
        for project in result:

            Console.info("Adding %s...", Console.colorize(project.getName(), "bold"))
            Console.indent()

            # Append to session list
            self.__projects.append(project)

            # Import library methods
            libraryPath = os.path.join(project.getPath(), "jasylibrary.py")
            if os.path.exists(libraryPath):
                self.loadLibrary(project.getName(), libraryPath, doc="Library of project %s" % project.getName())

            # Import command methods
            commandPath = os.path.join(project.getPath(), "jasycommand.py")
            if os.path.exists(commandPath):
                self.loadCommands(project.getName(), commandPath)

            # Import project defined fields which might be configured using "activateField()"
            fields = project.getFields()
            for name in fields:
                entry = fields[name]

                if name in self.__fields:
                    raise UserError("Field '%s' was already defined!" % (name))

                if "check" in entry:
                    check = entry["check"]
                    if check in ["Boolean", "String", "Number"] or isinstance(check, list):
                        pass
                    else:
                        raise UserError("Unsupported check: '%s' for field '%s'" % (check, name))

                self.__fields[name] = entry


            Console.outdent()
Exemple #58
0
    def close(self):
        """Closes the session and stores cache to the harddrive."""

        if not self.__projects:
            return

        Console.debug("Closing session...")
        Console.indent()

        for project in self.__projects:
            project.close()

        self.__projects = None

        Console.outdent()
Exemple #59
0
    def __addContent(self, content):
        Console.debug("Adding manual content")

        Console.indent()
        for fileId in content:
            fileContent = content[fileId]
            if len(fileContent) == 0:
                raise UserError("Empty content!")

            # If the user defines a file extension for JS public idenfiers
            # (which is not required) we filter them out
            if fileId.endswith(".js"):
                raise UserError(
                    "JavaScript files should define the exported name, not a file name: %s"
                    % fileId)

            fileExtension = os.path.splitext(fileContent[0])[1]

            # Support for joining text content
            if len(fileContent) == 1:
                filePath = os.path.join(self.__path, fileContent[0])
            else:
                filePath = [
                    os.path.join(self.__path, filePart)
                    for filePart in fileContent
                ]

            # Structure files
            if fileExtension in classExtensions:
                construct = jasy.item.Class.ClassItem
                dist = self.classes
            elif fileExtension in translationExtensions:
                construct = jasy.item.Translation.TranslationItem
                dist = self.translations
            else:
                construct = jasy.item.Asset.AssetItem
                dist = self.assets

            # Check for duplication
            if fileId in dist:
                raise UserError("Item ID was registered before: %s" % fileId)

            # Create instance
            item = construct(self, fileId).attach(filePath)
            Console.debug("Registering %s %s" % (item.kind, fileId))
            dist[fileId] = item

        Console.outdent()
Exemple #60
0
    def __getTree(self):
        """Returns the abstract syntax tree of the stylesheet."""

        field = "style:tree[%s]" % self.id
        tree = self.project.getCache().read(field, self.mtime)

        if not tree:
            Console.info("Parsing stylesheet %s...", Console.colorize(self.id, "bold"))

            Console.indent()
            tree = Engine.getTree(self.getText(), self.id)
            Console.outdent()

            self.project.getCache().store(field, tree, self.mtime, True)

        return tree