Store filelists in generated repositories

This commit is contained in:
Ellwood Zwovic
2017-07-19 16:51:32 -07:00
parent 390ad447e7
commit 20e5273635

View File

@@ -6,7 +6,6 @@ import zipfile
import ast import ast
import json import json
import logging import logging
from utils import *
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@@ -16,15 +15,15 @@ SCHEMA_VERSION = 1
class BadAddon(Exception): class BadAddon(Exception):
pass pass
def iter_addons(path: Path) -> (Path, dict): def iter_addons(path: Path) -> (Path, dict, list):
""" """
Generator, yields (path, bl_info) of blender addons in `path`. Generator, yields (path, bl_info, filelist) of blender addons in `path`.
""" """
for item in path.iterdir(): for item in path.iterdir():
try: try:
yield (item, extract_blinfo(item)) yield (item, extract_blinfo(item), get_filelist(item))
except BadAddon as err: except BadAddon as err:
log.debug("Skipping '{}': {}".format(item.name, err)) log.info("Skipping '{}': {}".format(item.name, err))
def parse_blinfo(source: str) -> dict: def parse_blinfo(source: str) -> dict:
"""Parse a python file and return its bl_info dict, if there is one (else return None)""" """Parse a python file and return its bl_info dict, if there is one (else return None)"""
@@ -46,6 +45,41 @@ def parse_blinfo(source: str) -> dict:
raise BadAddon('No bl_info found') raise BadAddon('No bl_info found')
def filelist_from_zip(zippath: Path) -> list:
"""Return list of files in the root of a zipfile"""
rootlist = []
with zipfile.ZipFile(str(zippath), 'r') as z:
for f in z.namelist():
# Get all names which have no path separators (root level files)
# or have a single path separator at the end (root level directories).
if len(f.rstrip('/').split('/')) == 1:
rootlist.append(f)
return rootlist
def get_filelist(addon_path: Path) -> list:
"""
Extract filelist from addon at path (can be single file, python package, or zip)
"""
if not addon_path.exists():
raise FileNotFoundError("Cannot extract blinfo from '%s'; no such file or directory" % addon_path)
if addon_path.is_dir():
return [str(addon_path)]
if addon_path.is_file():
ext = addon_path.suffix.lower()
if ext == '.zip':
return filelist_from_zip(addon_path)
elif ext == '.py':
return [str(addon_path)]
else:
raise BadAddon("File '%s' doesn't have a .zip or .py extension; not an addon" % addon_path)
# This should not happen
raise RuntimeError("Could not read addon '%s'" % addon_path.name)
def blinfo_from_zip(item: Path) -> dict: def blinfo_from_zip(item: Path) -> dict:
try: try:
@@ -115,7 +149,8 @@ class Package:
def __init__(self, path: Path, bl_info: dict): def __init__(self, path: Path, bl_info: dict):
self.bl_info = bl_info self.bl_info = bl_info
self.path = path self.path = path
self.url = None self.url = ""
self.files = []
def to_dict(self) -> dict: def to_dict(self) -> dict:
""" """
@@ -124,8 +159,14 @@ class Package:
return { return {
'bl_info': self.bl_info, 'bl_info': self.bl_info,
'url': self.url, 'url': self.url,
'files': self.files,
} }
# def raise_for_missing(self):
# """Ensure all fields are set"""
# if len(self.files) == 0:
# log.warning("Filelist for %s is empty", self.bl_info['name'])
class Repository: class Repository:
""" """
Stores repository metadata (including a list of packages) Stores repository metadata (including a list of packages)
@@ -171,17 +212,28 @@ def make_repo(path: Path, name: str, baseurl: str) -> Repository:
if not path.is_dir(): if not path.is_dir():
raise FileNotFoundError(path) raise FileNotFoundError(path)
for addon, bl_info in iter_addons(path): for addon_path, bl_info, filelist in iter_addons(path):
# Check if we have all bl_info fields we want # Check if we have all bl_info fields we want
if not REQUIRED_KEYS.issubset(set(bl_info)): if not REQUIRED_KEYS.issubset(set(bl_info)):
log.warning( log.warning(
"Required key(s) '{}' not found in bl_info of '{}'".format( "Skipping '{}': Required key(s) '{}' not found in bl_info".format(
"', '".join(REQUIRED_KEYS.difference(set(bl_info))), addon) addon_path,
"', '".join(REQUIRED_KEYS.difference(set(bl_info)))
)
) )
continue
package = Package(addon, bl_info) if addon_path.is_dir():
log.warning(
"Skipping '{}': Addon not zipped".format(addon_path)
)
continue
package = Package(addon_path, bl_info)
package.url = baseurl + package.path.name package.url = baseurl + package.path.name
package.files = filelist
repo.add_package(package) repo.add_package(package)
log.info("Repository generation successful") log.info("Repository generation successful")
@@ -210,7 +262,7 @@ def main():
args = parser.parse_args() args = parser.parse_args()
logging.basicConfig(format='%(levelname)8s: %(message)s', level=logging.INFO) logging.basicConfig(format='%(levelname)8s: %(message)s', level=logging.WARNING)
log.level += args.verbose log.level += args.verbose
if args.name is None: if args.name is None: