# Path: crmsh/ra.py
# def disambiguate_ra_type(s):
#     '''
#     Unravel [class:[provider:]]type
#     '''
#     l = s.split(':')
#     if not l or len(l) > 3:
#         return ["", "", ""]
#     if len(l) == 3:
#         return l
#     elif len(l) == 2:
#         cl, tp = l
#     else:
#         cl, tp = "ocf", l[0]
#     pr = pick_provider(ra_providers(tp, cl)) if cl == 'ocf' else ''
#     return cl, pr, tp
# 
# def ra_type_validate(s, ra_class, provider, rsc_type):
#     '''
#     Only ocf ra class supports providers.
#     '''
#     if not rsc_type:
#         logger.error("bad resource type specification %s", s)
#         return False
#     if ra_class == "ocf":
#         if not provider:
#             logger.error("provider could not be determined for %s", s)
#             return False
#     else:
#         if provider:
#             logger.warning("ra class %s does not support providers", ra_class)
#             return True
#     return True
# 
# Path: crmsh/utils.py
# def keyword_cmp(string1, string2):
#     return string1.lower() == string2.lower()
# 
# def verify_boolean(opt):
#     return opt.lower() in ("yes", "true", "on", "1") or \
#         opt.lower() in ("no", "false", "off", "0")
# 
# def lines2cli(s):
#     '''
#     Convert a string into a list of lines. Replace continuation
#     characters. Strip white space, left and right. Drop empty lines.
#     '''
#     cl = []
#     l = s.split('\n')
#     cum = []
#     for p in l:
#         p = p.strip()
#         if p.endswith('\\'):
#             p = p.rstrip('\\')
#             cum.append(p)
#         else:
#             cum.append(p)
#             cl.append(''.join(cum).strip())
#             cum = []
#     if cum:  # in case s ends with backslash
#         cl.append(''.join(cum))
#     return [x for x in cl if x]
# 
# Path: crmsh/utils.py
# def get_boolean(opt, dflt=False):
#     if not opt:
#         return dflt
#     return is_boolean_true(opt)
# 
# class olist(list):
#     """
#     Implements the 'in' operator
#     in a case-insensitive manner,
#     allowing "if x in olist(...)"
#     """
#     def __init__(self, keys):
#         super(olist, self).__init__([k.lower() for k in keys])
# 
#     def __contains__(self, key):
#         return super(olist, self).__contains__(key.lower())
# 
#     def append(self, key):
#         super(olist, self).append(key.lower())
# 
# def canonical_boolean(opt):
#     return 'true' if is_boolean_true(opt) else 'false'
# 
# Path: crmsh/utils.py
# def handle_role_for_ocf_1_1(value, name='role'):
#     """
#     * Convert role from Promoted/Unpromoted to Master/Slave if schema doesn't support OCF 1.1
#     * Convert role from Master/Slave to Promoted/Unpromoted if ocf1.1 cib schema detected and OCF_1_1_SUPPORT is yes
#     """
#     role_names = ["role", "target-role"]
#     downgrade_dict = {"Promoted": "Master", "Unpromoted": "Slave"}
#     upgrade_dict = {v: k for k, v in downgrade_dict.items()}
# 
#     if name not in role_names:
#         return value
#     if value in downgrade_dict and not is_ocf_1_1_cib_schema_detected():
#         logger.warning('Convert "%s" to "%s" since the current schema version is old and not upgraded yet. Please consider "%s"', value, downgrade_dict[value], constants.CIB_UPGRADE)
#         return downgrade_dict[value]
#     if value in upgrade_dict and is_ocf_1_1_cib_schema_detected() and config.core.OCF_1_1_SUPPORT:
#         logger.info('Convert deprecated "%s" to "%s"', value, upgrade_dict[value])
#         return upgrade_dict[value]
# 
#     return value


import shlex
import re
import inspect
from lxml import etree
from . import constants
from .ra import disambiguate_ra_type, ra_type_validate
from . import schema
from .utils import keyword_cmp, verify_boolean, lines2cli
from .utils import get_boolean, olist, canonical_boolean
from .utils import handle_role_for_ocf_1_1
from . import xmlutil
from . import log
        from .cibconfig import cib_factory
        from .cibconfig import cib_factory
        from .cibconfig import cib_factory
    from .cibconfig import cib_factory
        from collections import defaultdict
        from itertools import repeat
        from .cibconfig import cib_factory
        from copy import deepcopy
        self.cli_list = []
        return ret


def parse(s, comments=None, ignore_empty=True):
    '''
    Input: a list of tokens (or a CLI format string).
    Return: a cibobject
    On failure, returns either False or None.
    comments holds comment state between parses
    Handles basic normalization of the input string.
    Converts unicode to ascii, XML data to CLI format,
    lexing etc.
    '''
    if comments is None:
        comments = []

    if isinstance(s, str):
        try:
            s = s.encode('ascii', errors='xmlcharrefreplace')
            s = s.decode('utf-8')
        except Exception as e:
            logger.error(e)
            return False
    if isinstance(s, str):
        if s and s.startswith('#'):
            comments.append(s)
            return None
        if s.startswith('xml'):
            try:

