Better caching mechanics

This commit is contained in:
斟酌 鵬兄 2022-08-02 22:35:37 +09:00
parent 00180c815d
commit 70618b6b91
7 changed files with 104 additions and 38 deletions

View File

@ -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()

View File

@ -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()

View File

@ -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 ):

View File

@ -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 )

View File

@ -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
View 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
View 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()