#!/usr/bin/env python3 # HACK: seems 'requests' module bundled with blender isn't bundled with 'idna' module. So force system python for now import sys sys.path.insert(0, '/usr/lib/python3.6/site-packages') import requests import json import os import ast import argparse import zipfile import logging log = logging.getLogger(__name__) def report(msg): # if __name__ == '__main__': print("blenderpack:", msg) def fatal_report(msg, code=1): report(msg) exit(code) def fetch(url): # TODO: do conditional request re = requests.get(url) print(re.json()) def parse_blinfo(source, addon_name="unknown"): """Parse a python file and return its bl_info dict, if there is one (else return None)""" try: tree = ast.parse(source) except SyntaxError as ex: log.warning('Skipping addon: SyntaxError in %s: %s', addon_name, ex) return None for body in tree.body: if body.__class__ != ast.Assign: continue if len(body.targets) != 1: continue if getattr(body.targets[0], 'id', '') != 'bl_info': continue return ast.literal_eval(body.value) log.warning('Unable to find bl_info dict in %s', addon_name) return None def extract_blinfo(path): """Extract bl_info dict from addon at path (can be single file, module, or zip)""" source = None # get last component of path, even with trailing slash addon_name = os.path.split(path.rstrip(os.path.sep))[1] if os.path.isdir(path): with open(os.path.join(path, '__init__.py' 'r')) as f: source = f.read() else: # HACK: perhaps not the best approach determining filetype..? try: with zipfile.ZipFile(path, 'r') as z: for fname in z.namelist(): # HACK: this seems potentially fragile; depends on zipfile listing root contents first if fname.endswith('__init__.py'): source = z.read(fname) break except zipfile.BadZipFile: with open(path, 'r') as f: source = f.read() if source == None: raise RuntimeError("Could not read addon '%s'" % addon_name) return parse_blinfo(source, addon_name) def make_repo(path): """Make repo.json for files in directory 'path'""" # try: for addon in os.listdir(path): extract_blinfo(os.path.join(path, addon)) # except FileNotFoundError: # fatal_report("No such file or directory: '%s'" % path) def main(): pass # print(args) if __name__ == '__main__': parser = argparse.ArgumentParser(description='Search, install, and manage packages for Blender') subparsers = parser.add_subparsers() make = subparsers.add_parser('make') make.add_argument('path') make.set_defaults(func=lambda args: make_repo(args.path)) args = parser.parse_args() args.func(args) main()