# Path: pybombs/pb_logging.py
# BOLD = str('\033[1m')
# TRACE = 1
# class ColoredConsoleHandler(logging.StreamHandler):
# class PBLogger(logging.getLoggerClass()):
#     def emit(self, record):
#     def __init__(self, *args, **kwargs):
#     def trace(self, *args, **kwargs):
# 
# Path: pybombs/recipe_manager.py
# class RecipeListManager(object):
#     def __init__(self):
#     def get_recipe_filename(self, name):
#     def get_template_filename(self, template):
#     def list_all(self):
#     def _append_location(self, dirname):
# 
# Path: pybombs/config_manager.py
# def npath(path):
#     def __init__(self, args, cfg_list, select_prefix=None):
#     def _set_attrs(self):
#     def _merge_config_info_from_file(self, cfg_file, cfg_data):
#     def _find_prefix_dir(self, args):
#     def _detect_python_version(self):
#     def _detect_python_path(self):
#     def _load_environ_from_script(self, setup_env_file):
#     def _load_default_env(self, env):
#     def get_prefix_cfg_dir_writable(self):
#     def __init__(self, select_prefix=None):
#     def load(self, select_prefix=None):
#     def _append_cfg_from_file(self, cfg_filename, index=None):
#     def get_pybombs_dir(self, prefix_dir=None):
#     def get(self, key, default=None):
#     def keys(self):
#     def set(self, key, value):
#     def get_help(self, key):
#     def set_config_reference(self, ref):
#     def get_active_prefix(self):
#     def get_recipe_locations(self):
#     def get_named_recipe_dirs(self):
#     def get_named_recipe_sources(self):
#     def get_named_recipe_cfg_file(self, recipe_alias):
#     def get_template_dir(self):
#     def resolve_recipe_uri(self, uri, name, cache_dir):
#     def get_package_flags(self, pkgname, categoryname=None):
#     def get_python_version(self):
#     def get_satisfier_tags(self):
#     def update_cfg_file(self, new_data, cfg_file=None):
#     def setup_parser(self, parser):
# class PrefixInfo(object):
# class ConfigManager(object):
#     LAYER_DEFAULT = 0
#     LAYER_GLOBALS = 1
#     LAYER_HOME = 2
#     LAYER_PREFIX = 3
#     LAYER_CMDLINE_FILE = 4
#     LAYER_CMDLINE_ARGS = 5
#     LAYER_VOLATILE = 6
# 
# Path: pybombs/config_file.py
# class PBConfigFile(object):
#     """
#     Abstraction layer for our config and other files
#     """
#     def __init__(self, filename):
#         # Store normalized path, in case someone chdirs after calling the ctor
#         self._filename = os.path.abspath(os.path.expanduser(os.path.normpath(filename)))
#         self.data = None
#         self.yaml = AbstractYaml()
#         touch_file(filename)
#         with open(filename) as fn:
#             try:
#                 # TODO: Recursively turn this into an OrderedDict, not just at
#                 # top level. In a nested dict, some key elements will still be
#                 # ruamel.ordereddict.
#                 self.data = OrderedDict(self.yaml.load(fn.read()) or {})
#             except (IOError, OSError):
#                 self.data = OrderedDict()
#             except Exception as e:
#                 raise PBException("Error loading {0}: {1}".format(filename, str(e)))
#         assert isinstance(self.data, OrderedDict)
# 
#     def get(self, key=None, default=None):
#         " Return the data from the config file as a dict "
#         if key is None:
#             return self.data
#         if default is None:
#             default = OrderedDict()
#         # TODO Again, this is not recursive and sub-values may be non-vanilla
#         # ordered dicts
#         return OrderedDict(self.data.get(key, default))
# 
#     def save(self, newdata=None):
#         " Write the contents of the data cache to the file. "
#         if newdata is not None:
#             assert isinstance(newdata, dict)
#             self.data = newdata
#         fpath = os.path.split(self._filename)[0]
#         if len(fpath):
#             sysutils.mkdirp_writable(fpath)
#         with open(self._filename, 'w') as fn:
#             self.yaml.dump(self.data, fn)
# 
#     def update(self, newdata):
#         " Overwrite the data with newdata recursively. Updates the file. "
#         self.data = dict_merge(self.data, newdata)
#         self.save()
#         return self.data


import re
import os
import shlex
from six import iteritems
    from collections.abc import Sequence
    from collections import Sequence
from pybombs import pb_logging
from pybombs import recipe_manager
from pybombs import config_manager
from pybombs.pb_exception import PBException
from pybombs.config_file import PBConfigFile
from pybombs.utils import dict_merge
        from ruamel import yaml
        """
        Merges the recipe data with local config settings. Local settings
        always supersede recipe settings.

        This allows users to override anything in a recipe with whatever's stored
        in the `package:` and `category:` sections of their local config files.
        """
        return normalize_package_data(dict_merge(
            self.get_dict(),
            config_manager.config_manager.get_package_flags(
                self.id, self.get_dict().get('category')
            )
        ))


RECIPE_CACHE = {}
def get_recipe(pkgname, target='package', fail_easy=False):
    """
    Return a recipe object by its package name.
    """
    cache_key = pkgname
    if cache_key in RECIPE_CACHE:
        pb_logging.logger.getChild("get_recipe").trace("Woohoo, this one's already cached ({0})".format(pkgname))
        return RECIPE_CACHE[cache_key]
    try:
        r = Recipe(recipe_manager.recipe_manager.get_recipe_filename(pkgname))
    except PBException as ex:
        if fail_easy:
            return None
        else:

