Exemple #1
0
    def resume(self):
        """Resumes the session after it has been paused."""

        Console.info("Resuming session...")

        for project in self.__projects:
            project.resume()
    def build(self):
        """Build static website."""

        Console.info("Intializing Konstrukteur...")
        Console.indent()

        # Path configuration
        # TODO: Use Jasy configuration instead
        self.__templatePath = os.path.join("source", "template")
        self.__contentPath = os.path.join("source", "content")
        self.__sourcePath = os.path.join("source")

        self.__pagePath = os.path.join(self.__contentPath, "page")
        self.__postPath = os.path.join(self.__contentPath, "post")

        if not os.path.exists(self.__templatePath):
            raise RuntimeError("Path to templates not found : %s" % self.__templatePath)
        if not os.path.exists(self.__contentPath):
            raise RuntimeError("Path to content not found : %s" % self.__contentPath)

        # A theme could be any project registered in the current session
        if self.__theme:
            themeProject = session.getProjectByName(self.__theme)
            if not themeProject:
                raise RuntimeError("Theme '%s' not found" % self.__theme)

        self.__initializeTemplates()
        self.__generateOutput()
Exemple #3
0
    def deploy(self, classes, assetFolder=None):
        """
        Deploys all asset files to the destination asset folder. This merges
        assets from different projects into one destination folder.
        """

        # Sometimes it's called with explicit None - we want to fill the default
        # in that case as well.
        if assetFolder is None:
            assetFolder = "$prefix/asset"

        assets = self.__assets
        projects = self.__session.getProjects()

        copyAssetFolder = self.__session.expandFileName(assetFolder)
        filterExpr = self.__compileFilterExpr(classes)
        
        Console.info("Deploying assets...")
        
        counter = 0
        length = len(assets)
        
        for fileId in assets:
            if not filterExpr.match(fileId):
                length -= 1
                continue

            srcFile = assets[fileId].getPath()
            dstFile = os.path.join(copyAssetFolder, fileId.replace("/", os.sep))
            
            if jasy.core.File.syncfile(srcFile, dstFile):
                counter += 1
        
        Console.info("Updated %s/%s files" % (counter, length))
Exemple #4
0
    def resume(self):
        """Resumes the session after it has been paused."""

        Console.info("Resuming session...")

        for project in self.__projects:
            project.resume()
    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 #6
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 #7
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 #8
0
def compute(tree):
    Console.info("Resolving variables...")
    Console.indent()

    __computeRecurser(tree, None, {})

    Console.outdent()
Exemple #9
0
	def __build(self):
		""" Build static website """

		self.__parseContent()
		self.__outputContent()

		Console.info("Done processing website")
Exemple #10
0
    def deploy(self, classes, assetFolder=None):
        """
        Deploys all asset files to the destination asset folder. This merges
        assets from different projects into one destination folder.
        """

        # Sometimes it's called with explicit None - we want to fill the default
        # in that case as well.
        if assetFolder is None:
            assetFolder = "$prefix/asset"

        assets = self.__assets
        projects = self.__session.getProjects()

        copyAssetFolder = self.__session.expandFileName(assetFolder)
        filterExpr = self.__compileFilterExpr(classes)

        Console.info("Deploying assets...")

        counter = 0
        length = len(assets)

        for fileId in assets:
            if not filterExpr.match(fileId):
                length -= 1
                continue

            srcFile = assets[fileId].getPath()
            dstFile = os.path.join(copyAssetFolder,
                                   fileId.replace("/", os.sep))

            if jasy.core.File.syncfile(srcFile, dstFile):
                counter += 1

        Console.info("Updated %s/%s files" % (counter, length))
Exemple #11
0
    def getCompressed(self, profile):
        """Returns the compressed CSS code of this item."""

        field = "style:compressed[%s]-%s" % (self.id, profile.getId())
        mtime = self.getModificationTime(profile)

        compressed = self.project.getCache().read(field, mtime)

        if compressed is None:

            Console.info("Compressing tree %s...", Console.colorize(self.id, "bold"))

            # Start with the merged tree (includes resolved)
            tree = self.getMergedTree(profile)

            # Reduce tree
            Engine.reduceTree(tree, profile)

            # Compress tree
            compressed = Engine.compressTree(tree, profile.getCompressionLevel(), profile.getFormattingLevel())

            # Store in cache
            self.project.getCache().store(field, compressed, mtime)

        return compressed
