def get_commit_url(repo_url):
    """pass"""
    if 'github.com' in repo_url:
        return repo_url[:-4] if repo_url.endswith('.git') else repo_url
    elif 'git.openstack.org' in repo_url:
        uri = '/'.join(repo_url.split('/')[-2:])
        return 'https://github.com/{0}'.format(uri)
    else:
        return repo_url


def get_projects(osa_repo_dir, commit):
    """pass"""
    repo = Repo(osa_repo_dir)
    checkout(repo, commit)
    yaml_files = glob.glob('{0}/playbooks/defaults/repo_packages/*.yml'.format(osa_repo_dir))
    yaml_parsed = []
    for yaml_file in yaml_files:
        with open(yaml_file, 'r') as f:
            yaml_parsed.append(yaml.load(f))
    merged_dicts = {k: v for d in yaml_parsed for k, v in d.items()}
    return normalize_yaml(merged_dicts)


def checkout(repo, ref):
    """pass"""
    if ref in repo.branches:
        log.warn('Removing local branch {b} for repo {r}'.format(b=ref, r=repo))
        repo.head.reset(index=True, working_tree=True)
        repo.git.checkout(repo.head.commit.hexsha)
        repo.delete_head(ref, '--force')
    log.info('Checkout out repo {repo} to ref {ref}'.format(repo=repo, ref=ref))
    repo.head.reset(index=True, working_tree=True)
    repo.git.checkout(ref)
    repo.head.reset(index=True, working_tree=True)
    sha = repo.head.commit.hexsha
    log.info('Current SHA for repo {repo} is {sha}'.format(repo=repo, sha=sha))


def get_roles(osa_repo_dir, commit, role_requirements):
    """pass"""
    repo = Repo(osa_repo_dir)
    checkout(repo, commit)
    log.info('Looking for file {f} in repo {r}'.format(r=osa_repo_dir, f=role_requirements))
    filename = '{0}/{1}'.format(osa_repo_dir, role_requirements)
    with open(filename, 'r') as f:
        roles_yaml = yaml.load(f)
    return normalize_yaml(roles_yaml)


def make_osa_report(repo_dir, old_commit, new_commit, args):
    """pass"""
    update_repo(repo_dir, args.osa_repo_url, args.update)
    validate_commits(repo_dir, [old_commit, new_commit])
    validate_commit_range(repo_dir, old_commit, new_commit)
    commits = get_commits(repo_dir, old_commit, new_commit)
    template_vars = {'args': args, 'repo': 'openstack-ansible', 'commits': commits, 'commit_base_url': get_commit_url(args.osa_repo_url), 'old_sha': old_commit, 'new_sha': new_commit}
    return render_template('offline-header.j2', template_vars)


def _homogenize_data_filter(dfilter):
    """pass"""
    if isinstance(dfilter, tuple) and len(dfilter) == 1:
        dfilter = (dfilter[0], None)
    if dfilter is None or dfilter == (None, None) or dfilter == (None,):
        dfilter = (None, None)
    elif isinstance(dfilter, dict):
        dfilter = (dfilter, None)
    elif not (isinstance(dfilter, (list, str)) and (not (isinstance(dfilter, bool) and isinstance(dfilter, int)))) or (isinstance(dfilter[0], dict) or (filter is None and isinstance(dfilter[1], dict))):
        pass
    else:
        dfilter = (dfilter[1], dfilter[0])
    return dfilter


def _tofloat(obj):
    """pass"""
    if 'inf' in obj.lower().strip():
        return obj
    try:
        return int(obj)
    except ValueError:
        try:
            return float(obj)
        except ValueError:
            return obj


def _in_header(self, col):
    """pass"""
    if not self._has_header:
        icol_ex = pexdoc.exh.addex(RuntimeError, 'Invalid column specification')
    hnf_ex = pexdoc.exh.addex(ValueError, 'Column *[column_identifier]* not found')
    col_list = [col] if isinstance(col, (str, int)) else col
    for col in col_list:
        edata = {'field': 'column_identifier', 'value': col}
        if not self._has_header:
            icol_ex(not isinstance(col, int))
            hnf_ex(col < 0 or col > len(self._header) - 1, edata)
        else:
            hnf_ex(isinstance(col, int) and (col < 0 or col > self._data_cols) or (isinstance(col, str) and col.upper() not in self._header_upper), edata)
    return col_list