# Path: crmsh/ra.py
# def disambiguate_ra_type(s):
#     '''
#     Unravel [class:[provider:]]type
#     '''
#     l = s.split(':')
#     if not l or len(l) > 3:
#         return ["", "", ""]
#     if len(l) == 3:
#         return l
#     elif len(l) == 2:
#         cl, tp = l
#     else:
#         cl, tp = "ocf", l[0]
#     pr = pick_provider(ra_providers(tp, cl)) if cl == 'ocf' else ''
#     return cl, pr, tp
# 
# def ra_type_validate(s, ra_class, provider, rsc_type):
#     '''
#     Only ocf ra class supports providers.
#     '''
#     if not rsc_type:
#         logger.error("bad resource type specification %s", s)
#         return False
#     if ra_class == "ocf":
#         if not provider:
#             logger.error("provider could not be determined for %s", s)
#             return False
#     else:
#         if provider:
#             logger.warning("ra class %s does not support providers", ra_class)
#             return True
#     return True
# 
# Path: crmsh/utils.py
# def keyword_cmp(string1, string2):
#     return string1.lower() == string2.lower()
# 
# def verify_boolean(opt):
#     return opt.lower() in ("yes", "true", "on", "1") or \
#         opt.lower() in ("no", "false", "off", "0")
# 
# def lines2cli(s):
#     '''
#     Convert a string into a list of lines. Replace continuation
#     characters. Strip white space, left and right. Drop empty lines.
#     '''
#     cl = []
#     l = s.split('\n')
#     cum = []
#     for p in l:
#         p = p.strip()
#         if p.endswith('\\'):
#             p = p.rstrip('\\')
#             cum.append(p)
#         else:
#             cum.append(p)
#             cl.append(''.join(cum).strip())
#             cum = []
#     if cum:  # in case s ends with backslash
#         cl.append(''.join(cum))
#     return [x for x in cl if x]
# 
# Path: crmsh/utils.py
# def get_boolean(opt, dflt=False):
#     if not opt:
#         return dflt
#     return is_boolean_true(opt)
# 
# class olist(list):
#     """
#     Implements the 'in' operator
#     in a case-insensitive manner,
#     allowing "if x in olist(...)"
#     """
#     def __init__(self, keys):
#         super(olist, self).__init__([k.lower() for k in keys])
# 
#     def __contains__(self, key):
#         return super(olist, self).__contains__(key.lower())
# 
#     def append(self, key):
#         super(olist, self).append(key.lower())
# 
# def canonical_boolean(opt):
#     return 'true' if is_boolean_true(opt) else 'false'
# 
# Path: crmsh/utils.py
# def handle_role_for_ocf_1_1(value, name='role'):
#     """
#     * Convert role from Promoted/Unpromoted to Master/Slave if schema doesn't support OCF 1.1
#     * Convert role from Master/Slave to Promoted/Unpromoted if ocf1.1 cib schema detected and OCF_1_1_SUPPORT is yes
#     """
#     role_names = ["role", "target-role"]
#     downgrade_dict = {"Promoted": "Master", "Unpromoted": "Slave"}
#     upgrade_dict = {v: k for k, v in downgrade_dict.items()}
# 
#     if name not in role_names:
#         return value
#     if value in downgrade_dict and not is_ocf_1_1_cib_schema_detected():
#         logger.warning('Convert "%s" to "%s" since the current schema version is old and not upgraded yet. Please consider "%s"', value, downgrade_dict[value], constants.CIB_UPGRADE)
#         return downgrade_dict[value]
#     if value in upgrade_dict and is_ocf_1_1_cib_schema_detected() and config.core.OCF_1_1_SUPPORT:
#         logger.info('Convert deprecated "%s" to "%s"', value, upgrade_dict[value])
#         return upgrade_dict[value]
# 
#     return value


# Path: crmsh/parse.py
import shlex
import re
import inspect
from lxml import etree
from . import constants
from .ra import disambiguate_ra_type, ra_type_validate
from . import schema
from .utils import keyword_cmp, verify_boolean, lines2cli
from .utils import get_boolean, olist, canonical_boolean
from .utils import handle_role_for_ocf_1_1
from . import xmlutil
from . import log
        from .cibconfig import cib_factory
        from .cibconfig import cib_factory
        from .cibconfig import cib_factory
    from .cibconfig import cib_factory
        from collections import defaultdict
        from itertools import repeat
        from .cibconfig import cib_factory
        from copy import deepcopy

        self.cli_list = []
        return ret


def parse(s, comments=None, ignore_empty=True):
    '''
    Input: a list of tokens (or a CLI format string).
    Return: a cibobject
    On failure, returns either False or None.
    comments holds comment state between parses
    Handles basic normalization of the input string.
    Converts unicode to ascii, XML data to CLI format,
    lexing etc.
    '''
    if comments is None:
        comments = []

    if isinstance(s, str):
        try:
            s = s.encode('ascii', errors='xmlcharrefreplace')
            s = s.decode('utf-8')
        except Exception as e:
            logger.error(e)
            return False
    if isinstance(s, str):
        if s and s.startswith('#'):
            comments.append(s)
            return None
        if s.startswith('xml'):
            try:

                s = [x for p in lines2cli(s) for x in p.split()]