Source code for cleanmymac.registry
#
# author: Cosmin Basca
#
# Copyright 2015 Cosmin Basca
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import os
from tabulate import tabulate
from yaml import load
from functools import partial
from pkg_resources import iter_entry_points
from cleanmymac.util import yaml_files
from cleanmymac.builtins import BUILTINS_PATH
from cleanmymac.log import debug, error
from cleanmymac.constants import TARGET_ENTRY_POINT, VALID_TARGET_TYPES, TYPE_TARGET_CMD, TYPE_TARGET_DIR, \
GLOBAL_CONFIG_FILE
from cleanmymac.schema import validate_yaml_target
from cleanmymac.target import Target, YamlShellCommandTarget, YamlDirTarget
__TARGETS__ = {}
__YAML_TYPES__ = {
TYPE_TARGET_CMD: YamlShellCommandTarget,
TYPE_TARGET_DIR: YamlDirTarget
}
[docs]def load_target(yaml_file, config, update=False, verbose=False, strict=True):
"""
load a target given its description from a **YAML** file.
The file is validated according to its type before loading.
:param str yaml_file: a valid path to a **YAML** file
:param dict config: the global configuration dictionary
:param bool update: specify whether to perform update before cleanup
:param bool verbose: toggle verbosity
:return: the target
:rtype: :class:`cleanmymac.target.Target`
"""
with open(yaml_file, 'r+') as DESC:
try:
description = load(DESC)
description = validate_yaml_target(description, strict=strict)
_type = description['type']
if _type not in VALID_TARGET_TYPES:
error('unknown yaml target type: "{0}", valid options are: {1}'.format(
_type, VALID_TARGET_TYPES
))
return None
target_class = __YAML_TYPES__[_type]
if not issubclass(target_class, Target):
error('expected a subclass of Target for "{0}", instead got: "{1}"'.format(
os.path.basename(yaml_file), target_class
))
return None
if not config:
config = {}
config['spec'] = description['spec']
return target_class(config, update=update, verbose=verbose)
except Exception as e:
error('Error loading configuration: "{0}". Reason: {1}'.format(yaml_file, e))
if strict:
raise e
return None
[docs]def register_target(name, target):
"""
register a target type to a given target name
:param str name: the target name (case sensitive)
:param target: the target to register
:type target: :class:`cleanmymac.target.Target`
"""
global __TARGETS__
if issubclass(target, Target):
debug('registering : {0}'.format(name))
__TARGETS__[name] = target
else:
error('target {0} is not of type Target, instead got: {1}'.format(name, target))
[docs]def register_yaml_targets(path):
"""
scans and registers all valid **YAML** defined targets in `path`. The name of the
**YAML** file (without extension) becomes the target name
:param str path: a valid directory
"""
global __TARGETS__
for name, yaml_file in yaml_files(path):
if os.path.basename(yaml_file) == GLOBAL_CONFIG_FILE:
continue
debug('registering : {0}'.format(name))
__TARGETS__[name] = partial(load_target, yaml_file)
[docs]def get_target(name):
"""
get a registered target
:param str name: the target name
:return: the target
:rtype: :class:`cleanmymac.target.Target`
"""
global __TARGETS__
try:
return __TARGETS__[name]
except KeyError:
error("no target found for: {0}".format(name))
return None
[docs]def iter_targets():
"""
generator over all registered targets
:return: pairs of (name: target)
"""
global __TARGETS__
for name, target in __TARGETS__.iteritems():
yield name, target
[docs]def get_targets_as_table(simple=True, fancy=False):
headers = ['Name', 'Type']
def row(name, target):
data = [name.upper()]
t = target(None, update=False, verbose=False, strict=False)
data.append(t.__class__.__name__ if simple else t.__class__)
return data
return tabulate([row(name, target) for name, target in __TARGETS__.iteritems()],
headers=headers, tablefmt='fancy_grid' if fancy else 'orgtbl')
# register built in targets
# 1 YAML based ones
register_yaml_targets(BUILTINS_PATH)
# register installed targets (if any)
debug("looking for registered cleanup targets...")
for ep in iter_entry_points(TARGET_ENTRY_POINT):
debug("found: {0}".format(ep))
register_target(ep.name, ep.load())