def with_reactor(*dec_args, **dec_kwargs):
    """pass"""
    if len(dec_args) == 1 and callable(dec_args[0]) and (not dec_kwargs):
        callee = dec_args[0]
        dec_args = ()
        dec_kwargs = {}

        @functools.wraps(callee)
        def wrapper(*call_args, **call_kwargs):
            return _twisted_test_sync(callee, call_args, call_kwargs)
        return wrapper
    else:

        def decorator(callee):

            @functools.wraps(callee)
            def wrapper(*call_args, **call_kwargs):
                return _twisted_test_sync(callee, call_args, call_kwargs, *dec_args, **dec_kwargs)
            return wrapper
        return decorator


def _ensure_reactor_running():
    """pass"""
    if not reactor.running:
        signal_registrations = []

        def signal_capture(*args, **kwargs):
            signal_registrations.append((orig_signal, args, kwargs))

        def set_wakeup_fd_capture(*args, **kwargs):
            signal_registrations.append((orig_set_wakeup_fd, args, kwargs))
        orig_signal = signal.signal
        signal.signal = signal_capture
        orig_set_wakeup_fd = signal.set_wakeup_fd
        signal.set_wakeup_fd = set_wakeup_fd_capture
        reactor_thread = threading.Thread(target=reactor.run, name='reactor')
        reactor_thread.daemon = True
        reactor_thread.start()
        while not reactor.running:
            time.sleep(0.01)
        time.sleep(0.01)
        signal.signal = orig_signal
        signal.set_wakeup_fd = orig_set_wakeup_fd
        for func, args, kwargs in signal_registrations:
            func(*args, **kwargs)


def _timeoutDeferred(deferred, timeout):
    """pass"""
    delayedCall = reactor.callLater(timeout, deferred.cancel)

    def gotResult(result):
        if delayedCall.active():
            delayedCall.cancel()
        return result
    deferred.addBoth(gotResult)


def _get_json(value):
    """pass"""
    if hasattr(value, 'replace'):
        value = value.replace('\n', ' ')
    try:
        return json.loads(value)
    except json.JSONDecodeError:
        if hasattr(value, 'replace'):
            value = value.replace('"', '\\"')
        return json.loads('"{}"'.format(value))


def save_list(key, *values):
    """pass"""
    return json.dumps({key: [_get_json(value) for value in values]})


def save_file(key, file_path, *refs):
    """pass"""
    if not os.path.isfile(file_path):
        return error("Output '{}' set to a missing file: '{}'.".format(key, file_path))
    result = {key: {'file': file_path}}
    if refs:
        missing_refs = [ref for ref in refs if (not os.path.isfile(ref)) and (not os.path.isdir(ref))]
        if len(missing_refs) > 0:
            return error("Output '{}' set to missing references: '{}'.".format(key, ', '.join(missing_refs)))
        result[key]['refs'] = refs
    return json.dumps(result)


def save_file_list(key, *files_refs):
    """pass"""
    file_list = []
    for file_refs in files_refs:
        if ':' in file_refs:
            try:
                file_name, refs = file_refs.split(':')
            except ValueError as e:
                return error("Only one colon ':' allowed in file-refs specification.")
        else:
            file_name, refs = (file_refs, None)
        if not os.path.isfile(file_name):
            return error("Output '{}' set to a missing file: '{}'.".format(key, file_name))
        file_obj = {'file': file_name}
        if refs:
            refs = [ref_path.strip() for ref_path in refs.split(',')]
            missing_refs = [ref for ref in refs if not os.path.isfile(ref) and (not os.path.isdir(ref))]
            if len(missing_refs) > 0:
                return error("Output '{}' set to missing references: '{}'.".format(key, ', '.join(missing_refs)))
            file_obj['refs'] = refs
        file_list.append(file_obj)
    return json.dumps({key: file_list})


def save_dir(key, dir_path, *refs):
    """pass"""
    if not os.path.isdir(dir_path):
        return error("Output '{}' set to a missing directory: '{}'.".format(key, dir_path))
    result = {key: {'dir': dir_path}}
    if refs:
        missing_refs = [ref for ref in refs if (not os.path.isfile(ref)) and (not os.path.isdir(ref))]
        if len(missing_refs) > 0:
            return error("Output '{}' set to missing references: '{}'.".format(key, ', '.join(missing_refs)))
        result[key]['refs'] = refs
    return json.dumps(result)


