[Bf-blender-cvs] [dbe6331a3b9] soc-2017-package_manager: Refactor Package class
gandalf3
noreply at git.blender.org
Mon Aug 28 09:47:06 CEST 2017
Commit: dbe6331a3b9f9e262edf043f5a621a2a3ec6d925
Author: gandalf3
Date: Sun Aug 27 22:11:23 2017 -0700
Branches: soc-2017-package_manager
https://developer.blender.org/rBdbe6331a3b9f9e262edf043f5a621a2a3ec6d925
Refactor Package class
* Use property decorator
* Display an error when encountering an incorrectly formatted bl_info
* General cleanup
===================================================================
M release/scripts/modules/bpkg/__init__.py
M release/scripts/modules/bpkg/display.py
M release/scripts/modules/bpkg/types.py
M release/scripts/startup/bl_ui/space_userpref.py
===================================================================
diff --git a/release/scripts/modules/bpkg/__init__.py b/release/scripts/modules/bpkg/__init__.py
index d61a4627909..525acb7b6f2 100644
--- a/release/scripts/modules/bpkg/__init__.py
+++ b/release/scripts/modules/bpkg/__init__.py
@@ -5,6 +5,8 @@
from . import utils
from . import types
+from . import display
+from . import exceptions
from pathlib import Path
from collections import OrderedDict
import logging
@@ -29,13 +31,19 @@ def get_repositories() -> list:
def get_installed_packages(refresh=False) -> list:
"""Get list of packages installed on disk"""
+ log = logging.getLogger(__name__ + ".get_installed_packages")
import addon_utils
installed_pkgs = []
#TODO: just use addon_utils for now
for mod in addon_utils.modules(refresh=refresh):
- pkg = types.Package.from_module(mod)
- pkg.installed = True
- installed_pkgs.append(pkg)
+ try:
+ pkg = types.Package.from_module(mod)
+ except exceptions.PackageException as err:
+ msg = "Error parsing package \"{}\" ({}): {}".format(mod.__name__, mod.__file__, err)
+ display.pkg_errors.append(msg)
+ else:
+ pkg.installed = True
+ installed_pkgs.append(pkg)
return installed_pkgs
def _build_packagelist() -> dict: # {{{
@@ -45,6 +53,7 @@ def _build_packagelist() -> dict: # {{{
log = logging.getLogger(__name__ + "._build_packagelist")
masterlist = {}
+ display.pkg_errors.clear()
installed_packages = get_installed_packages(refresh=True)
known_repositories = get_repositories()
diff --git a/release/scripts/modules/bpkg/display.py b/release/scripts/modules/bpkg/display.py
index 188018f3232..b06784a3056 100644
--- a/release/scripts/modules/bpkg/display.py
+++ b/release/scripts/modules/bpkg/display.py
@@ -6,3 +6,14 @@ displayed_packages = []
expanded_packages = []
# name of package who's preferences are shown
preference_package = None
+
+
+#errors
+pkg_errors = []
+# def pkg_error(msg: str):
+# """Add a package related error message"""
+# _pkg_errors.append(msg)
+#
+# def pkg_errors() -> str:
+# """Return list of error messages related to packages"""
+# return _pkg_errors
diff --git a/release/scripts/modules/bpkg/types.py b/release/scripts/modules/bpkg/types.py
index 48a362c5c37..d4b1b182cf3 100644
--- a/release/scripts/modules/bpkg/types.py
+++ b/release/scripts/modules/bpkg/types.py
@@ -4,6 +4,7 @@ from pathlib import Path
from . import exceptions
from . import utils
from . import actions
+from . import display
class Package:
"""
@@ -12,61 +13,85 @@ class Package:
log = logging.getLogger(__name__ + ".Package")
- def __init__(self, package_dict:dict = None):
- self.bl_info = {}
- self.url = ""
- self.files = []
-
- self.repositories = set()
- self.installed_location = None
- self.module_name = None
-
+ def __init__(self):
+ self._bl_info = dict()
+
+ ## bl_infos ##
+ # required fields
+ self.name = str()
+ self.version = tuple()
+ self.blender = tuple()
+ # optional fields
+ self.description = str()
+ self.author = str()
+ self.category = str()
+ self.location = str()
+ self.support = 'COMMUNITY'
+ self.warning = str()
+ self.wiki_url = str()
+ self.tracker_url = str()
+
+ ## package stuff ##
+ self.url = str()
+ self.files = list()
+
+ ## package stuff which is not stored in repo ##
self.installed = False
+ self.installed_location = None
self.is_user = False
self.enabled = False
+ self.repositories = set()
- self.set_from_dict(package_dict)
-
- def test_is_user(self) -> bool:
- """Return true if package's install location is in user or preferences scripts path"""
- import bpy
- user_script_path = bpy.utils.script_path_user()
- prefs_script_path = bpy.utils.script_path_pref()
+ ## other ##
+ self.module_name = None
- if user_script_path is not None:
- in_user = Path(user_script_path) in Path(self.installed_location).parents
- else:
- in_user = False
+ def set_from_dict(self, package_dict: dict):
+ """
+ Get attributes from a dict such as produced by `to_dict`
+ """
+ if package_dict is None:
+ raise PackageException("Can't set package from None")
+
+ self.files = package_dict['files']
+ self.url = package_dict['url']
+ self.bl_info = package_dict['bl_info']
- if prefs_script_path is not None:
- in_prefs = Path(prefs_script_path) in Path(self.installed_location).parents
- else:
- in_prefs = False
+ @classmethod
+ def from_dict(cls, package_dict: dict):
+ """
+ Return a Package with values from dict
+ """
+ pkg = cls()
+ pkg.set_from_dict(package_dict)
+ return pkg
- return in_user or in_prefs
+ @classmethod
+ def from_blinfo(cls, blinfo: dict):
+ """
+ Return a Package with bl_info filled in
+ """
+ return cls.from_dict({'bl_info': blinfo})
- def test_enabled(self) -> bool:
- """Return true if package is enabled"""
- import bpy
- if self.module_name is not None:
- return (self.module_name in bpy.context.user_preferences.addons)
- else:
- return False
+ @classmethod
+ def from_module(cls, module):
+ """
+ Return a Package object from an addon module
+ """
+ from pathlib import Path
+ filepath = Path(module.__file__)
+ if filepath.name == '__init__.py':
+ filepath = filepath.parent
- def test_installed(self) -> bool:
- """Return true if package is installed"""
- import addon_utils
- return len([Package.from_module(mod) for mod in addon_utils.modules(refresh=False) if
- addon_utils.module_bl_info(mod)['name'] == self.name and
- addon_utils.module_bl_info(mod)['version'] == self.version]) > 0
+ pkg = cls()
+ pkg.files = [filepath.name]
+ pkg.installed_location = str(filepath)
+ pkg.module_name = module.__name__
- def set_installed_metadata(self, installed_pkg):
- """Sets metadata specific to installed packages from the Package given as `installed_pkg`"""
- self.installed = installed_pkg.test_installed()
- self.enabled = installed_pkg.test_enabled()
- self.is_user = installed_pkg.test_is_user()
- self.module_name = installed_pkg.module_name
- self.installed_location = installed_pkg.installed_location
+ try:
+ pkg.bl_info = module.bl_info
+ except AttributeError as err:
+ raise exceptions.PackageException("Module does not appear to be an addon; no bl_info attribute") from err
+ return pkg
def to_dict(self) -> dict:
"""
@@ -78,111 +103,176 @@ class Package:
'files': self.files,
}
- def set_from_dict(self, package_dict: dict):
- """
- Get attributes from a dict such as produced by `to_dict`
- """
- if package_dict is None:
- package_dict = {}
-
- for attr in ('files', 'url', 'bl_info'):
- if package_dict.get(attr) is not None:
- setattr(self, attr, package_dict[attr])
-
- # bl_info convenience getters {{{
+ # bl_info properties {{{
# required fields
@property
def name(self) -> str:
"""Get name from bl_info"""
- return self.bl_info.get('name')
+ return self._bl_info.get('name')
+ @name.setter
+ def name(self, name:str) -> str:
+ if type(name) != str:
+ raise exceptions.PackageException("refusing to set name to non str %s" % name)
+ self._bl_info['name'] = name
@property
def version(self) -> tuple:
"""Get version from bl_info"""
- return tuple(self.bl_info.get('version'))
+ return tuple(self._bl_info.get('version'))
+ @version.setter
+ def version(self, version:tuple) -> tuple:
+ if type(version) == str:
+ raise exceptions.PackageException("Refusing to set version to non tuple %s" % version)
+ self._bl_info['version'] = version
@property
def blender(self) -> tuple:
"""Get blender from bl_info"""
- return self.bl_info.get('blender')
+ return self._bl_info.get('blender')
+ @blender.setter
+ def blender(self, blender:tuple):
+ if type(blender) == str:
+ raise exceptions.PackageException("Refusing to set blender to non tuple %s" % blender)
+ self._bl_info['blender'] = blender
# optional fields
@property
def description(self) -> str:
"""Get description from bl_info"""
- return self.bl_info.get('description')
+ return self._bl_info.get('description')
+ @description.setter
+ def description(self, description:str):
+ self._bl_info['description'] = description
@property
def author(self) -> str:
"""Get author from bl_info"""
- return self.bl_info.get('author')
+ return self._bl_info.get('author')
+ @author.setter
+ def author(self, author:str):
+ self._bl_info['author'] = author
@property
def category(self) -> str:
"""Get category from bl_info"""
- return self.bl_info.get('category')
+ return self._bl_info.get('category')
+ @category.setter
+ def category(self, category:str):
+ self._bl_info['category'] = category
@property
def location(self) -> str:
"""Get location from bl_info"""
- return self.bl_info.get('location')
+ return self._bl_info.get('location')
+ @location.setter
+ def location(self, location:str):
+ self._bl_info['location'] = location
@property
def support(self) -> str:
"""Get support from bl_info"""
- return self.bl_info.get('support')
+ return self._
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list