Exemple #12
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 #13
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 #14
0
    def loadCommands(self, objectName, fileName, encoding="utf-8"):
        """Loads new commands into the session wide command registry."""

        counter = 0
        commands = self.__commands

        # Method for being used as a decorator to share methods to the outside
        def share(func):
            name = "%s.%s" % (objectName, func.__name__)
            if name in commands:
                raise Exception("Command %s already exists!" % name)

            commands[name] = func

            nonlocal counter
            counter += 1

            return func

        # Execute given file. Using clean new global environment
        # but add additional decorator for allowing to define shared methods
        # and the session object (self).
        code = open(fileName, "r", encoding=encoding).read()
        exec(compile(code, os.path.abspath(fileName), "exec"), {"share" : share, "session" : self})

        # Export destination name as global
        Console.info("Imported %s.", Console.colorize("%s commands" % counter, "magenta"))

        return counter
Exemple #15
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 #16
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 #17
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 #18
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 #19
0
 def removeDir(self, dirname):
     """Removes the given directory"""
     
     dirname = self.__session.expandFileName(dirname)
     if os.path.exists(dirname):
         Console.info("Deleting folder %s" % dirname)
         shutil.rmtree(dirname)
Exemple #20
0
 def removeFile(self, filename):
     """Removes the given file"""
     
     filename = self.__session.expandFileName(filename)
     if os.path.exists(filename):
         Console.info("Deleting file %s" % filename)
         os.remove(filename)
Exemple #21
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 #22
0
    def __init__(self, id, config, mimeTypes=None):
        self.id = id
        self.config = config
        self.mimeTypes = mimeTypes
        self.root = getKey(config, "root", ".")
        self.enableDebug = getKey(config, "debug", False)

        Console.info('Static "%s" => "%s" [debug:%s]', self.id, self.root, self.enableDebug)
Exemple #23
0
    def __init__(self, id, config, mimeTypes=None):
        self.id = id
        self.config = config
        self.mimeTypes = mimeTypes
        self.root = getKey(config, "root", ".")
        self.enableDebug = getKey(config, "debug", False)

        Console.info('Static "%s" => "%s" [debug:%s]', self.id, self.root,
                     self.enableDebug)
Exemple #24
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 #25
0
    def removeDir(self, dirname):
        """Removes the given directory."""

        if self.__profile:
            dirname = self.__profile.expandFileName(dirname)

        if os.path.exists(dirname):
            Console.info("Deleting folder %s" % dirname)
            shutil.rmtree(dirname)
Exemple #26
0
    def removeFile(self, filename):
        """Removes the given file."""

        if self.__profile:
            filename = self.__profile.expandFileName(filename)

        if os.path.exists(filename):
            Console.info("Deleting file %s" % filename)
            os.remove(filename)
