Package: aiatools
AIA ToolsAIA Tools is a Python library for interacting with App Inventor Application (AIA) files in Python. It is useful for opening, summarizing, and analyzing AIA files for research inquiries. The query API is inspired by SQLalchemyInstalling$pipinstallaiatoolsFor development:$pyenvinstall3.6.3
$pyenvvirtualenv3.6.3aiatools
$pyenvactivateaiatools
$pipinstall-rrequirements.txt
$pipinstall.Usage ExamplesfromaiatoolsimportAIAFilewithAIAFile('MyProject.aia')asaia:print('Number of screens:%d\n'%len(aia.screens))print('Number of components:%d\n'%len(aia.screens['Screen1'].componentiter()))print('Number of blocks:%d\n'%len(aia.screens['Screen1'].blockiter()))print('Number of event blocks:%d\n'%len(aia.screens['Screen1'].blockiter(type='component_event')))aia.screens['Screen1'].blocks(type=='component_event').count(by='event_name')fromaiatoolsimportAIAFilefromaiatools.attributesimportevent_name,typefromaiatools.block_typesimport*fromaiatools.component_typesimport*aia=AIAFile('MyProject.aia')# Count the number of screensprintlen(aia.screens)# Count the number of distinct component types used on Screen1printaia.screens['Screen1'].components().count(group_by=type)# Count the number of Button components on Screen1printaia.screens['Screen1'].components(type==Button).count()# Count the number of component_event blocks, grouped by event nameprintaia.screens['Screen1'].blocks(type==component_event).count(group_by=event_name)# Compute the average depth of the blocks tree in Button.Click handlersprintaia.screens['Screen1'].blocks(type==component_event&&event_name==Button.Click).avg(depth)# Count the number of blocks referencing a specific componentprintaia.screens['Screen1'].components(name=='Button1').blocks().count()# Count the number of event handlers where the event opens another screenprintaia.blocks(type==component_event).descendants(type==control_openAnotherScreen).count()# Get the screens where the user has included more than one TinyDBprintaia.screens().components(type==TinyDB).count(group_by=Screen.name).filter(lambdak,v:v>1)Selectorsproject=AIAFile('project.aia')project.screens()# Select all screensproject.screens('Screen1')# Select Screen1project.screens(Button.any)# Select any screen with at least 1 buttonproject.screens(Control.open_another_screen)# Select any screen containing an open_another_screen blockproject.screens(Component.Name=='TinyDb1')# Select any screen containing a component named TinyDb1classBlock(object):""":py:class:`Block` represents an individual block in the blocks workspace... Arguments ::id_ The block IDtype_ :py:class:`BlockType` The block type"""def__init__(self,id_,type_):self.id=id_self.type=type_self.parent=Noneself.children=[]classComponent(object):""":py:class:`Component` represents a component in the designer view... Arguments ::id_type_ :py:class:`ComponentType`"""def__init__(self,id_,type_):self.id=id_self.type=type_self.properties={}classComponentContainer(Component):def__init__(self,id_,type_):super(self,ComponentContainer).__init__(id_,type_)self.components=[]classBlockType(object):def__init__(self,name):self.name=nameself.mutators=[]classComponentType(object):def__init__(self,name,class_name):self.name=nameself.class_name=class_nameclassScreen(object):def__init__(self,scm=None,bky=None):self.name=''self.properties={}self.components=FilterableDict()self.blocks=FilterableDict()self.top_blocks=FilterableDict()ifscmisnotNone:self._read_scheme(scm)ifbkyisnotNone:self._read_blocks(bky)classProject(object):def__init__(self,file=None):self.name=''self.screens=FilterableDict()self.components=FilterableDict()self.components.parent=self.screensself.blocks=FilterableDict()self.blocks.parent=self.screensiffileisnotNone:self.read(file)classFilterableDict(dict):def__call__(self,filter_):returnFilterableDict([k,vfork,vinself.iteritems()iffilter_(v)elseNone,None])classFilter(object):def__call__(self,o):throwNotImplementedError()def__and__(self,right):returnand_(self,right)def__or__(self,right):returnor_(self,right)def__eq__(self,right):returneq(self,right)def__ne__(self,right):returnne(self,right)def__lt__(self,right):returnlt(self,right)def__gt__(self,right):returngt(self,right)def__le__(self,right):returnle(self,right)def__ge__(self,right):returnge(self,right)classAndFilter(Filter):def__init__(self,l,r):self.l=lself.r=rdef__call__(self,o):returnself.l(o)andself.r(o)classOrFilter(Filter):def__init__(self,l,r):self.l=lself.r=rdef__call__(self,o):returnself.l(o)orself.r(o)classNotFilter(Filter):def__init__(self,expression):self.expression=expressiondef__call__(self,o):returnnotself.expression(o)classEqualFilter(Filter):def__init__(self,l,r):self.l=lself.r=rdef__call__(self,o):returnself.l(o)==self.r(o)classNotEqualFilter(Filter):def__init__(self,l,r):self.l=lself.r=rdef__call__(self,o):returnself.l(o)!=self.r(o)classLessThanFilter(Filter):def__init__(self,l,r):self.l=lself.r=rdef__call__(self,o):returnself.l(o)<self.r(o)classGreaterThanFilter(Filter):def__init__(self,l,r):self.l=lself.r=rdef__call__(self,o):returnself.l(o)>self.r(o)classLessThanOrEqualFilter(Filter):def__init__(self,l,r):self.l=lself.r=rdef__call__(self,o):returnself.l(o)<=self.r(o)classGreaterThanOrEqualFilter(Filter):def__init__(self,l,r):self.l=lself.r=rdef__call__(self,o):returnself.l(o)<=self.r(o)classScreenFilter(Filter):passclassComponentFilter(Filter):passclassBlockFilter(Filter):passAttributesdepth- For a component, this is the depth of the component hierarchy rooted at that component. For components that are not containers this value is always 1. For containers and blocks, this is the longest length of the paths from this root node to any of its leaf nodes.length- The number of direct descendants of the target. If the target is a component container, it will be the number of direct chidlren. For a block, it will be the number ofchildren- The list of children for the item(s) in the set. If more than one item is in the set, the children will be provided in the order of their parents.mutators- If the block has mutations, a list of strings indicating the types of the mutations, e.g. ['if', 'elseif', 'elseif', 'else'].callers- For procedures, the number of caller blocks in the workspace. For variables and component methods and properties, the number of getter blocks.Aggregationmax- Maximum value of the filtermin- Minimum value of the filteravg- Average value of the filtercount- Count of items matching the filtermedian- Median value of the attribute