def save_dir_list(key, *dirs_refs):
    """pass"""
    dir_list = []
    for dir_refs in dirs_refs:
        if ':' in dir_refs:
            try:
                dir_path, refs = dir_refs.split(':')
            except ValueError as e:
                return error("Only one colon ':' allowed in dir-refs specification.")
        else:
            dir_path, refs = (dir_refs, None)
        if not os.path.isdir(dir_path):
            return error("Output '{}' set to a missing directory: '{}'.".format(key, dir_path))
        dir_obj = {'dir': dir_path}
        if refs:
            refs = [ref_path.strip() for ref_path in refs.split(',')]
            missing_refs = [ref for ref in refs if not os.path.isfile(ref) and (not os.path.isdir(ref))]
            if len(missing_refs) > 0:
                return error("Output '{}' set to missing references: '{}'.".format(key, ', '.join(missing_refs)))
            dir_obj['refs'] = refs
        dir_list.append(dir_obj)
    return json.dumps({key: dir_list})


def n_day(date_string):
    """pass"""
    today = datetime.date.today()
    match = re.match('(\\d{1,3}|a) days? ago', date_string)
    groups = match.groups()
    if groups:
        decrement = groups[0]
        if decrement == 'a':
            decrement = 1
        return today - datetime.timedelta(days=int(decrement))


def encloses(self, location: FileLocation) -> Optional[FunctionDesc]:
    """pass"""
    for func in self.in_file(location.filename):
        if location in func.location:
            return func
    return None


def in_file(self, filename: str) -> Iterator[FunctionDesc]:
    """pass"""
    yield from self.__filename_to_functions.get(filename, [])


def parse_config(args):
    """pass"""
    config_path = path.expanduser(args.config_file)
    if not path.exists(config_path):
        if args.config_file != DEFAULT_JOURNAL_RC:
            print("journal: error: config file '" + args.config_file + "' not found")
            sys.exit()
        else:
            return DEFAULT_JOURNAL
    config = ConfigParser.SafeConfigParser({'journal': {'default': '__journal'}, '__journal': {'location': DEFAULT_JOURNAL}})
    config.read(config_path)
    journal_location = config.get(config.get('journal', 'default'), 'location')
    if args.journal:
        journal_location = config.get(args.journal, 'location')
    return journal_location


def record_entries(journal_location, entries):
    """pass"""
    check_journal_dest(journal_location)
    current_date = datetime.datetime.today()
    date_header = current_date.strftime('%a %H:%M:%S %Y-%m-%d') + '\n'
    with open(build_journal_path(journal_location, current_date), 'a') as date_file:
        entry_output = date_header
        entry_output += '-' + ' '.join(entries) + '\n'
        entry_output += '\n'
        date_file.write(entry_output)


def get_entry(journal_location, date):
    """pass"""
    if not isinstance(date, datetime.date):
        return None
    try:
        with open(build_journal_path(journal_location, date), 'r') as entry_file:
            return entry_file.read()
    except IOError:
        pass


def TemplateValidator(value):
    """pass"""
    try:
        Template(value)
    except Exception as e:
        raise ValidationError(_('Cannot compile template (%(exception)s)'), params={'exception': e})


def get_lbry_api_function_docs(url=LBRY_API_RAW_JSON_URL):
    """pass"""
    try:
        docs_page = urlopen(url)
        contents = docs_page.read().decode('utf-8')
        return loads(contents)
    except URLError as UE:
        print(UE)
        return []
    except Exception as E:
        print(E)
        return []