Exemple #27
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 #28
0
def cacheManifest(profile):
	PREFIX = "{{prefix}}"
	HASH = "{{id}}"

	timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
	appcache = """CACHE MANIFEST

# Jasy AppCache Manifest file
# Version: {version}

CACHE:
{htmlfile}
{scripts}
{assets}

NETWORK:
*"""

	htmlcache = '<!DOCTYPE html><html manifest="{manifestfile}"></html>'

	destinationPath = profile.getDestinationPath()

	fileManager = FileManager(profile)
	session = profile.getSession()
	parts = profile.getParts()

	assetBuilder = AssetBuilder.AssetBuilder(profile)
	scriptBuilder = ScriptBuilder.ScriptBuilder(profile)
	styleBuilder = StyleBuilder.StyleBuilder(profile)

	assetManager = profile.getAssetManager()
	
	htmlfile = "index.html"

	for permutation in profile.permutate():
		scripts = []
		assets = []

		if KERNEL_NAME in parts:
			scripts.append("js/kernel.js")

		for part in parts:
			if part != KERNEL_NAME:
				scripts.append(profile.expandFileName("js/%s-{{id}}.js" % part))
				assets.append(profile.expandFileName("css/%s-{{id}}.css" % part))

		# TODO: How to get permutated asset list?
		for (srcFile, dstFile) in assetManager.getAssetList():
			assets.append(os.path.relpath(dstFile, profile.getDestinationPath()))

		appcacheFilename = "appcache-{{id}}.manifest"
		fileManager.writeFile(
			"{{destination}}/" + appcacheFilename,
			appcache.format(version=timestamp, htmlfile=htmlfile, scripts="\n".join(scripts), assets="\n".join(assets))
		)
		fileManager.writeFile("{{destination}}/index-{{id}}.html", htmlcache.format(manifestfile=profile.expandFileName(appcacheFilename)))
		Console.info("Generate manifest file...")
Exemple #29
0
    def pause(self):
        """
        Pauses the session. This release cache files etc. and makes 
        it possible to call other jasy processes on the same projects.
        """

        Console.info("Pausing session...")

        for project in self.__projects:
            project.pause()
Exemple #30
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 #31
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 #32
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 #33
0
    def __generateOutput(self):
        """Build static website."""

        Console.info("Building website....")
        Console.indent()

        self.__parseContent()
        self.__outputContent()

        Console.info("Website successfully build!")
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 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 #36
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 #37
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 #38
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 #39
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 #40
0
    def pause(self):
        """
        Pauses the session. This release cache files etc. and makes 
        it possible to call other jasy processes on the same projects.
        """
        
        Console.info("Pausing session...")

        for project in self.__projects:
            project.pause()
Exemple #41
0
def about():
    """Print outs the Jasy about page"""

    import jasy

    jasy.info()

    from jasy.env.Task import getCommand

    Console.info("Command: %s", getCommand())
    Console.info("Version: %s", jasy.__version__)
Exemple #42
0
def about():
    """Print outs the Jasy about page."""

    import jasy

    jasy.info()

    from jasy.env.Task import getCommand

    Console.info("Command: %s", getCommand())
    Console.info("Version: %s", jasy.__version__)
Exemple #43
0
        def on_deleted(self, event):
        super(JasyEventHandler, self).on_deleted(event)

        what = 'directory' if event.is_directory else 'file'
        Console.info("Deleted %s: %s", what, event.src_path)

        def on_modified(self, event):
        super(JasyEventHandler, self).on_modified(event)

        what = 'directory' if event.is_directory else 'file'
        Console.info("Modified %s: %s", what, event.src_path)
Exemple #44
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 #45
0
def mergeMixin(className, mixinName, classApi, mixinApi):
    Console.info("Merging %s into %s", mixinName, className)

    sectionLink = ["member", "property", "event"]

    for pos, section in enumerate(("members", "properties", "events")):
        mixinItems = getattr(mixinApi, section, None)
        if mixinItems:
            classItems = getattr(classApi, section, None)
            if not classItems:
                classItems = {}
                setattr(classApi, section, classItems)

            for name in mixinItems:

                # Overridden Check
                if name in classItems:

                    # If it was included, just store another origin
                    if "origin" in classItems[name]:
                        classItems[name]["origin"].append({
                            "name":
                            mixinName,
                            "link":
                            "%s:%s~%s" % (sectionLink[pos], mixinName, name)
                        })

                    # Otherwise add it to the overridden list
                    else:
                        if not "overridden" in classItems[name]:
                            classItems[name]["overridden"] = []

                        classItems[name]["overridden"].append({
                            "name":
                            mixinName,
                            "link":
                            "%s:%s~%s" % (sectionLink[pos], mixinName, name)
                        })

                # Remember where classes are included from
                else:
                    classItems[name] = {}
                    classItems[name].update(mixinItems[name])
                    if not "origin" in classItems[name]:
                        classItems[name]["origin"] = []

                    classItems[name]["origin"].append({
                        "name":
                        mixinName,
                        "link":
                        "%s:%s~%s" % (sectionLink[pos], mixinName, name)
                    })