# Path: pybombs/pb_logging.py
# BOLD = str('\033[1m')
# TRACE = 1
# class ColoredConsoleHandler(logging.StreamHandler):
# class PBLogger(logging.getLoggerClass()):
#     def emit(self, record):
#     def __init__(self, *args, **kwargs):
#     def trace(self, *args, **kwargs):
# 
# Path: pybombs/recipe_manager.py
# class RecipeListManager(object):
#     def __init__(self):
#     def get_recipe_filename(self, name):
#     def get_template_filename(self, template):
#     def list_all(self):
#     def _append_location(self, dirname):
# 
# Path: pybombs/config_manager.py
# def npath(path):
#     def __init__(self, args, cfg_list, select_prefix=None):
#     def _set_attrs(self):
#     def _merge_config_info_from_file(self, cfg_file, cfg_data):
#     def _find_prefix_dir(self, args):
#     def _detect_python_version(self):
#     def _detect_python_path(self):
#     def _load_environ_from_script(self, setup_env_file):
#     def _load_default_env(self, env):
#     def get_prefix_cfg_dir_writable(self):
#     def __init__(self, select_prefix=None):
#     def load(self, select_prefix=None):
#     def _append_cfg_from_file(self, cfg_filename, index=None):
#     def get_pybombs_dir(self, prefix_dir=None):
#     def get(self, key, default=None):
#     def keys(self):
#     def set(self, key, value):
#     def get_help(self, key):
#     def set_config_reference(self, ref):
#     def get_active_prefix(self):
#     def get_recipe_locations(self):
#     def get_named_recipe_dirs(self):
#     def get_named_recipe_sources(self):
#     def get_named_recipe_cfg_file(self, recipe_alias):
#     def get_template_dir(self):
#     def resolve_recipe_uri(self, uri, name, cache_dir):
#     def get_package_flags(self, pkgname, categoryname=None):
#     def get_python_version(self):
#     def get_satisfier_tags(self):
#     def update_cfg_file(self, new_data, cfg_file=None):
#     def setup_parser(self, parser):
# class PrefixInfo(object):
# class ConfigManager(object):
#     LAYER_DEFAULT = 0
#     LAYER_GLOBALS = 1
#     LAYER_HOME = 2
#     LAYER_PREFIX = 3
#     LAYER_CMDLINE_FILE = 4
#     LAYER_CMDLINE_ARGS = 5
#     LAYER_VOLATILE = 6
# 
# Path: pybombs/config_file.py
# class PBConfigFile(object):
#     """
#     Abstraction layer for our config and other files
#     """
#     def __init__(self, filename):
#         # Store normalized path, in case someone chdirs after calling the ctor
#         self._filename = os.path.abspath(os.path.expanduser(os.path.normpath(filename)))
#         self.data = None
#         self.yaml = AbstractYaml()
#         touch_file(filename)
#         with open(filename) as fn:
#             try:
#                 # TODO: Recursively turn this into an OrderedDict, not just at
#                 # top level. In a nested dict, some key elements will still be
#                 # ruamel.ordereddict.
#                 self.data = OrderedDict(self.yaml.load(fn.read()) or {})
#             except (IOError, OSError):
#                 self.data = OrderedDict()
#             except Exception as e:
#                 raise PBException("Error loading {0}: {1}".format(filename, str(e)))
#         assert isinstance(self.data, OrderedDict)
# 
#     def get(self, key=None, default=None):
#         " Return the data from the config file as a dict "
#         if key is None:
#             return self.data
#         if default is None:
#             default = OrderedDict()
#         # TODO Again, this is not recursive and sub-values may be non-vanilla
#         # ordered dicts
#         return OrderedDict(self.data.get(key, default))
# 
#     def save(self, newdata=None):
#         " Write the contents of the data cache to the file. "
#         if newdata is not None:
#             assert isinstance(newdata, dict)
#             self.data = newdata
#         fpath = os.path.split(self._filename)[0]
#         if len(fpath):
#             sysutils.mkdirp_writable(fpath)
#         with open(self._filename, 'w') as fn:
#             self.yaml.dump(self.data, fn)
# 
#     def update(self, newdata):
#         " Overwrite the data with newdata recursively. Updates the file. "
#         self.data = dict_merge(self.data, newdata)
#         self.save()
#         return self.data


# Path: pybombs/recipe.py
import re
import os
import shlex
from six import iteritems
    from collections.abc import Sequence
    from collections import Sequence
from pybombs import pb_logging
from pybombs import recipe_manager
from pybombs import config_manager
from pybombs.pb_exception import PBException
from pybombs.config_file import PBConfigFile
from pybombs.utils import dict_merge
        from ruamel import yaml

        """
        Merges the recipe data with local config settings. Local settings
        always supersede recipe settings.

        This allows users to override anything in a recipe with whatever's stored
        in the `package:` and `category:` sections of their local config files.
        """
        return normalize_package_data(dict_merge(
            self.get_dict(),
            config_manager.config_manager.get_package_flags(
                self.id, self.get_dict().get('category')
            )
        ))


RECIPE_CACHE = {}
def get_recipe(pkgname, target='package', fail_easy=False):
    """
    Return a recipe object by its package name.
    """
    cache_key = pkgname
    if cache_key in RECIPE_CACHE:
        pb_logging.logger.getChild("get_recipe").trace("Woohoo, this one's already cached ({0})".format(pkgname))
        return RECIPE_CACHE[cache_key]
    try:
        r = Recipe(recipe_manager.recipe_manager.get_recipe_filename(pkgname))
    except PBException as ex:
        if fail_easy:
            return None
        else:

            pb_logging.logger.getChild("get_recipe").error("Error fetching recipe `{0}':\n{1}".format(