This repository has been archived on 2023-02-07. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-package-manager-addon/blenderpack.py

133 lines
3.5 KiB
Python
Raw Normal View History

2017-06-22 01:43:08 -07:00
#!/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')
2017-06-22 01:43:08 -07:00
import requests
import json
import os
2017-06-23 20:05:10 -07:00
import pathlib
import ast
import argparse
import zipfile
import logging
log = logging.getLogger(__name__)
2017-06-23 13:23:11 -07:00
REQUIRED_KEYS = set(['name', 'blender', 'version'])
SCHEMA_VERSION = 1
class BadAddon(Exception):
pass
2017-06-22 01:43:08 -07:00
def fetch(url):
# TODO: do conditional request
re = requests.get(url)
print(re.json())
def parse_blinfo(source: str) -> dict:
"""Parse a python file and return its bl_info dict, if there is one (else return None)"""
tree = ast.parse(source)
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)
raise BadAddon('No bl_info found')
2017-06-23 20:05:10 -07:00
def extract_blinfo(path: pathlib.Path) -> dict:
"""Extract bl_info dict from addon at path (can be single file, module, or zip)"""
source = None
2017-06-23 20:05:10 -07:00
# get last component of path
addon_name = path.name
2017-06-23 20:05:10 -07:00
if path.is_dir():
with open(path / '__init__.py', 'r') as f:
source = f.read()
else:
# HACK: perhaps not the best approach determining filetype..?
try:
2017-06-23 20:05:10 -07:00
with zipfile.ZipFile(str(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:
2017-06-23 20:05:10 -07:00
with path.open() as f:
source = f.read()
if source == None:
raise RuntimeError("Could not read addon '%s'" % addon_name)
return parse_blinfo(source)
2017-06-23 20:05:10 -07:00
def make_repo(repopath: pathlib.Path):
"""Make repo.json for files in directory 'repopath'"""
repo_data = {}
package_data = []
2017-06-23 20:05:10 -07:00
if not repopath.is_dir():
raise FileNotFoundError(repopath)
2017-06-23 20:05:10 -07:00
for addon_path in repopath.iterdir():
package_datum = {}
addon = addon_path.name
try:
bl_info = extract_blinfo(addon_path)
except BadAddon as err:
log.warning('Could not extract bl_info from {}: {}'.format(addon_path, err))
continue
if not REQUIRED_KEYS.issubset(set(bl_info)):
log.warning(
"Required key(s) '{}' not found in bl_info of '{}'".format(
"', '".join(REQUIRED_KEYS.difference(set(bl_info))), addon)
)
package_datum['bl_info'] = bl_info
package_datum['type'] = 'addon'
package_data.append(package_datum)
repo_data['packages'] = package_data
2017-06-23 20:05:10 -07:00
with (repopath / 'repo.json').open('w', encoding='utf-8') as repo_file:
json.dump(repo_data, repo_file, indent=4, sort_keys=True)
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')
2017-06-23 20:05:10 -07:00
make.set_defaults(func=lambda args: make_repo(pathlib.Path(args.path)))
args = parser.parse_args()
args.func(args)
main()