def generate_method_definition(func):
    """pass"""
    indent = 4
    method_definition = ' ' * indent + 'def ' + func['name']
    params_required = [param for param in func['arguments'] if param['is_required']]
    params_optional = [param for param in func['arguments'] if not param['is_required']]
    method_definition += '(self, '
    for param in params_required:
        method_definition += param['name']
        method_definition += ', '
    for param in params_optional:
        method_definition += param['name']
        method_definition += '=None, '
    method_definition = method_definition.rstrip(', ') + '):\n'
    indent += 4
    method_definition += ' ' * indent
    method_definition += '"""' + func['description']
    method_definition += '\n\n' + ' ' * indent
    for param in params_required + params_optional:
        method_definition += ':param ' + DTYPE_MAPPING[param['type'].lower()]
        method_definition += ' ' + param['name'] + ': '
        method_definition += param['description']
        method_definition += '\n' if param['is_required'] else ' (Optional)\n'
        method_definition += ' ' * indent
    open_index = func['returns'].find('(')
    close_index = func['returns'].find(')', open_index > -1 and open_index or 0)
    func['returns'] = func['returns'].replace('\t', '    ')
    return_string = func['returns'].replace('\n', '')
    if open_index < close_index:
        if func['returns'][open_index + 1:close_index] in DTYPE_MAPPING:
            method_definition += ':rtype: ' + DTYPE_MAPPING[func['returns'][open_index + 1:close_index]]
            func['returns'] = func['returns'].replace(func['returns'][open_index:close_index + 1], '')
            method_definition += '\n' + ' ' * indent
    method_definition += ':return: ' + return_string
    for i in range(0, len(return_string) + 1, 80 - (indent + 2)):
        method_definition += return_string[i:i + 80 - (indent + 2)] + '\n' + ' ' * indent
    method_definition += '"""\n' + ' ' * indent
    params_map = '__params_map = {'
    params_indent, num_params = (len(params_map), len(params_required) + len(params_optional))
    method_definition += params_map
    for i, param in enumerate(params_required + params_optional):
        method_definition += "'" + param['name'] + "': " + param['name']
        if not param['is_required']:
            method_definition += ' if ' + param['name'] + 'is not None else None'
        method_definition += ',\n' + ' ' * (indent + 1) + ' ' * params_indent
    method_definition += '}\n\n' + ' ' * indent
    method_definition += "return self.make_request(SERVER_ADDRESS, '" + func['name'] + "', " + params_map.rstrip(' = {') + ', timeout=self.timeout)\n\n'
    return method_definition


def generate_lbryd_wrapper(url=LBRY_API_RAW_JSON_URL, read_file=__LBRYD_BASE_FPATH__, write_file=LBRYD_FPATH):
    """pass"""
    functions = get_lbry_api_function_docs(url)
    with open(write_file, 'w') as lbry_file:
        lbry_file.write('# This file was generated at build time using the generator function\n')
        lbry_file.write('# You may edit but do so with caution\n')
        with open(read_file, 'r') as template:
            header = template.read()
        lbry_file.write(header)
        for func in functions:
            method_definition = generate_method_definition(func)
            lbry_file.write(method_definition)
    try:
        from yapf.yapflib.yapf_api import FormatFile
        FormatFile(write_file, in_place=True)
    except ImportError as IE:
        print('[Warning]: yapf is not installed, so the generated code will not follow an easy-to-read standard')
        print(IE)


def get(self, style):
    """pass"""
    level = len(self.stack) - 1
    while level >= 0:
        if style in self.stack[level]:
            return self.stack[level][style]
        else:
            level = level - 1
    return None


def enforce_type(self, attr, val):
    """pass"""
    if not attr in self.types:
        return utfstr(val)
    elif self.types[attr] == 'int':
        return int(float(val))
    elif self.types[attr] == 'float':
        return float(val)
    else:
        return utfstr(val)


def to_escpos(self):
    """pass"""
    cmd = ''
    ordered_cmds = self.cmds.keys()
    ordered_cmds.sort(lambda x, y: cmp(self.cmds[x]['_order'], self.cmds[y]['_order']))
    for style in ordered_cmds:
        cmd += self.cmds[style][self.get(style)]
    return cmd


def start_inline(self, stylestack=None):
    """pass"""
    self.stack.append('inline')
    if self.dirty:
        self.escpos._raw(' ')
    if stylestack:
        self.style(stylestack)


def start_block(self, stylestack=None):
    """pass"""
    if self.dirty:
        self.escpos._raw('\n')
        self.dirty = False
    self.stack.append('block')
    if stylestack:
        self.style(stylestack)


def end_entity(self):
    """pass"""
    if self.stack[-1] == 'block' and self.dirty:
        self.escpos._raw('\n')
        self.dirty = False
    if len(self.stack) > 1:
        self.stack = self.stack[:-1]


