【问题标题】:Compute the number of source lines of code or blocks used in an App Inventor 2 project?计算 App Inventor 2 项目中使用的源代码行数或块数?
【发布时间】:2015-05-29 17:45:03
【问题描述】:

有没有什么方法可以计算 App Inventor 2 项目中使用的源代码行 (SLOC) 或块的数量?

【问题讨论】:

    标签: app-inventor


    【解决方案1】:

    我编写了一个 Python 函数 aia_count_blocks(aia_filename),通过计算 bky 文件中字符串 <block 的出现次数来计算给定 AIA 文件中的块数:

    from __future__ import print_function
    from __future__ import division
    
    import glob
    import ntpath
    import os
    import shutil
    import zipfile
    
    def unzip(source_filename, dest_dir):
        '''
        Source: http://stackoverflow.com/questions/12886768/how-to-unzip-file-in-python-on-all-oses
        '''
        with zipfile.ZipFile(source_filename) as zf:
            for member in zf.infolist():
                # Path traversal defense copied from
                # http://hg.python.org/cpython/file/tip/Lib/http/server.py#l789
                words = member.filename.split('/')
                path = dest_dir
                for word in words[:-1]:
                    drive, word = os.path.splitdrive(word)
                    head, word = os.path.split(word)
                    if word in (os.curdir, os.pardir, ''): continue
                    path = os.path.join(path, word)
                zf.extract(member, path)
    
    def list_subdirectories(dir):
        '''
        Source: http://stackoverflow.com/questions/800197/get-all-of-the-immediate-subdirectories-in-python
        '''
        return filter(os.path.isdir, [os.path.join(dir,f) for f in os.listdir(dir)])
    
    
    def path_leaf(path):
        '''
        Source: http://stackoverflow.com/questions/8384737/python-extract-file-name-from-path-no-matter-what-the-os-path-format
        '''
        head, tail = ntpath.split(path)
        return tail or ntpath.basename(head)
    
    def bky_count_blocks(bky_filename):
        return open(bky_filename).read().count('<block ')
    
    def aia_count_blocks(aia_filename):
        '''
        Count blocks in an AIA project 
        '''
    
        # unzip
        temp_folder = 'temp_aia'
        unzip(aia_filename, temp_folder)
    
        # Build path to .bky files, which contains all blocks for each screen of the AI2 project
        bky_files_path = os.path.join(temp_folder, 'src', 'appinventor', )
        for i in range(6): bky_files_path = list_subdirectories(bky_files_path)[0] # walk inside...
        #print(bky_files_path)    
    
        # Count
        total_blocks_count = 0
        bky_filenames = glob.glob(os.path.join(bky_files_path, '*.bky'))
        for bky_filename in bky_filenames :
            bky_block_count = bky_count_blocks(bky_filename)
            print('Screen {0} contains {1} blocks'.format(path_leaf(bky_filename), bky_block_count))
            total_blocks_count += bky_block_count
        print('The AIA project {0} contains {1} blocks spread across {2} screens.'.format(aia_filename, total_blocks_count, len(bky_filenames)))
    
        # Clean temp files
        shutil.rmtree(temp_folder)
    
    def main():
        '''
        This is the main function
        '''
        aia_filename = 'test.aia'
        aia_count_blocks(aia_filename)
    
    if __name__ == "__main__":
        main()
        #cProfile.run('main()') # if you want to do some profiling
    

    输出:

    Screen address.bky contains 42 blocks
    Screen edit.bky contains 265 blocks
    Screen list.bky contains 233 blocks
    Screen logic.bky contains 954 blocks
    Screen plan.bky contains 70 blocks
    Screen table1.bky contains 206 blocks
    Screen table2.bky contains 157 blocks
    Screen Screen1.bky contains 16 blocks
    The AIA project test.aia contains 1943 blocks spread across 8 screens.
    

    可能会有很多改进,例如避免计算禁用块、按块类型计数等。

    【讨论】:

    • 非常好!现在的问题是,我该如何使用它(没有任何 Python 知识)?
    • 0。将代码另存为 a.py(将 aia_filename = 'test.aia' 行替换为 .aia 文件名)1。安装pythonpython.org/downloads; 2. 将您的 .aia 与 a.py 放在同一文件夹中 3. 打开 shell/cmd 并转到包含 a.py 的同一文件夹 4. 运行 python a.py
    【解决方案2】:

    对于碰巧安装 Python 版本 3+ 而不是 2+ 的其他人

    找到这个

    return filter(os.path.isdir, [os.path.join(dir,f) for f in os.listdir(dir)])
    

    用这个替换

    return list(filter(os.path.isdir, [os.path.join(dir,f) for f in os.listdir(dir)]))
    

    【讨论】:

    • 感谢您的修复!
    猜你喜欢
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多