forked from Botanical/BotanJS
Better caching mechanics
This commit is contained in:
parent
00180c815d
commit
70618b6b91
@ -1,11 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os;
|
||||
import re;
|
||||
import sys;
|
||||
import os, re, sys
|
||||
|
||||
from xml.dom import minidom
|
||||
from collections import defaultdict
|
||||
from botanjs.utils import checksum
|
||||
|
||||
RegEx_N = re.compile( r"""
|
||||
.*
|
||||
@ -136,7 +135,7 @@ class ClassMap:
|
||||
|
||||
return True;
|
||||
|
||||
def drawMap( self, ns, ci, ce, cf ):
|
||||
def drawMap( self, ns, ci, ce, cf, chksum ):
|
||||
nsNode = self.getNode( ns )
|
||||
|
||||
# Source every:
|
||||
@ -150,6 +149,8 @@ class ClassMap:
|
||||
|
||||
if not srcEvery:
|
||||
nsNode.setAttribute( "src", cf )
|
||||
nsNode.setAttribute( "js", chksum["js"] )
|
||||
nsNode.setAttribute( "css", chksum["css"] )
|
||||
|
||||
for ex in ce:
|
||||
_t = eDef[ ex[0] ]
|
||||
@ -164,6 +165,8 @@ class ClassMap:
|
||||
cNode.appendChild( impNode )
|
||||
|
||||
cNode.setAttribute( "src", cf )
|
||||
cNode.setAttribute( "js", chksum["js"] )
|
||||
cNode.setAttribute( "css", chksum["css"] )
|
||||
|
||||
# the file dose not export classes
|
||||
# Hence it import for itself
|
||||
@ -187,7 +190,12 @@ class ClassMap:
|
||||
continue
|
||||
|
||||
ns, ci, ce = classMeta( classFile )
|
||||
|
||||
chksum = {}
|
||||
chksum[ "js" ] = checksum( classFile )
|
||||
chksum[ "css" ] = checksum( classFile[:-2] + "css" )
|
||||
|
||||
classFile = classFile.replace( self.R + os.path.sep, "" )
|
||||
self.drawMap( ns, ci, ce, classFile )
|
||||
self.drawMap( ns, ci, ce, classFile, chksum )
|
||||
return self.DOM.toxml()
|
||||
|
||||
|
@ -4,11 +4,11 @@ import os
|
||||
from sys import platform
|
||||
from tempfile import NamedTemporaryFile
|
||||
from botanjs.config import Config as config
|
||||
from botanjs.service.jwork import log
|
||||
|
||||
COMPILER = config[ "BotanJS" ][ "ClosureCompiler" ]
|
||||
|
||||
if not os.path.isfile( COMPILER ):
|
||||
raise Exception( "Compiler not found" )
|
||||
AVAILABLE = os.path.isfile( COMPILER )
|
||||
|
||||
|
||||
COMPILER_OPTIONS = [
|
||||
@ -42,6 +42,11 @@ class Wrapper:
|
||||
break
|
||||
|
||||
def compress( self, loc ):
|
||||
|
||||
if not AVAILABLE:
|
||||
log.error( "Compiler not found" )
|
||||
return
|
||||
|
||||
content = ""
|
||||
with open( loc, "rb" ) as f:
|
||||
content = f.read()
|
||||
|
@ -1,7 +1,13 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
class log:
|
||||
def info( self, *args ):
|
||||
|
||||
@staticmethod
|
||||
def info( *args ):
|
||||
print( *args )
|
||||
|
||||
@staticmethod
|
||||
def error( *args ):
|
||||
print( *args )
|
||||
|
||||
class dummyTask( object ):
|
||||
|
@ -30,7 +30,11 @@ class Resolver:
|
||||
|
||||
def resource( self, elem ):
|
||||
if "src" in elem.attrib:
|
||||
return elem.attrib[ "src" ]
|
||||
return {
|
||||
"src": elem.attrib[ "src" ]
|
||||
, "js": elem.attrib[ "js" ]
|
||||
, "css": elem.attrib[ "css" ]
|
||||
}
|
||||
|
||||
parent = self.parentMap[ elem ]
|
||||
|
||||
@ -153,9 +157,10 @@ class BotanClassResolver:
|
||||
if src not in classFiles:
|
||||
classFiles.append( src )
|
||||
|
||||
def cssLookup( self, jsList, cssList ):
|
||||
def cssLookup( self, classList, cssList ):
|
||||
|
||||
for f in jsList:
|
||||
for cdef in classList:
|
||||
f = cdef[ "src" ]
|
||||
possibleList = []
|
||||
|
||||
cssFile = os.path.splitext( f )[0] + ".css"
|
||||
@ -183,7 +188,7 @@ class BotanClassResolver:
|
||||
if self.CR == None:
|
||||
return None
|
||||
|
||||
md5 = hashlib.md5( bytearray( "".join( fileList ), "utf-8" ) ).hexdigest()
|
||||
md5 = hashlib.md5( bytearray( "|".join( x[mode] for x in fileList ), "utf-8" ) ).hexdigest()
|
||||
|
||||
cName[0] = oFHash = md5 + "." + mode
|
||||
cFHash = md5 + ".c." + mode
|
||||
@ -193,19 +198,10 @@ class BotanClassResolver:
|
||||
# Compressed file
|
||||
cFile = os.path.join( self.CR, cFHash )
|
||||
|
||||
dates = list(
|
||||
os.path.getmtime( os.path.join( self.R, x ) )
|
||||
if os.path.exists( os.path.join( self.R, x ) ) else -1
|
||||
for x in fileList
|
||||
)
|
||||
|
||||
# Root file date
|
||||
dates.append( os.path.getmtime( os.path.join( self.R, "_this.js" ) ) );
|
||||
|
||||
if self.flagCompress and self.useCache( cFile, dates ):
|
||||
if self.flagCompress and self.useCache( cFile ):
|
||||
return self.BotanCache( cFile, cFHash, self.returnDynamic )
|
||||
|
||||
elif self.useCache( oFile, dates ):
|
||||
elif self.useCache( oFile ):
|
||||
self.JWork.saveCache(
|
||||
oFile
|
||||
# Content is None to initiate a compression
|
||||
@ -216,17 +212,8 @@ class BotanClassResolver:
|
||||
|
||||
return self.BotanCache( oFile, oFHash, False )
|
||||
|
||||
def useCache( self, f, dList ):
|
||||
if not os.path.exists( f ):
|
||||
return False
|
||||
|
||||
t = os.path.getmtime( f )
|
||||
|
||||
for i in dList:
|
||||
if t < i:
|
||||
return False
|
||||
|
||||
return True
|
||||
def useCache( self, f ):
|
||||
return os.path.exists( f )
|
||||
|
||||
def compileJs( self, cList, xList ):
|
||||
md5 = [ None ]
|
||||
@ -244,6 +231,7 @@ class BotanClassResolver:
|
||||
|
||||
|
||||
for f in cList:
|
||||
f = f[ "src" ]
|
||||
path = (
|
||||
os.path.splitext( f )[0]
|
||||
.replace( PY_SEP, "." )
|
||||
@ -285,8 +273,8 @@ class BotanClassResolver:
|
||||
if cacheFile != None:
|
||||
return cacheFile;
|
||||
|
||||
# The root file
|
||||
outputCss = self.BotanFile( "_this.css" )
|
||||
struct = "/* @ */"
|
||||
outputCss = struct + self.BotanFile( "_this.css" )
|
||||
|
||||
for f in self.cleanList( cList ):
|
||||
outputCss += self.BotanFile( f )
|
||||
|
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
from botanjs.compressor.closure import Wrapper as ClosureWrapper
|
||||
from botanjs.compressor.yui import Wrapper as YUIWrapper
|
||||
from botanjs.classmap import ClassMap
|
||||
|
||||
CeleryExists = True
|
||||
@ -38,6 +36,7 @@ class JWork:
|
||||
|
||||
@app.task()
|
||||
def compressJs( md5, externs ):
|
||||
from botanjs.compressor.closure import Wrapper as ClosureWrapper
|
||||
log.info( "Compress js: " + md5 )
|
||||
w = ClosureWrapper()
|
||||
w.scanExterns( externs )
|
||||
@ -45,6 +44,7 @@ class JWork:
|
||||
|
||||
@app.task()
|
||||
def compressCss( md5 ):
|
||||
from botanjs.compressor.yui import Wrapper as YUIWrapper
|
||||
log.info( "Compress css: " + md5 )
|
||||
w = YUIWrapper()
|
||||
w.compress( md5 )
|
||||
|
12
botanjs/utils.py
Normal file
12
botanjs/utils.py
Normal file
@ -0,0 +1,12 @@
|
||||
from functools import lru_cache
|
||||
from zlib import adler32 as _HashFunc
|
||||
HashFunc = lambda v: hex( _HashFunc( v ) )[2:]
|
||||
|
||||
|
||||
@lru_cache( maxsize = 1024 )
|
||||
def checksum( file_path ):
|
||||
try:
|
||||
with open( file_path, "rb" ) as f:
|
||||
return HashFunc( f.read() )
|
||||
except FileNotFoundError:
|
||||
return HashFunc( b"" )
|
47
tests.py
Normal file
47
tests.py
Normal file
@ -0,0 +1,47 @@
|
||||
#!env/bin/python
|
||||
import os, sys
|
||||
sys.path.append( os.path.abspath( "." ) )
|
||||
|
||||
from botanjs.service.jwork import app, JWork
|
||||
from botanjs.config import Config as config
|
||||
|
||||
SiteRoot = os.path.abspath( "." )
|
||||
|
||||
# Setting the SiteRoot for config
|
||||
config["Paths"]["SiteRoot"] = SiteRoot
|
||||
|
||||
jsCache = config["Paths"]["Cache"]
|
||||
jsRoot = config["BotanJS"]["SrcDir"]
|
||||
|
||||
bmap = os.path.join( jsCache, "botanjs", "bmap.xml" )
|
||||
|
||||
app.conf.update( broker_url = config["BotanJS"]["CeleryBroker"] )
|
||||
|
||||
JWork.buildClassMap.delay( jsRoot, bmap )
|
||||
|
||||
from botanjs.service.jclassresv import BotanClassResolver as JCResv
|
||||
srvHandler = JCResv( JWork, jsRoot, bmap, jsCache )
|
||||
|
||||
import unittest
|
||||
|
||||
class TestStringMethods( unittest.TestCase ):
|
||||
|
||||
# Run each twice to test the cache capabilities
|
||||
def test_ojscall( self ):
|
||||
for _ in range(0,2):
|
||||
s = srvHandler.getAPI( "System", mode = "rjs" )
|
||||
self.assertTrue( "BotanJS.define( \"System\" );" in s )
|
||||
|
||||
def test_import( self ):
|
||||
for _ in range(0,2):
|
||||
s = srvHandler.getAPI( "System.Policy", mode = "rjs" )
|
||||
self.assertTrue( "BotanJS.define( \"System.Policy\" );" in s )
|
||||
self.assertTrue( "BotanJS.define( \"System.Global\" );" in s )
|
||||
|
||||
def test_cssInheritance( self ):
|
||||
for _ in range(0,2):
|
||||
s = srvHandler.getAPI( "System", mode = "rcss" )
|
||||
self.assertTrue( "/* @ */" in s )
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
Loading…
Reference in New Issue
Block a user