def _pinyin_generator(chars, format):
    """pass"""
    for char in chars:
        key = '%X' % ord(char)
        pinyin = pinyin_dict.get(key, char)
        tone = pinyin_tone.get(key, 0)
        if tone == 0 or format == 'strip':
            pass
        elif format == 'numerical':
            pinyin += str(tone)
        elif format == 'diacritical':
            vowels = itertools.chain((c for c in pinyin if c in 'aeo'), (c for c in pinyin if c in 'iuv'))
            vowel = pinyin.index(next(vowels)) + 1
            pinyin = pinyin[:vowel] + tonemarks[tone] + pinyin[vowel:]
        else:
            error = 'Format must be one of: numerical/diacritical/strip'
            raise ValueError(error)
        yield unicodedata.normalize('NFC', pinyin)


def get(s, delimiter='', format='diacritical'):
    """pass"""
    return delimiter.join(_pinyin_generator(u(s), format=format))


def get_initial(s, delimiter=' '):
    """pass"""
    initials = (p[0] for p in _pinyin_generator(u(s), format='strip'))
    return delimiter.join(initials)


def _add_to_tree(tree, word, meaning):
    """pass"""
    if len(word) == 0:
        tree[''] = meaning
    else:
        _add_to_tree(tree[word[0]], word[1:], meaning)


def init():
    """pass"""
    global dictionaries, trees
    dictionaries = {'traditional': {}, 'simplified': {}}
    trees = {'traditional': Tree(), 'simplified': Tree()}
    lines = gzip.open(os.path.join(os.path.dirname(__file__), 'cedict.txt.gz'), mode='rt', encoding='utf-8')
    exp = re.compile('^([^ ]+) ([^ ]+) \\[(.*)\\] /(.+)/')
    parsed_lines = (exp.match(line).groups() for line in lines if line[0] != '#')
    for traditional, simplified, pinyin, meaning in parsed_lines:
        meaning = meaning.split('/')
        dictionaries['traditional'][traditional] = meaning
        dictionaries['simplified'][simplified] = meaning
        _add_to_tree(trees['traditional'], traditional, meaning)
        _add_to_tree(trees['simplified'], simplified, meaning)


def translate_word(word, dictionary=['simplified']):
    """pass"""
    global dictionaries
    if not dictionaries:
        init()
    for d in dictionary:
        if word in dictionaries[d]:
            return dictionaries[d][word]


def get_status_key(self, instance):
    """pass"""
    key_id = 'inst_%s' % id(instance) if instance.pk is None else instance.pk
    return '%s.%s-%s-%s' % (instance._meta.app_label, get_model_name(instance), key_id, self.field.name)


def get_status(self, instance):
    """pass"""
    status_key, status = self._get_status(instance)
    if status['state'] in ['complete', 'error']:
        cache.delete(status_key)
    return status


def set_status(self, instance, status):
    """pass"""
    status_key = self.get_status_key(instance)
    cache.set(status_key, status, timeout=300)


def get_mode(self, old_mode=None):
    """pass"""
    if self.mode is not None:
        return self.mode
    assert self.can_write, 'This format does not have a supported output mode.'
    if old_mode is None:
        return self.output_modes[0]
    if old_mode in self.output_modes:
        return old_mode
    try:
        idx = PILLOW_MODES.index(old_mode)
    except ValueError:
        return self.output_modes[0]
    for mode in PILLOW_MODES[idx + 1:]:
        if mode in self.output_modes:
            return mode
    opposite = PILLOW_MODES[:idx]
    opposite.reverse()
    for mode in opposite:
        if mode in self.output_modes:
            return mode


def token_at_cursor(code, pos=0):
    """pass"""
    l = len(code)
    end = start = pos
    while end < l and code[end].isalpha():
        end += 1
    while start > 0 and code[start - 1].isalpha():
        start -= 1
    if start > 0 and code[start - 1] == '%':
        start -= 1
    return (code[start:end], start)


def _send(self, data, msg_type='ok', silent=False):
    """pass"""
    if data is not None:
        try:
            self._klog.debug('msg to frontend (%d): %.160s...', silent, data)
        except Exception as e:
            self._klog.warn("can't log response: %s", e)
        if not silent:
            if msg_type != 'raw':
                data = data_msg(data, mtype=msg_type)
            self.send_response(self.iopub_socket, 'display_data', data)
    return {'status': 'error' if msg_type == 'error' else 'ok', 'execution_count': self.execution_count, 'payload': [], 'user_expressions': {}}