Exemple #46
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 #47
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 #48
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 #49
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 #50
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 #51
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 #52
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 #53
0
    def default(self, *args, **query):
        """
        This method returns the content of existing files on the file system.

        Query string might be used for cache busting and are otherwise ignored.

        """

        # Append special header to all responses
        cherrypy.response.headers["X-Jasy-Version"] = jasyVersion

        # Enable cross domain access to this server
        enableCrossDomain()

        # When it's a file name in the local folder... load it
        if args:
            path = os.path.join(*args)
        else:
            path = "index.html"

        path = os.path.join(self.root, path)

        # Check for existance first
        if os.path.isfile(path):
            if self.enableDebug:
                Console.info("Serving file: %s", path)

            # Default content type to autodetection by Python mimetype API
            contentType = None

            # Support overriding by extensions
            extension = os.path.splitext(path)[1]
            if extension:
                extension = extension.lower()[1:]
                if extension in self.mimeTypes:
                    contentType = self.mimeTypes[
                        extension] + "; charset=" + locale.getpreferredencoding(
                        )

            return cherrypy.lib.static.serve_file(os.path.abspath(path),
                                                  content_type=contentType)

        # Otherwise return a classic 404
        else:
            if self.enableDebug:
                Console.warn("File at location %s not found at %s!", path,
                             os.path.abspath(path))

            raise cherrypy.NotFound(path)
Exemple #54
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 #55
0
    def loadLibrary(self, objectName, fileName, encoding="utf-8", doc=None):
        """
        Creates a new object inside the user API (jasyscript.py) with the given name
        containing all @share'd functions and fields loaded from the given file.
        """

        if objectName in self.__scriptEnvironment:
            raise UserError("Could not import library %s as the object name %s is already used." % (fileName, objectName))

        # Create internal class object for storing shared methods
        class Shared(object):
            pass
        exportedModule = Shared()
        exportedModule.__doc__ = doc or "Imported from %s" % os.path.relpath(fileName, os.getcwd())
        counter = 0

        # Method for being used as a decorator to share methods to the outside
        def share(func):
            nonlocal counter
            setattr(exportedModule, func.__name__, func)
            counter += 1

            return func

        def itemtype(type, name):
            def wrap(cls):
                id = "%s.%s" % (objectName, type[0].upper() + type[1:])
                self.addItemType(id, name, cls)
                return cls
            return wrap

        def postscan():
            def wrap(f):
                self.__postscans.append(f)
                return f
            return wrap

        # Execute given file. Using clean new global environment
        # but add additional decorator for allowing to define shared methods
        # and the session object (self).
        code = open(fileName, "r", encoding=encoding).read()
        exec(compile(code, os.path.abspath(fileName), "exec"), {"share" : share, "itemtype": itemtype, "postscan": postscan, "session" : self})

        # Export destination name as global
        self.__scriptEnvironment[objectName] = exportedModule

        Console.info("Imported %s.", Console.colorize("%s methods" % counter, "magenta"))

        return counter
Exemple #56
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
Exemple #57
0
    def __getTree(self, context=None):

        field = "tree[%s]" % self.id
        tree = self.project.getCache().read(field, self.mtime)
        if not tree:
            Console.info("Processing class %s %s...",
                         Console.colorize(self.id, "bold"),
                         Console.colorize("[%s]" % context, "cyan"))

            Console.indent()
            tree = Parser.parse(self.getText(), self.id)
            ScopeScanner.scan(tree)
            Console.outdent()

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

        return tree
Exemple #58
0
    def __getTree(self):
        """Returns the abstract syntax tree."""

        field = "script:tree[%s]" % self.id
        tree = self.project.getCache().read(field, self.mtime)
        if not tree:
            Console.info("Processing class %s...",
                         Console.colorize(self.id, "bold"))

            Console.indent()
            tree = Parser.parse(self.getText(), self.id)
            ScopeScanner.scan(tree)
            Console.outdent()

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

        return tree