2013-06-13 15:19:50 -04:00
import gzip
2013-06-13 14:43:47 -04:00
import os
import simplejson
from collections import namedtuple
PROJECT_DIR_PREFIX = ' /nfsmount/projectstore '
VERSION_DIR_PREFIX = ' /nfsmount/versionstore '
def calculate_project_dirpath ( prefix , project_id ) :
project_id = str ( project_id )
s = project_id . rjust ( 9 , ' 0 ' )
path = os . path . join ( prefix , s [ 0 : 2 ] , s [ 2 : 4 ] , s [ 4 : 6 ] , s [ 6 : 8 ] , s [ 8 : ] )
return path
class BaseObj ( object ) :
def __init__ ( self , info_dict ) :
self . _d = info_dict
def __getattr__ ( self , name ) :
2013-06-15 15:52:44 -04:00
if name in self . _d :
2013-06-13 14:43:47 -04:00
return self . _d [ name ]
else :
raise AttributeError
class ScratchObj ( BaseObj ) :
def __init__ ( self , info_dict ) :
BaseObj . __init__ ( self , info_dict )
@property
def variables ( self ) :
2013-06-18 20:07:22 +00:00
try :
return [ ScratchDataStructureObj ( x ) for x in self . _d [ ' variables ' ] ]
except KeyError :
return [ ]
2013-06-13 14:43:47 -04:00
class ScratchMediaObj ( BaseObj ) :
def __init__ ( self , info_dict ) :
BaseObj . __init__ ( self , info_dict )
class ScratchDataStructureObj ( BaseObj ) :
def __init__ ( self , info_dict ) :
BaseObj . __init__ ( self , info_dict )
class Sprite ( ScratchObj ) :
def __init__ ( self , sprite_dict ) :
ScratchObj . __init__ ( self , sprite_dict )
@property
def spriteInfo ( self ) :
return namedtuple ( ' SpriteInfo ' ,
self . _d [ ' info ' ] . keys ( ) ) ( * * ( self . _d [ ' info ' ] ) )
@property
def costumes ( self ) :
return [ ScratchMediaObj ( x ) for x in self . _d [ ' costumes ' ] ]
@property
def sounds ( self ) :
return [ ScratchMediaObj ( x ) for x in self . _d [ ' sounds ' ] ]
2013-06-19 20:22:40 -04:00
@property
def assets ( self ) :
return self . sounds + self . costumes
2013-06-13 14:43:47 -04:00
2013-06-13 15:19:50 -04:00
class Project ( ScratchObj ) :
def __init__ ( self , project_id ) :
self . project_id = project_id
self . _versions_cache = [ ]
2013-06-13 14:43:47 -04:00
filepath = \
os . path . join ( calculate_project_dirpath ( PROJECT_DIR_PREFIX ,
project_id ) , ' LATEST ' )
with open ( filepath ) as fp :
d = simplejson . loads ( fp . read ( ) )
ScratchObj . __init__ ( self , d )
2013-06-13 15:19:50 -04:00
@property
def versions ( self ) :
2013-06-15 15:52:44 -04:00
if self . _versions_cache :
2013-06-13 15:19:50 -04:00
return self . _versions_cache
dirname = calculate_project_dirpath ( VERSION_DIR_PREFIX ,
self . project_id )
files = os . listdir ( dirname )
files . sort ( )
for filename in files :
filepath = os . path . join ( dirname , filename )
with gzip . open ( filepath , ' rb ' ) as fp :
d = simplejson . loads ( fp . read ( ) )
self . _versions_cache . append ( { ' timestamp ' : int ( filename . replace ( ' .gz ' , ' ' ) ) ,
' revision ' : ProjectRevision ( d ) } )
return self . _versions_cache
2013-06-13 14:43:47 -04:00
@property
def info ( self ) :
return namedtuple ( ' ProjectInfo ' ,
self . _d [ ' info ' ] . keys ( ) ) ( * * ( self . _d [ ' info ' ] ) )
@property
def children ( self ) :
def convertChild ( child ) :
2013-06-15 15:52:44 -04:00
if ' spriteInfo ' in child :
2013-06-13 14:43:47 -04:00
return Sprite ( child )
else :
return BaseObj ( child )
2013-06-13 19:35:28 +00:00
2013-06-13 14:43:47 -04:00
return [ convertChild ( child ) for child in self . _d [ ' children ' ] ]
@property
def sprites ( self ) :
return [ Sprite ( x ) for x in self . _d [ ' children ' ] ]
2013-06-13 15:19:50 -04:00
class ProjectRevision ( Project ) :
def __init__ ( self , project_dict ) :
ScratchObj . __init__ ( self , project_dict )