def __setitem__(self, key, val):
        if key.startswith('path.') and not val.startswith('/'):
            val = self._absolute_path(val)
        dict.__setitem__(self, key, val)

__setitem__(self={}, key='path.workdir', val='/home/XXX/.cheat.sh')


def _load_config_from_file(default_config, filename):
    import yaml

    update = {}
    if not os.path.exists(filename):
        return update

    with open(filename) as f:
        newconfig = yaml.load(f.read(), Loader=yaml.SafeLoader)
    for key, val in default_config.items():
        newval = _get_nested(newconfig, key)
        if newval is None:
            continue

        if isinstance(val, int):
            try:
                newval = int(newval)
            except (ValueError, TypeError):
                continue

        update[key] = newval

    return update

_load_config_from_file(default_config={'adapters.active': ['tldr', 'cheat', 'fosdem', 'translation', 'rosetta', 'late.nz', 'question', 'cheat.sheets', 'cheat.sheets dir', 'learnxiny', 'rfc', 'oeis', 'chmod'], 'adapters.mandatory': ['search'], 'cache.redis.db': 0, 'cache.redis.host': 'localhost', 'cache.redis.port': 6379, 'cache.redis.prefix': '', 'cache.type': 'redis', 'frontend.styles': ['abap', 'algol', 'algol_nu', 'arduino', 'autumn', 'borland', 'bw', 'colorful', 'default', 'dracula', 'emacs', 'friendly', 'friendly_grayscale', 'fruity', 'github-dark', 'gruvbox-dark', 'gruvbox-light', 'igor', 'inkpot', 'lightbulb', 'lilypond', 'lovelace', 'manni', 'material', 'monokai', 'murphy', 'native', 'nord', 'nord-darker', 'one-dark', 'paraiso-dark', 'paraiso-light', 'pastie', 'perldoc', 'rainbow_dash', 'rrt', 'sas', 'solarized-dark', 'solarized-light', 'staroffice', 'stata-dark', 'stata-light', 'tango', 'trac', 'vim', 'vs', 'xcode', 'zenburn'], 'log.level': 4, 'path.internal.ansi2html': '/local/rcs/XXX/code/pytrace-collector/logs/self_collected/tried/chubin+cheat.sh/chubin+cheat.sh/share/ansi2html.sh', 'path.internal.bin': '/local/rcs/XXX/code/pytrace-collector/logs/self_collected/tried/chubin+cheat.sh/chubin+cheat.sh/bin', 'path.internal.bin.upstream': '/local/rcs/XXX/code/pytrace-collector/logs/self_collected/tried/chubin+cheat.sh/chubin+cheat.sh/bin/upstream', 'path.internal.malformed': '/local/rcs/XXX/code/pytrace-collector/logs/self_collected/tried/chubin+cheat.sh/chubin+cheat.sh/share/static/malformed-response.html', 'path.internal.pages': '/local/rcs/XXX/code/pytrace-collector/logs/self_collected/tried/chubin+cheat.sh/chubin+cheat.sh/share', 'path.internal.static': '/local/rcs/XXX/code/pytrace-collector/logs/self_collected/tried/chubin+cheat.sh/chubin+cheat.sh/share/static', 'path.internal.templates': '/local/rcs/XXX/code/pytrace-collector/logs/self_collected/tried/chubin+cheat.sh/chubin+cheat.sh/share/templates', 'path.internal.vim': '/local/rcs/XXX/code/pytrace-collector/logs/self_collected/tried/chubin+cheat.sh/chubin+cheat.sh/share/vim', 'path.log.main': 'log/main.log', 'path.log.queries': 'log/queries.log', 'path.log.fetch': 'log/fetch.log', 'path.repositories': 'upstream', 'path.spool': 'spool', 'path.workdir': '/home/XXX/.cheat.sh', 'routing.pre': [('^$', 'search'), ('^[^/]*/rosetta(/|$)', 'rosetta'), ('^rfc/', 'rfc'), ('^oeis/', 'oeis'), ('^chmod/', 'chmod'), ('^:', 'internal'), ('/:list$', 'internal'), ('/$', 'cheat.sheets dir')], 'routing.main': [('', 'cheat.sheets'), ('', 'cheat'), ('', 'tldr'), ('', 'late.nz'), ('', 'fosdem'), ('', 'learnxiny')], 'routing.post': [('^[^/ +]*$', 'unknown'), ('^[a-z][a-z]-[a-z][a-z]$', 'translation')], 'routing.default': 'question', 'upstream.url': 'https://cheat.sh', 'upstream.timeout': 5, 'search.limit': 20, 'server.bind': '0.0.0.0', 'server.port': 8002}, filename='/local/rcs/XXX/code/pytrace-collector/logs/self_collected/tried/chubin+cheat.sh/chubin+cheat.sh/etc/config.yaml')

<module 'yaml' from '/local/rcs/XXX/miniforge3/envs/chubin+cheat.sh/lib/python3.9/site-packages/yaml/__init__.py'>


def test_base_model_can_be_adapter_v2_loaded(name):
    from lit_gpt.adapter_v2 import GPT as AdapterV2GPT
    from lit_gpt.adapter_v2 import adapter_filter
    from lit_gpt.model import GPT as BaseGPT

    kwargs = {"n_layer": 2, "n_head": 8, "n_embd": 16, "padded_vocab_size": 32}
    base_model = BaseGPT.from_name(name, **kwargs)
    base_model_state_dict = base_model.state_dict()
    lora_model = AdapterV2GPT.from_name(name, **kwargs, adapter_start_layer=0)
    keys = lora_model.load_state_dict(base_model_state_dict, strict=False)
    assert not keys.unexpected_keys
    for k in keys.missing_keys:
        assert adapter_filter(k, None)

test_base_model_can_be_adapter_v2_loaded(name='stablelm-base-alpha-3b')

<function adapter_filter at 0x7f801db68af0>

{'n_layer': 2, 'n_head': 8, 'n_embd': 16, 'padded_vocab_size': 32}

GPT(  (lm_head): Linear(in_features=16, out_features=32, bias=False)  (transformer): ModuleDict(    (wte): Embedding(32, 16)    (h): ModuleList(      (0-1): 2 x Block(        (norm_1): LayerNorm((16,), eps=1e-05, elementwise_affine=True)        (attn): CausalSelfAttention(          (attn): Linear(in_features=16, out_features=48, bias=True)          (proj): Linear(in_features=16, out_features=16, bias=True)        )        (norm_2): LayerNorm((16,), eps=1e-05, elementwise_affine=True)        (mlp): GptNeoxMLP(          (fc): Linear(in_features=16, out_features=64, bias=True)          (proj): Linear(in_features=64, out_features=16, bias=True)        )      )    )    (ln_f): LayerNorm((16,), eps=1e-05, elementwise_affine=True)  ))

GPT(  (lm_head): AdapterV2Linear(    (linear): Linear(in_features=16, out_features=32, bias=False)  )  (transformer): ModuleDict(    (wte): Embedding(32, 16)    (h): ModuleList(      (0-1): 2 x Block(        (norm_1): LayerNorm((16,), eps=1e-05, elementwise_affine=True)        (attn): CausalSelfAttention(          (attn): AdapterV2Linear(            (linear): Linear(in_features=16, out_features=48, bias=True)          )          (proj): AdapterV2Linear(            (linear): Linear(in_features=16, out_features=16, bias=True)          )          (adapter_wte): Embedding(10, 16)        )        (norm_2): LayerNorm((16,), eps=1e-05, elementwise_affine=True)        (mlp): GptNeoxMLP(          (fc): AdapterV2Linear(            (linear): Linear(in_features=16, out_features=64, bias=True)          )          (proj): AdapterV2Linear(            (linear): Linear(in_features=64, out_features=16, bias=True)          )        )      )    )    (ln_f): LayerNorm((16,), eps=1e-05, elementwise_affine=True)  ))


def layer_template(layer_name: str, idx: int) -> Tuple[str, int]:
    split = layer_name.split(".")
    number = int(split[idx])
    split[idx] = "{}"
    from_name = ".".join(split)
    return from_name, number

layer_template(layer_name='model.layers.0.self_attn.q_proj.weight', idx=2)

['model', 'layers', '{}', 'self_attn', 'q_proj', 'weight']

['model', 'layers', '0', 'self_attn', 'q_proj', 'weight']


def test_generate(monkeypatch, generated, stop_tokens, expected):
    import chat.base as chat
    import generate.base as generate

    input_idx = torch.tensor([5, 3])
    max_returned_tokens = len(input_idx) + 8
    model = MagicMock()
    model.config.block_size = 100
    model.max_seq_length = 100
    it = iter(generated)

    def multinomial(*_, **__):
        out = next(it)
        return torch.tensor([out])

    monkeypatch.setattr(generate, "multinomial_num_samples_1", multinomial)
    actual = chat.generate(model, input_idx, max_returned_tokens, stop_tokens=stop_tokens)
    actual = list(actual)

    assert len(actual) == len(expected)
    if not actual:
        assert actual == expected
    else:
        for t in actual:
            assert t.dtype == torch.long
        assert torch.cat(actual).tolist() == expected

test_generate(monkeypatch={_setattr=[], _setitem=[], _cwd=None, _savesyspath=None}, generated=repeat(1), stop_tokens=(), expected=[1, 1, 1, 1, 1, 1, 1, 1])

{_setattr=[(<module 'generate.base' from '/local/rcs/XXX/code/pytrace-collector/logs/self_collected/tried/Lightning-AI+lit-gpt/Lightning-AI+lit-gpt/generate/base.py'>, 'multinomial_num_samples_1', <function multinomial_num_samples_1 at 0x7f805238a160>)], _setitem=[], _cwd=None, _savesyspath=None}

<function test_generate.<locals>.multinomial at 0x7f7fd0f7e430>

<generator object generate at 0x7f803c55ff90>


def rowcol_to_a1(row, col):
    """Translates a row and column cell address to A1 notation.

    :param row: The row of the cell to be converted.
        Rows start at index 1.
    :type row: int, str

    :param col: The column of the cell to be converted.
        Columns start at index 1.
    :type row: int, str

    :returns: a string containing the cell's coordinates in A1 notation.

    Example:

    >>> rowcol_to_a1(1, 1)
    A1

    """
    row = int(row)
    col = int(col)

    if row < 1 or col < 1:
        raise IncorrectCellLabel("({}, {})".format(row, col))

    div = col
    column_label = ""

    while div:
        (div, mod) = divmod(div, 26)
        if mod == 0:
            mod = 26
            div -= 1
        column_label = chr(mod + MAGIC_NUMBER) + column_label

    label = "{}{}".format(column_label, row)

    return label

rowcol_to_a1(row=4, col=4)


def a1_to_rowcol(label):
    """Translates a cell's address in A1 notation to a tuple of integers.

    :param str label: A cell label in A1 notation, e.g. 'B1'.
        Letter case is ignored.
    :returns: a tuple containing `row` and `column` numbers. Both indexed
              from 1 (one).
    :rtype: tuple

    Example:

    >>> a1_to_rowcol('A1')
    (1, 1)

    """
    m = CELL_ADDR_RE.match(label)
    if m:
        column_label = m.group(1).upper()
        row = int(m.group(2))

        col = 0
        for i, c in enumerate(reversed(column_label)):
            col += (ord(c) - MAGIC_NUMBER) * (26**i)
    else:
        raise IncorrectCellLabel(label)

    return (row, col)

a1_to_rowcol(label='B1')

<re.Match object; span=(0, 2), match='B1'>


def _a1_to_rowcol_unbounded(label):
    """Translates a cell's address in A1 notation to a tuple of integers.

    Same as `a1_to_rowcol()` but allows for missing row or column part
    (e.g. "A" for the first column)

    :returns: a tuple containing `row` and `column` numbers. Both indexed
        from 1 (one).
    :rtype: tuple

    Example:

    >>> _a1_to_rowcol_unbounded('A1')
    (1, 1)

    >>> _a1_to_rowcol_unbounded('A')
    (inf, 1)

    >>> _a1_to_rowcol_unbounded('1')
    (1, inf)

    >>> _a1_to_rowcol_unbounded('ABC123')
    (123, 731)

    >>> _a1_to_rowcol_unbounded('ABC')
    (inf, 731)

    >>> _a1_to_rowcol_unbounded('123')
    (123, inf)

    >>> _a1_to_rowcol_unbounded('1A')
    Traceback (most recent call last):
        ...
    gspread.exceptions.IncorrectCellLabel: 1A

    >>> _a1_to_rowcol_unbounded('')
    (inf, inf)

    """
    m = A1_ADDR_ROW_COL_RE.match(label)
    if m:
        column_label, row = m.groups()

        if column_label:
            col = 0
            for i, c in enumerate(reversed(column_label.upper())):
                col += (ord(c) - MAGIC_NUMBER) * (26**i)
        else:
            col = inf

        if row:
            row = int(row)
        else:
            row = inf
    else:
        raise IncorrectCellLabel(label)

    return (row, col)

_a1_to_rowcol_unbounded(label='A1')

<re.Match object; span=(0, 2), match='A1'>


def render_pep440_feature(pieces):
    """Build up version string, used within "feature" branch of repository.

    Our goal: MERGE-POINT.post.devN+gHEX.BRANCH-NAME.M[.dirty]
        +) MERGE-POINT = Most recent common ancestor for `develop` and `master`
          *) Does not yet handle branch from `release-*`
        +) N = DISTANCE from the MERGE-POINT of `develop` and `master`
        +) M = DISTANCE from the MERGE-POINT of "feature" and `develop`

    Exceptions:
    1: no tags. 0.post.devDISTANCE+gHEX[.dirty]
    """
    if pieces["closest-tag"] and pieces["develop"]:
        rendered = pieces["closest-tag"]
        distance_to_develop = pieces["distance-to-develop"]
        distance_to_merge = pieces["distance-to-master"]
        distance_merge_to_tag = (pieces["distance"] - distance_to_merge)
        distance_dev_to_merge = (distance_to_merge - distance_to_develop)
        if (distance_merge_to_tag > 0):
            rendered += ".%d" % distance_merge_to_tag
        rendered += ".post.dev%d" % distance_dev_to_merge
        rendered += plus_or_dot(pieces)
        rendered += "g%s" % pieces["short"]
        rendered += ".%s" % pieces["branch"]
        rendered += ".%d" % distance_to_develop
    else:
        # exception #1
        rendered = "0.post.dev%d" % (pieces["distance"] - 1)
        rendered += plus_or_dot(pieces)
        rendered += "g%s" % pieces["short"]
    if pieces["dirty"]:
        rendered += ".dirty"
    return rendered

render_pep440_feature(pieces={'long': 'e60d005d389cb31b6e99f937e35adbe3fccb7aaf', 'short': 'e60d005', 'error': None, 'dirty': False, 'closest-tag': '0.8', 'distance': 3, 'branch': 'HEAD', 'distance-to-master': 0, 'develop': None, 'distance-to-develop': None, 'date': '2018-05-05T22:17:58-0700', 'authors': ['Padraic Shafer']})


def compute_loc(idx, shape):
    loc = [0] * len(shape)
    for i in range(len(shape)):
        prod = int(np.prod(shape[i + 1:]))
        loc[i] = idx // prod
        idx = idx % prod
    return tuple(loc)

compute_loc(idx=0, shape=(2, 4))


def byteatoms(characterstring):
            binary = characterstring.encode()
            atoms.extend(binary[i:i + 1] for i in range(len(binary)))

byteatoms(characterstring='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', atoms=[])


def __build_func(verb, args, kwargs={}):
        params = ['self']
        params += ['%s' % stringcase.snakecase(k) for k in args]
        params += ['%s=%s' % (stringcase.snakecase(k), v) for k, v in kwargs.items()]
        largs = list(args) + list(kwargs.keys())
        return eval(
            'lambda %s: self._%s(%s)' % (
                ','.join(params), verb, ','.join(['%s=%s' % (k, stringcase.snakecase(k)) for k in largs])
            )
        )

__build_func(verb='get', args=[], kwargs={})


def run_validator_for_test_file(filename: str) -> List:
    test_file_path = os.path.join(
        os.path.dirname(os.path.abspath(__file__)),
        'test_files',
        filename,
    )
    with open(test_file_path, 'r') as file_handler:
        raw_content = file_handler.read()
    tree = ast.parse(raw_content)
    checker = SuperMarionChecker(tree=tree, filename=test_file_path)

    return list(checker.run())

run_validator_for_test_file(filename='ok_pipe.py')

"from super_mario import BasePipeline, process_pipe\n\n\nclass SimplePipeline(BasePipeline):\n    pipeline = [\n        'sum_numbers',\n        'multiply_numbers',\n    ]\n\n    @process_pipe\n    @staticmethod\n    def sum_numbers(a, b):\n        return {'d': a + b}\n\n    @process_pipe\n    def multiply_numbers(c, d):\n        return {'e': c * d}\n"

{body=[<ast.ImportFrom object at 0x7feb90bccfa0>, <ast.ClassDef object at 0x7feb90bcceb0>], type_ignores=[]}

{body=[<ast.ImportFrom object at 0x7feb90bccfa0>, <ast.ClassDef object at 0x7feb90bcceb0>], type_ignores=[], parent=None}


def append(self, item):
        self._deque.append(item)
        if self._clear_all_updates:
            self._clear_all_updates = False
            self._clear_updates_by_symbol.clear()
            self._all_new_updates = 0
            self._new_updates_by_symbol.clear()
        if self._clear_updates_by_symbol.get(item['symbol']):
            self._clear_updates_by_symbol[item['symbol']] = False
            self._new_updates_by_symbol[item['symbol']] = 0
        self._new_updates_by_symbol[item['symbol']] = self._new_updates_by_symbol.get(item['symbol'], 0) + 1
        self._all_new_updates = (self._all_new_updates or 0) + 1

append(self=[], item={'symbol': 'BTC/USDT', 'data': 1})


def bit_length(num):
    # http://docs.python.org/dev/library/stdtypes.html#int.bit_length
    s = bin(num)  # binary representation:  bin(-37) --> '-0b100101'
    s = s.lstrip('-0b')  # remove leading zeros and minus sign
    return len(s)

bit_length(num=115792089237316195423570985008687907852837564279074904382605163141518161494337)


def __str__(self):
        self.reduce()
        sign = '-' if self.integer < 0 else ''
        integer_array = list(str(abs(self.integer)).rjust(self.decimals, '0'))
        index = len(integer_array) - self.decimals
        if index == 0:
            item = '0.'
        elif self.decimals < 0:
            item = '0' * (-self.decimals)
        elif self.decimals == 0:
            item = ''
        else:
            item = '.'
        integer_array.insert(index, item)
        return sign + ''.join(integer_array)

__str__(self=Precise(1393.938), self.base=10, self.decimals=3, self.integer=1393938)


def div(self, other, precision=18):
        distance = precision - self.decimals + other.decimals
        if distance == 0:
            numerator = self.integer
        elif distance < 0:
            exponent = self.base ** -distance
            numerator = self.integer // exponent
        else:
            exponent = self.base ** distance
            numerator = self.integer * exponent
        result, mod = divmod(numerator, other.integer)
        # python floors negative numbers down instead of truncating
        # if mod is zero it will be floored to itself so we do not add one
        result = result + 1 if result < 0 and mod else result
        return Precise(result, precision)

div(self=Precise(0.00000002), other=Precise(69696900000), precision=1, self.base=10, self.decimals=8, self.integer=2)


def _import_plugins(plugin_names):
    plugins = []
    for name, path in plugin_names.items():
        log.debug("Importing plugin %s: %s", name, path)
        if '.' not in path:
            plugins.append(__import__(path))
        else:
            package, module = path.rsplit('.', 1)
            module = __import__(path, fromlist=[module])
            plugins.append(module)
    return plugins

_import_plugins(plugin_names={'__builtin__': 'awscli.handlers'})


def test_soft_jaccard_score(y_true, y_pred, expected, eps):
    y_true = torch.tensor(y_true, dtype=torch.float32)
    y_pred = torch.tensor(y_pred, dtype=torch.float32)
    actual = F.soft_jaccard_score(y_pred, y_true, eps=eps)
    assert float(actual) == pytest.approx(expected, eps)

test_soft_jaccard_score(y_true=[1, 1, 1, 1], y_pred=[1, 1, 1, 1], expected=1.0, eps=1e-05)


def test_soft_jaccard_score_2(y_true, y_pred, expected, eps):
    y_true = torch.tensor(y_true, dtype=torch.float32)
    y_pred = torch.tensor(y_pred, dtype=torch.float32)
    actual = F.soft_jaccard_score(y_pred, y_true, dims=[1], eps=eps)
    actual = actual.mean()
    assert float(actual) == pytest.approx(expected, eps)

test_soft_jaccard_score_2(y_true=[[1, 1, 0, 0], [0, 0, 1, 1]], y_pred=[[1, 1, 0, 0], [0, 0, 1, 1]], expected=1.0, eps=1e-05)


def test_soft_dice_score(y_true, y_pred, expected, eps):
    y_true = torch.tensor(y_true, dtype=torch.float32)
    y_pred = torch.tensor(y_pred, dtype=torch.float32)
    actual = F.soft_dice_score(y_pred, y_true, eps=eps)
    assert float(actual) == pytest.approx(expected, eps)

test_soft_dice_score(y_true=[1, 1, 1, 1], y_pred=[1, 1, 1, 1], expected=1.0, eps=1e-05)


def test_soft_tversky_score(y_true, y_pred, expected, eps, alpha, beta):
    y_true = torch.tensor(y_true, dtype=torch.float32)
    y_pred = torch.tensor(y_pred, dtype=torch.float32)
    actual = F.soft_tversky_score(y_pred, y_true, eps=eps, alpha=alpha, beta=beta)
    assert float(actual) == pytest.approx(expected, eps)

test_soft_tversky_score(y_true=[1, 1, 1, 1], y_pred=[1, 1, 1, 1], expected=1.0, eps=1e-05, alpha=0.5, beta=0.5)


def forward(self, y_pred: torch.Tensor, y_true: torch.Tensor) -> torch.Tensor:

        assert y_true.size(0) == y_pred.size(0)

        if self.from_logits:
            # Apply activations to get [0..1] class probabilities
            # Using Log-Exp as this gives more numerically stable result and does not cause vanishing gradient on
            # extreme values 0 and 1
            if self.mode == MULTICLASS_MODE:
                y_pred = y_pred.log_softmax(dim=1).exp()
            else:
                y_pred = F.logsigmoid(y_pred).exp()

        bs = y_true.size(0)
        num_classes = y_pred.size(1)
        dims = (0, 2)

        if self.mode == BINARY_MODE:
            y_true = y_true.view(bs, 1, -1)
            y_pred = y_pred.view(bs, 1, -1)

            if self.ignore_index is not None:
                mask = y_true != self.ignore_index
                y_pred = y_pred * mask
                y_true = y_true * mask

        if self.mode == MULTICLASS_MODE:
            y_true = y_true.view(bs, -1)
            y_pred = y_pred.view(bs, num_classes, -1)

            if self.ignore_index is not None:
                mask = y_true != self.ignore_index
                y_pred = y_pred * mask.unsqueeze(1)

                y_true = F.one_hot((y_true * mask).to(torch.long), num_classes)  # N,H*W -> N,H*W, C
                y_true = y_true.permute(0, 2, 1) * mask.unsqueeze(1)  # N, C, H*W
            else:
                y_true = F.one_hot(y_true, num_classes)  # N,H*W -> N,H*W, C
                y_true = y_true.permute(0, 2, 1)  # N, C, H*W

        if self.mode == MULTILABEL_MODE:
            y_true = y_true.view(bs, num_classes, -1)
            y_pred = y_pred.view(bs, num_classes, -1)

            if self.ignore_index is not None:
                mask = y_true != self.ignore_index
                y_pred = y_pred * mask
                y_true = y_true * mask

        scores = self.compute_score(y_pred, y_true.type_as(y_pred), smooth=self.smooth, eps=self.eps, dims=dims)

        if self.log_loss:
            loss = -torch.log(scores.clamp_min(self.eps))
        else:
            loss = 1.0 - scores

        # Dice loss is undefined for non-empty classes
        # So we zero contribution of channel that does not have true pixels
        # NOTE: A better workaround would be to use loss term `mean(y_pred)`
        # for this case, however it will be a modified jaccard loss

        mask = y_true.sum(dims) > 0
        loss *= mask.to(loss.dtype)

        if self.classes is not None:
            loss = loss[self.classes]

        return self.aggregate_loss(loss)

forward(self=DiceLoss(), y_pred=tensor([[[[1., 1., 1.]]]]), y_true=tensor([[[[1, 1, 1]]]]), self._backward_hooks=OrderedDict(), self._backward_pre_hooks=OrderedDict(), self._buffers=OrderedDict(), self._forward_hooks=OrderedDict(), self._forward_hooks_always_called=OrderedDict(), self._forward_hooks_with_kwargs=OrderedDict(), self._forward_pre_hooks=OrderedDict(), self._forward_pre_hooks_with_kwargs=OrderedDict(), self._is_full_backward_hook=None, self._load_state_dict_post_hooks=OrderedDict(), self._load_state_dict_pre_hooks=OrderedDict(), self._modules=OrderedDict(), self._non_persistent_buffers_set=set(), self._parameters=OrderedDict(), self._state_dict_hooks=OrderedDict(), self._state_dict_pre_hooks=OrderedDict(), self.classes=None, self.eps=1e-07, self.from_logits=False, self.ignore_index=None, self.log_loss=False, self.mode='binary', self.reduction='mean', self.smooth=0.0, self.training=True)


def load_translation(self) -> "I18N":
        """Load translations from a JSON file based on the specified language."""
        try:
            dir_path = os.path.dirname(os.path.realpath(__file__))
            prompts_path = os.path.join(
                dir_path, f"../translations/{self.language}.json"
            )

            with open(prompts_path, "r") as f:
                self._translations = json.load(f)
        except FileNotFoundError:
            raise ValidationError(
                f"Trasnlation file for language '{self.language}' not found."
            )
        except json.JSONDecodeError:
            raise ValidationError(f"Error decoding JSON from the prompts file.")
        return self

load_translation(self=I18N(language='en'), self.__dict__={'language': 'en'}, self.__pydantic_extra__=None, self.__pydantic_fields_set__=set(), self.__pydantic_private__={}, self.language='en')

{'_translations': {'slices': {'observation': '\nObservation', 'task': 'Begin! This is VERY important to you, your job depends on it!\n\nCurrent Task: {input}', 'memory': 'This is the summary of your work so far:\n{chat_history}', 'role_playing': 'You are {role}.\n{backstory}\n\nYour personal goal is: {goal}', 'tools': 'TOOLS:\n------\nYou have access to only the following tools:\n\n{tools}\n\nTo use a tool, please use the exact following format:\n\n```\nThought: Do I need to use a tool? Yes\nAction: the action to take, should be one of [{tool_names}], just the name.\nAction Input: the input to the action\nObservation: the result of the action\n```\n\nWhen you have a response for your task, or if you do not need to use a tool, you MUST use the format:\n\n```\nThought: Do I need to use a tool? No\nFinal Answer: [your response here]', 'task_with_context': "{task}\nThis is the context you're working with:\n{context}"}, 'errors': {'used_too_many_tools': "I've used too many tools for this task. I'm going to give you my absolute BEST Final answer now and not use any more tools.", 'agent_tool_missing_param': '\nError executing tool. Missing exact 3 pipe (|) separated values. For example, `coworker|task|context`. I need to make sure to pass context as context.\n', 'agent_tool_unexsiting_coworker': '\nError executing tool. Co-worker mentioned on the Action Input not found, it must to be one of the following options: {coworkers}.\n', 'task_repeated_usage': "I just used the {tool} tool with input {tool_input}. So I already know the result of that and don't need to use it now.\n"}, 'tools': {'delegate_work': 'Useful to delegate a specific task to one of the following co-workers: {coworkers}.\nThe input to this tool should be a pipe (|) separated text of length 3 (three), representing the co-worker you want to ask it to (one of the options), the task and all actual context you have for the task.\nFor example, `coworker|task|context`.', 'ask_question': 'Useful to ask a question, opinion or take from on of the following co-workers: {coworkers}.\nThe input to this tool should be a pipe (|) separated text of length 3 (three), representing the co-worker you want to ask it to (one of the options), the question and all actual context you have for the question.\n For example, `coworker|question|context`.'}}}


def _to_str(size, suffixes, base):
    # type: (SupportsInt, Iterable[Text], int) -> Text
    try:
        size = int(size)
    except ValueError:
        raise TypeError("filesize requires a numeric value, not {!r}".format(size))
    if size == 1:
        return "1 byte"
    elif size < base:
        return "{:,} bytes".format(size)

    for i, suffix in enumerate(suffixes, 2):
        unit = base ** i
        if size < unit:
            break
    return "{:,.1f} {}".format((base * size / unit), suffix)

_to_str(size=1024, suffixes=('KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'), base=1024)


def _parse_time(t):
    t = " ".join(token.strip() for token in t.lower().split(" "))
    try:
        try:
            _t = time.strptime(t, "%b %d %Y")
        except ValueError:
            _t = time.strptime(t, "%b %d %H:%M")
    except ValueError:
        # Unknown time format
        return None

    year = _t.tm_year if _t.tm_year != 1900 else time.localtime().tm_year
    month = _t.tm_mon
    day = _t.tm_mday
    hour = _t.tm_hour
    minutes = _t.tm_min
    dt = datetime.datetime(year, month, day, hour, minutes, tzinfo=UTC)

    epoch_time = (dt - epoch_dt).total_seconds()
    return epoch_time

_parse_time(t='Jan 18  2006')

time.struct_time(tm_year=2006, tm_mon=1, tm_mday=18, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=2, tm_yday=18, tm_isdst=-1)

datetime.datetime(2006, 1, 18, 0, 0, tzinfo=<UTC>)


def __setitem__(self, key, value):
        # type: (_K, _V) -> None
        """Store a new views, potentially discarding an old value.
        """
        if key not in self:
            if len(self) >= self.cache_size:
                self.popitem(last=False)
        OrderedDict.__setitem__(self, key, value)

__setitem__(self=LRUCache(), key='foo', value=1)


def _insert(self, key, value):
        flat_key = self._serialize_key(key)
        i = self._index.get(flat_key, -1)
        if i >= 0:
            self._items[i] = (key, value)
        else:
            self._items.append((key, value))
            self._index[flat_key] = len(self._items) - 1

_insert(self=OrderedMapSerializedKey([]), key='みbob', value=199)


def _prep_ordered_arg(desired_length, arguments=None):
    """Ensure list of arguments passed to add_ordered_transitions has the proper length.
    Expands the given arguments and apply same condition, callback
    to all transitions if only one has been given.

    Args:
        desired_length (int): The size of the resulting list
        arguments (optional[str, reference or list]): Parameters to be expanded.
    Returns:
        list: Parameter sets with the desired length.
    """
    arguments = listify(arguments) if arguments is not None else [None]
    if len(arguments) != desired_length and len(arguments) != 1:
        raise ValueError("Argument length must be either 1 or the same length as "
                         "the number of transitions.")
    if len(arguments) == 1:
        return arguments * desired_length
    return arguments

_prep_ordered_arg(desired_length=3, arguments=None)


def config(_config=None, **kwargs):
    """
    A decorator for setting the default kwargs of `BaseHandler.crawl`.
    Any self.crawl with this callback will use this config.
    """
    if _config is None:
        _config = {}
    _config.update(kwargs)

    def wrapper(func):
        func._config = _config
        return func
    return wrapper

config(_config=None, kwargs={'age': 864000})

<function config.<locals>.wrapper at 0x7f6a10388ee0>


def quat_from_axis_angle(axis, angle):
        axis_ = np.array(axis, dtype=np.float64)
        half_angle = angle * 0.5
        ret = np.empty(4)
        ret[0] = math.cos(half_angle)
        ret[1:4] = math.sin(half_angle) * axis_
        return ret

quat_from_axis_angle(axis=[1.0, 0.0, 0.0], angle=6.1086523819801535)


def base64url_decode(input: Union[bytes, str]) -> bytes:
    input_bytes = force_bytes(input)

    rem = len(input_bytes) % 4

    if rem > 0:
        input_bytes += b"=" * (4 - rem)

    return base64.urlsafe_b64decode(input_bytes)

base64url_decode(input='hJtXIZ2uSN5kbQfbtTNWbpdmhkV8FJG-Onbc6mxCcYg')


def to_base64url_uint(val: int) -> bytes:
    if val < 0:
        raise ValueError("Must be a positive integer")

    int_bytes = bytes_from_int(val)

    if len(int_bytes) == 0:
        int_bytes = b"\x00"

    return base64url_encode(int_bytes)

to_base64url_uint(val=0)


def get_targets_from_csv(csv_filename):
        '''Returns list of Target objects parsed from CSV file.'''
        targets = []
        import csv
        with open(csv_filename, 'r') as csvopen:
            lines = []
            for line in csvopen:
                line = line.replace('\0', '')
                lines.append(line)
            csv_reader = csv.reader(lines,
                    delimiter=',',
                    quoting=csv.QUOTE_ALL,
                    skipinitialspace=True,
                    escapechar='\\')

            hit_clients = False
            for row in csv_reader:
                # Each 'row' is a list of fields for a target/client

                if len(row) == 0: continue

                if row[0].strip() == 'BSSID':
                    # This is the 'header' for the list of Targets
                    hit_clients = False
                    continue

                elif row[0].strip() == 'Station MAC':
                    # This is the 'header' for the list of Clients
                    hit_clients = True
                    continue

                if hit_clients:
                    # The current row corresponds to a 'Client' (computer)
                    try:
                        client = Client(row)
                    except (IndexError, ValueError) as e:
                        # Skip if we can't parse the client row
                        continue

                    if 'not associated' in client.bssid:
                        # Ignore unassociated clients
                        continue

                    # Add this client to the appropriate Target
                    for t in targets:
                        if t.bssid == client.bssid:
                            t.clients.append(client)
                            break

                else:
                    # The current row corresponds to a 'Target' (router)
                    try:
                        target = Target(row)
                        targets.append(target)
                    except Exception:
                        continue

        return targets

get_targets_from_csv(csv_filename='/local/rcs/XXX/code/pytrace-collector/logs/self_collected/tried/derv82+wifite2/derv82+wifite2/tests/files/airodump-weird-ssids.csv')

[<wifite.model.target.Target object at 0x7ff2ae4e23d0>]

[<wifite.model.target.Target object at 0x7ff2ae4e23d0>, <wifite.model.target.Target object at 0x7ff2ae4e2310>]

[<wifite.model.target.Target object at 0x7ff2ae4e23d0>, <wifite.model.target.Target object at 0x7ff2ae4e2310>, <wifite.model.target.Target object at 0x7ff2ae4e2a30>]

[<wifite.model.target.Target object at 0x7ff2ae4e23d0>, <wifite.model.target.Target object at 0x7ff2ae4e2310>, <wifite.model.target.Target object at 0x7ff2ae4e2a30>, <wifite.model.target.Target object at 0x7ff2ae4e2df0>]

[<wifite.model.target.Target object at 0x7ff2ae4e23d0>, <wifite.model.target.Target object at 0x7ff2ae4e2310>, <wifite.model.target.Target object at 0x7ff2ae4e2a30>, <wifite.model.target.Target object at 0x7ff2ae4e2df0>, <wifite.model.target.Target object at 0x7ff2ae4e2af0>]

<module 'csv' from '/local/rcs/XXX/miniforge3/envs/derv82+wifite2/lib/python3.9/csv.py'>

['\n', 'BSSID, First time seen, Last time seen, channel, Speed, Privacy, Cipher, Authentication, Power, # beacons, # IV, LAN IP, ID-length, ESSID, Key\n']

['\n', 'BSSID, First time seen, Last time seen, channel, Speed, Privacy, Cipher, Authentication, Power, # beacons, # IV, LAN IP, ID-length, ESSID, Key\n', 'AA:BB:CC:DD:EE:FF, 2018-04-06 18:21:23, 2018-04-06 18:21:24, 10,  54, WPA2, CCMP,PSK, -34,        5,        0,   0.  0.  0.  0,  24, Comma\\, no trailing space, \n']

['\n', 'BSSID, First time seen, Last time seen, channel, Speed, Privacy, Cipher, Authentication, Power, # beacons, # IV, LAN IP, ID-length, ESSID, Key\n', 'AA:BB:CC:DD:EE:FF, 2018-04-06 18:21:23, 2018-04-06 18:21:24, 10,  54, WPA2, CCMP,PSK, -34,        5,        0,   0.  0.  0.  0,  24, Comma\\, no trailing space, \n', 'AA:BB:CC:DD:EE:FF, 2018-04-06 18:19:17, 2018-04-06 18:19:19, 10,  54, WPA2, CCMP,PSK, -35,       18,        0,   0.  0.  0.  0,  20, \\"Quoted ESSID\\, Comma\\, no trailing spaces.   \\", \n']

'Station MAC, First time seen, Last time seen, Power, # packets, BSSID, Probed ESSIDs\n'

['BSSID', 'First time seen', 'Last time seen', 'channel', 'Speed', 'Privacy', 'Cipher', 'Authentication', 'Power', '# beacons', '# IV', 'LAN IP', 'ID-length', 'ESSID', 'Key']

['Station MAC', 'First time seen', 'Last time seen', 'Power', '# packets', 'BSSID', 'Probed ESSIDs']

{bssid='AA:BB:CC:DD:EE:FF', channel='10', encryption='WPA', power=66, beacons=5, ivs=0, essid_known=True, essid_len=24, essid='Comma, no trailing space', wps=3, decloaked=False, clients=[]}

{bssid='AA:BB:CC:DD:EE:FF', channel='10', encryption='WPA', power=65, beacons=18, ivs=0, essid_known=True, essid_len=20, essid='"Quoted ESSID, Comma, no trailing spaces.   "', wps=3, decloaked=False, clients=[]}

{bssid='AA:BB:CC:DD:EE:FF', channel='10', encryption='WPA', power=69, beacons=12, ivs=0, essid_known=True, essid_len=22, essid='Comma, Trailing space ', wps=3, decloaked=False, clients=[]}

{bssid='AA:BB:CC:DD:EE:FF', channel='10', encryption='WPA', power=71, beacons=15, ivs=0, essid_known=True, essid_len=30, essid='"quote" comma, trailing space ', wps=3, decloaked=False, clients=[]}

{bssid='AA:BB:CC:DD:EE:FF', channel='10', encryption='WPA', power=80, beacons=43, ivs=0, essid_known=False, essid_len=19, essid=None, wps=3, decloaked=False, clients=[]}


def f(e):
            result.append(e)

f(e=1, result=[])


def _create_key_val_str(input_dict: Union[Mapping[Any, Any], Any]) -> str:
    """
    Returns string of format {'key': val, 'key2': val2}
    Function is called recursively for nested dictionaries

    :param input_dict: dictionary to transform
    :return: (str) reformatted string
    """

    def list_to_str(input_list: List[str]) -> str:
        """
        Convert all list items to string.
        Function is called recursively for nested lists
        """
        converted_list = []
        for item in sorted(input_list, key=lambda x: str(x)):
            if isinstance(item, dict):
                item = _create_key_val_str(item)
            elif isinstance(item, list):
                item = list_to_str(item)

            converted_list.append(str(item))
        list_str = ", ".join(converted_list)
        return "[" + list_str + "]"

    items_list = []
    for key in sorted(input_dict.keys(), key=lambda x: str(x)):
        val = input_dict[key]
        if isinstance(val, dict):
            val = _create_key_val_str(val)
        elif isinstance(val, list):
            val = list_to_str(input_list=val)

        items_list.append(f"{key}: {val}")

    key_val_str = "{{{}}}".format(", ".join(items_list))
    return key_val_str

_create_key_val_str(input_dict={})

<function _create_key_val_str.<locals>.list_to_str at 0x7f684994adc0>


def _clean_unicode(url: str) -> str:
    """Clean up URLs, which use punycode to handle unicode chars.

    Applies percent encoding to URL path and query if required.

    Parameters
    ----------
    url : str
        URL that should be cleaned from unicode

    Returns
    -------
    str
        Cleaned URL

    """
    urllist = list(urlsplit(url))
    netloc = urllist[1]
    if _has_unicode(netloc):
        domains = netloc.split(".")
        for i, d in enumerate(domains):
            if _has_unicode(d):
                d = "xn--" + d.encode("punycode").decode("ascii")
                domains[i] = d
        urllist[1] = ".".join(domains)
        url = urlunsplit(urllist)

    # Clean up path/query/params, which use url-encoding to handle unicode chars
    chars = list(url)
    for i, x in enumerate(chars):
        if ord(x) > 128:
            chars[i] = quote(x)

    return "".join(chars)

_clean_unicode(url='http://example.com/test?type=2&ie=utf8&query=汉字')

['http', 'example.com', '/test', 'type=2&ie=utf8&query=汉字', '']


def class_to_tg(sub_class: str):
    trans = {"Online": "_online", "Offline": "_offline"}

    for upper, lower in trans.items():
        sub_class = sub_class.replace(upper, lower)

    return sub_class.lower()

class_to_tg(sub_class='YYeTsOffline')

{'Online': '_online', 'Offline': '_offline'}


def patch_terminal_size(monkeypatch):
    term_width = '250'
    term_height = '60'
    monkeypatch.setitem(os.environ, 'COLUMNS', term_width)
    monkeypatch.setitem(os.environ, 'LINES', term_height)

patch_terminal_size(monkeypatch={_setattr=[], _setitem=[], _cwd=None, _savesyspath=None})

{_setattr=[], _setitem=[(environ({'SHELL': '/bin/bash', 'LSCOLORS': 'Gxfxcxdxbxegedabagacad', 'USER_ZDOTDIR': '/home/XXX', 'COLORTERM': 'truecolor', 'LESS': '-R', 'TERM_PROGRAM_VERSION': '3.2a', 'GVM_VERSION': '1.0.22', 'CONDA_EXE': '/local/rcs/XXX/miniforge3/bin/conda', '_CE_M': '', 'TMUX': '/tmp/tmux-19200/default,59951,3', 'PKG_CONFIG_PATH': '/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay/lib/pkgconfig:/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay/lib/pkgconfig:', '_P9K_TTY': '/dev/pts/20', 'GVM_PATH_BACKUP': '/home/XXX/.gvm/bin:/local/rcs/XXX/miniforge3/envs/mal/bin:/local/rcs/XXX/miniforge3/condabin:/home/XXX/.gdrive-downloader:/local/arise/XXX/miniforge3/bin:/home/XXX/.gvm/pkgsets/go1.19.1/global/bin:/home/XXX/.gvm/gos/go1.19.1/bin:/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay/bin:/home/XXX/.gvm/bin:/home/XXX/.vscode-server/cli/servers/Stable-31c37ee8f63491495ac49e43b8544550fbae4533/server/bin/remote-cli:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/XXX/.local/bin:/home/XXX/.local/bin:/home/XXX/.local/bin', 'P9K_TTY': 'old', 'LC_FIG_SET_PARENT': '4c022497-5122-4b80-b325-c89bab32302a', 'PWD': '/local/rcs/XXX/code/pytrace-collector/logs/pypibugs/tried/AmmsA+Githeat/AmmsA+Githeat', 'LOGNAME': 'XXX', 'XDG_SESSION_TYPE': 'tty', 'CONDA_PREFIX': '/local/rcs/XXX/miniforge3/envs/AmmsA+Githeat', 'VSCODE_GIT_ASKPASS_NODE': '/home/XXX/.vscode-server/cli/servers/Stable-31c37ee8f63491495ac49e43b8544550fbae4533/server/node', 'MOTD_SHOWN': 'pam', 'VSCODE_INJECTION': '1', 'GVM_OVERLAY_PREFIX': '/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay', 'HOME': '/home/XXX', 'LANG': 'en_US.UTF-8', 'DYLD_LIBRARY_PATH': '/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay/lib:/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay/lib', 'LS_COLORS': 'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:', 'gvm_pkgset_name': 'global', 'SSL_CERT_DIR': '/usr/lib/ssl/certs', 'CONDA_PROMPT_MODIFIER': '(AmmsA+Githeat) ', 'GIT_ASKPASS': '/home/XXX/.vscode-server/cli/servers/Stable-31c37ee8f63491495ac49e43b8544550fbae4533/server/extensions/git/dist/askpass.sh', 'GVM_ROOT': '/home/XXX/.gvm', 'SSH_CONNECTION': '127.0.0.1 39996 127.0.0.1 22', 'GOROOT': '/home/XXX/.gvm/gos/go1.19.1', 'NVM_DIR': '/local/rcs/XXX/.nvm', 'VSCODE_GIT_ASKPASS_EXTRA_ARGS': '', 'XDG_SESSION_CLASS': 'user', 'PYTHONPATH': ':/local/rcs/XXX/code/pytrace-collector:/local/rcs/XXX/code/pytrace-collector/logs/pypibugs/tried/AmmsA+Githeat/AmmsA+Githeat', 'TERM': 'screen', 'ZSH': '/home/XXX/.oh-my-zsh', '_CE_CONDA': '', 'VSCODE_NONCE': 'd0bc7031-48a3-4719-8bb5-ef236ddd0016', 'ZDOTDIR': '/home/XXX', 'USER': 'XXX', 'TMUX_PANE': '%3', 'VSCODE_GIT_IPC_HANDLE': '/run/user/19200/vscode-git-13d67c6199.sock', 'CONDA_SHLVL': '3', 'SHLVL': '3', 'PAGER': 'less', '_P9K_SSH_TTY': '/dev/pts/20', 'XDG_SESSION_ID': '43', 'CONDA_PYTHON_EXE': '/local/rcs/XXX/miniforge3/bin/python', 'LD_LIBRARY_PATH': '/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay/lib:/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay/lib', 'XDG_RUNTIME_DIR': '/run/user/19200', 'SSL_CERT_FILE': '/usr/lib/ssl/certs/ca-certificates.crt', 'SSH_CLIENT': '127.0.0.1 46946 22', 'CONDA_DEFAULT_ENV': 'AmmsA+Githeat', 'P9K_SSH': '1', 'LC_ALL': 'en_US.UTF-8', 'VSCODE_GIT_ASKPASS_MAIN': '/home/XXX/.vscode-server/cli/servers/Stable-31c37ee8f63491495ac49e43b8544550fbae4533/server/extensions/git/dist/askpass-main.js', 'XDG_DATA_DIRS': '/usr/local/share:/usr/share:/var/lib/snapd/desktop', 'BROWSER': '/home/XXX/.vscode-server/cli/servers/Stable-31c37ee8f63491495ac49e43b8544550fbae4533/server/bin/helpers/browser.sh', 'PATH': '/home/XXX/.gdrive-downloader:/local/arise/XXX/miniforge3/bin:/home/XXX/.gvm/pkgsets/go1.19.1/global/bin:/home/XXX/.gvm/gos/go1.19.1/bin:/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay/bin:/home/XXX/.gvm/bin:/local/rcs/XXX/miniforge3/envs/AmmsA+Githeat/bin:/local/rcs/XXX/miniforge3/condabin:/home/XXX/.gdrive-downloader:/local/arise/XXX/miniforge3/bin:/home/XXX/.vscode-server/cli/servers/Stable-31c37ee8f63491495ac49e43b8544550fbae4533/server/bin/remote-cli:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/XXX/.local/bin:/home/XXX/.local/bin', 'DBUS_SESSION_BUS_ADDRESS': 'unix:path=/run/user/19200/bus', 'gvm_go_name': 'go1.19.1', 'CONDA_PREFIX_1': '/local/rcs/XXX/miniforge3', 'CONDA_PREFIX_2': '/local/rcs/XXX/miniforge3/envs/mal', 'OLDPWD': '/local/rcs/XXX/code/pytrace-collector', 'GOPATH': '/home/XXX/.gvm/pkgsets/go1.19.1/global', 'TERM_PROGRAM': 'tmux', 'VSCODE_IPC_HOOK_CLI': '/run/user/19200/vscode-ipc-518d6355-acaf-4714-a359-be3fe9f21e09.sock', '_': '/local/rcs/XXX/miniforge3/envs/AmmsA+Githeat/bin/python', 'PYTEST_CURRENT_TEST': 'test/test_interactive.py::test_print_left_header (setup)', 'COLUMNS': '250'}), 'COLUMNS', <notset>)], _cwd=None, _savesyspath=None}

{_setattr=[], _setitem=[(environ({'SHELL': '/bin/bash', 'LSCOLORS': 'Gxfxcxdxbxegedabagacad', 'USER_ZDOTDIR': '/home/XXX', 'COLORTERM': 'truecolor', 'LESS': '-R', 'TERM_PROGRAM_VERSION': '3.2a', 'GVM_VERSION': '1.0.22', 'CONDA_EXE': '/local/rcs/XXX/miniforge3/bin/conda', '_CE_M': '', 'TMUX': '/tmp/tmux-19200/default,59951,3', 'PKG_CONFIG_PATH': '/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay/lib/pkgconfig:/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay/lib/pkgconfig:', '_P9K_TTY': '/dev/pts/20', 'GVM_PATH_BACKUP': '/home/XXX/.gvm/bin:/local/rcs/XXX/miniforge3/envs/mal/bin:/local/rcs/XXX/miniforge3/condabin:/home/XXX/.gdrive-downloader:/local/arise/XXX/miniforge3/bin:/home/XXX/.gvm/pkgsets/go1.19.1/global/bin:/home/XXX/.gvm/gos/go1.19.1/bin:/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay/bin:/home/XXX/.gvm/bin:/home/XXX/.vscode-server/cli/servers/Stable-31c37ee8f63491495ac49e43b8544550fbae4533/server/bin/remote-cli:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/XXX/.local/bin:/home/XXX/.local/bin:/home/XXX/.local/bin', 'P9K_TTY': 'old', 'LC_FIG_SET_PARENT': '4c022497-5122-4b80-b325-c89bab32302a', 'PWD': '/local/rcs/XXX/code/pytrace-collector/logs/pypibugs/tried/AmmsA+Githeat/AmmsA+Githeat', 'LOGNAME': 'XXX', 'XDG_SESSION_TYPE': 'tty', 'CONDA_PREFIX': '/local/rcs/XXX/miniforge3/envs/AmmsA+Githeat', 'VSCODE_GIT_ASKPASS_NODE': '/home/XXX/.vscode-server/cli/servers/Stable-31c37ee8f63491495ac49e43b8544550fbae4533/server/node', 'MOTD_SHOWN': 'pam', 'VSCODE_INJECTION': '1', 'GVM_OVERLAY_PREFIX': '/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay', 'HOME': '/home/XXX', 'LANG': 'en_US.UTF-8', 'DYLD_LIBRARY_PATH': '/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay/lib:/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay/lib', 'LS_COLORS': 'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:', 'gvm_pkgset_name': 'global', 'SSL_CERT_DIR': '/usr/lib/ssl/certs', 'CONDA_PROMPT_MODIFIER': '(AmmsA+Githeat) ', 'GIT_ASKPASS': '/home/XXX/.vscode-server/cli/servers/Stable-31c37ee8f63491495ac49e43b8544550fbae4533/server/extensions/git/dist/askpass.sh', 'GVM_ROOT': '/home/XXX/.gvm', 'SSH_CONNECTION': '127.0.0.1 39996 127.0.0.1 22', 'GOROOT': '/home/XXX/.gvm/gos/go1.19.1', 'NVM_DIR': '/local/rcs/XXX/.nvm', 'VSCODE_GIT_ASKPASS_EXTRA_ARGS': '', 'XDG_SESSION_CLASS': 'user', 'PYTHONPATH': ':/local/rcs/XXX/code/pytrace-collector:/local/rcs/XXX/code/pytrace-collector/logs/pypibugs/tried/AmmsA+Githeat/AmmsA+Githeat', 'TERM': 'screen', 'ZSH': '/home/XXX/.oh-my-zsh', '_CE_CONDA': '', 'V...deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:', 'gvm_pkgset_name': 'global', 'SSL_CERT_DIR': '/usr/lib/ssl/certs', 'CONDA_PROMPT_MODIFIER': '(AmmsA+Githeat) ', 'GIT_ASKPASS': '/home/XXX/.vscode-server/cli/servers/Stable-31c37ee8f63491495ac49e43b8544550fbae4533/server/extensions/git/dist/askpass.sh', 'GVM_ROOT': '/home/XXX/.gvm', 'SSH_CONNECTION': '127.0.0.1 39996 127.0.0.1 22', 'GOROOT': '/home/XXX/.gvm/gos/go1.19.1', 'NVM_DIR': '/local/rcs/XXX/.nvm', 'VSCODE_GIT_ASKPASS_EXTRA_ARGS': '', 'XDG_SESSION_CLASS': 'user', 'PYTHONPATH': ':/local/rcs/XXX/code/pytrace-collector:/local/rcs/XXX/code/pytrace-collector/logs/pypibugs/tried/AmmsA+Githeat/AmmsA+Githeat', 'TERM': 'screen', 'ZSH': '/home/XXX/.oh-my-zsh', '_CE_CONDA': '', 'VSCODE_NONCE': 'd0bc7031-48a3-4719-8bb5-ef236ddd0016', 'ZDOTDIR': '/home/XXX', 'USER': 'XXX', 'TMUX_PANE': '%3', 'VSCODE_GIT_IPC_HANDLE': '/run/user/19200/vscode-git-13d67c6199.sock', 'CONDA_SHLVL': '3', 'SHLVL': '3', 'PAGER': 'less', '_P9K_SSH_TTY': '/dev/pts/20', 'XDG_SESSION_ID': '43', 'CONDA_PYTHON_EXE': '/local/rcs/XXX/miniforge3/bin/python', 'LD_LIBRARY_PATH': '/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay/lib:/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay/lib', 'XDG_RUNTIME_DIR': '/run/user/19200', 'SSL_CERT_FILE': '/usr/lib/ssl/certs/ca-certificates.crt', 'SSH_CLIENT': '127.0.0.1 46946 22', 'CONDA_DEFAULT_ENV': 'AmmsA+Githeat', 'P9K_SSH': '1', 'LC_ALL': 'en_US.UTF-8', 'VSCODE_GIT_ASKPASS_MAIN': '/home/XXX/.vscode-server/cli/servers/Stable-31c37ee8f63491495ac49e43b8544550fbae4533/server/extensions/git/dist/askpass-main.js', 'XDG_DATA_DIRS': '/usr/local/share:/usr/share:/var/lib/snapd/desktop', 'BROWSER': '/home/XXX/.vscode-server/cli/servers/Stable-31c37ee8f63491495ac49e43b8544550fbae4533/server/bin/helpers/browser.sh', 'PATH': '/home/XXX/.gdrive-downloader:/local/arise/XXX/miniforge3/bin:/home/XXX/.gvm/pkgsets/go1.19.1/global/bin:/home/XXX/.gvm/gos/go1.19.1/bin:/home/XXX/.gvm/pkgsets/go1.19.1/global/overlay/bin:/home/XXX/.gvm/bin:/local/rcs/XXX/miniforge3/envs/AmmsA+Githeat/bin:/local/rcs/XXX/miniforge3/condabin:/home/XXX/.gdrive-downloader:/local/arise/XXX/miniforge3/bin:/home/XXX/.vscode-server/cli/servers/Stable-31c37ee8f63491495ac49e43b8544550fbae4533/server/bin/remote-cli:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/XXX/.local/bin:/home/XXX/.local/bin', 'DBUS_SESSION_BUS_ADDRESS': 'unix:path=/run/user/19200/bus', 'gvm_go_name': 'go1.19.1', 'CONDA_PREFIX_1': '/local/rcs/XXX/miniforge3', 'CONDA_PREFIX_2': '/local/rcs/XXX/miniforge3/envs/mal', 'OLDPWD': '/local/rcs/XXX/code/pytrace-collector', 'GOPATH': '/home/XXX/.gvm/pkgsets/go1.19.1/global', 'TERM_PROGRAM': 'tmux', 'VSCODE_IPC_HOOK_CLI': '/run/user/19200/vscode-ipc-518d6355-acaf-4714-a359-be3fe9f21e09.sock', '_': '/local/rcs/XXX/miniforge3/envs/AmmsA+Githeat/bin/python', 'PYTEST_CURRENT_TEST': 'test/test_interactive.py::test_print_left_header (setup)', 'COLUMNS': '250', 'LINES': '60'}), 'LINES', <notset>)], _cwd=None, _savesyspath=None}


def generate_samples_loguniform(low, high, step, base, size=1):
    """Generate sample for (discrete)uniform density."""

    samples = base ** (random.uniform(low=logb(low, base), high=logb(high, base), size=size))
    if step:
        samples = step * np.floor(samples / step)
    return samples

generate_samples_loguniform(low=5.8884365535558836e-08, high=2.6977394324449206e-07, step=None, base=10, size=100000)


def parzen_estimator_build_posterior_parameter(parameter, observations):
    """TPE algorith transform a prior parameter into a posterior parameters using observations
    to build posterior.
    """
    posterior_parameter = None
    parameter_values = [observation.sample[parameter.name] for observation in observations]
    search_space = parameter.search_space
    if parameter.category == "categorical":
        """ TODO Compare mean (current implem) vs hyperopt approach."""
        prior_probabilities = np.array(search_space["probabilities"])
        posterior_probabilities = prior_probabilities
        if len(parameter_values) != 0:
            observed_probabilities = np.array([parameter_values.count(value)
                                               for value in search_space["values"]])
            observed_probabilities = observed_probabilities / np.sum(observed_probabilities)
            posterior_probabilities += observed_probabilities
        posterior_probabilities /= sum(posterior_probabilities)

        # Build param
        posterior_parameter = Parameter.from_dict(
            {
                "name": parameter.name,
                "category": "categorical",
                "search_space": {
                    "values": search_space["values"],
                    "probabilities": list(posterior_probabilities),
                }
            }
        )

    if parameter.category in ("uniform", "normal", "loguniform", "lognormal"):
        if parameter.category in ("uniform", "loguniform"):
            prior_mu = 0.5 * (search_space["high"] + search_space["low"])
            prior_sigma = (search_space["high"] - search_space["low"])
        elif parameter.category in ("normal", "lognormal"):
            prior_mu = search_space["mu"]
            prior_sigma = search_space["sigma"]

        # Mus
        mus = np.sort(parameter_values + [prior_mu])

        # Sigmas
        # Trick to get for each mu the greater distance from left and right neighbor
        # when low and high are not defined we use inf to get the only available distance
        # (right neighbor for sigmas[0] and left for sigmas[-1])
        tmp = np.concatenate(
            (
                [search_space.get("low", np.inf)],
                mus,
                [search_space.get("high", -np.inf)],
            )
        )
        sigmas = np.maximum(tmp[1:-1] - tmp[0:-2], tmp[2:] - tmp[1:-1])

        # Use formulas from hyperopt to clip sigmas
        sigma_max_value = prior_sigma
        sigma_min_value = prior_sigma / min(100.0, (1.0 + len(mus)))
        sigmas = np.clip(sigmas, sigma_min_value, sigma_max_value)

        # Fix prior sigma with correct value
        sigmas[np.where(mus == prior_mu)[0]] = prior_sigma

        posterior_parameter = Parameter.from_dict(
            {
                "name": parameter.name,
                "category": "mixture",
                "search_space": {
                    "parameters": [
                        {
                            "category": "normal",
                            "search_space": {
                                "mu": mu.tolist(),
                                "sigma": sigma.tolist(),
                                "low": search_space["low"],
                                "high": search_space["high"],
                                "step": search_space.get("step", None)
                            }
                        } if parameter.category[:3] != "log" else
                        {
                            "category": "lognormal",
                            "search_space": {
                                "mu": mu.tolist(),
                                "sigma": sigma.tolist(),
                                "low": search_space["low"],
                                "high": search_space["high"],
                                "step": search_space["step"],
                                "base": search_space["base"],
                            }
                        } for mu, sigma in zip(mus, sigmas)
                    ],
                    "weights": [1 / len(mus) for _ in range(len(mus))]
                }
            }
        )

    return posterior_parameter

parzen_estimator_build_posterior_parameter(parameter=x, observations=[])


def validate_categorical(search_space):
    # error = "Expected a dict with mandatory key 'values' (list) and optional key 'probabilities' (list)"
    search_space = search_space.copy()

    if type(search_space) != dict:
        raise ValueError
    if "values" not in search_space.keys() or type(search_space['values']) != list:
        raise ValueError
    if "probabilities" in search_space.keys() and (
            type(search_space['probabilities']) != list or
            len(search_space['probabilities']) != len(search_space['values'])):
        raise ValueError

    # Test that proba sum to 1 but we are lazy and we try directly
    if "probabilities" in search_space.keys():
        np.random.choice(range(len(search_space["probabilities"])),
                         p=search_space["probabilities"])

    if "probabilities" not in search_space.keys():
        number_of_values = len(search_space["values"])
        search_space["probabilities"] = list(np.ones(number_of_values) / number_of_values)

    return search_space

validate_categorical(search_space={'values': [0, 0.6283185307179586, 0.7853981633974483, 1.0471975511965976, 1.5707963267948966, 3.141592653589793]})


def __missing__(self, b):
        # Handle a cache miss, store encoded string in cache and return.
        if b in _TILDE_ENCODING_SAFE:
            res = chr(b)
        elif b == _space:
            res = "+"
        else:
            res = "~{:02X}".format(b)
        self[b] = res
        return res

__missing__(self={}, b=102)


def to_css_class(s):
    """
    Given a string (e.g. a table name) returns a valid unique CSS class.
    For simple cases, just returns the string again. If the string is not a
    valid CSS class (we disallow - and _ prefixes even though they are valid
    as they may be confused with browser prefixes) we strip invalid characters
    and add a 6 char md5 sum suffix, to make sure two tables with identical
    names after stripping characters don't end up with the same CSS class.
    """
    if css_class_re.match(s):
        return s
    md5_suffix = hashlib.md5(s.encode("utf8")).hexdigest()[:6]
    # Strip leading _, -
    s = s.lstrip("_").lstrip("-")
    # Replace any whitespace with hyphens
    s = "-".join(s.split())
    # Remove any remaining invalid characters
    s = css_invalid_chars_re.sub("", s)
    # Attach the md5 suffix
    bits = [b for b in (s, md5_suffix) if b]
    return "-".join(bits)

to_css_class(s='table/with/slashes.csv')


def client_factory(client_name, **kwargs):
    """Return a client for an external data set"""
    # set up
    dir_name = os.path.dirname(os.path.abspath(__file__))
    error_msg = 'No client found for name %s' % client_name
    client_key = client_name.upper()

    # find client
    try:
        client_vals = BALANCING_AUTHORITIES[client_key]
        module_name = client_vals['module']

        class_name = client_vals['class']
    except KeyError:
        raise ValueError(error_msg)

    # find module
    try:
        fp, pathname, description = imp.find_module(module_name, [dir_name])
    except ImportError:
        raise ValueError(error_msg)

    # load
    try:
        mod = imp.load_module(module_name, fp, pathname, description)
    finally:
        # Since we may exit via an exception, close fp explicitly.
        if fp:
            fp.close()

    # instantiate class
    try:
        client_inst = getattr(mod, class_name)(**kwargs)
    except AttributeError:
        raise ValueError(error_msg)

    # set name
    client_inst.NAME = client_name

    return client_inst

client_factory(client_name='MISO', kwargs={})

{'module': 'miso', 'class': 'MISOClient'}

('.py', 'r', 1)


def get_generation(ba_name, **kwargs):
    # get data
    c = client_factory(ba_name)
    data = c.get_generation(**kwargs)

    # log
    if len(data) == 0:
        msg = '%s: No generation data at %s with args %s' % (ba_name, datetime.utcnow().isoformat(),
                                                    kwargs)
        logger.warn(msg)

    # return
    return data

get_generation(ba_name='CAISO', kwargs={'latest': True})

"CAISO: No generation data at 2024-04-03T22:46:21.338362 with args {'latest': True}"

{options={'data': 'gen', 'latest': True, 'yesterday': False, 'start_at': False, 'end_at': False, 'sliceable': False, 'forecast': False, 'market': 'RT5M', 'freq': '10m'}, NAME='CAISO', session=<requests.sessions.Session object at 0x7fcc37a98b50>}


def get_load(ba_name, **kwargs):
    # get data
    c = client_factory(ba_name)
    data = c.get_load(**kwargs)

    # log
    if len(data) == 0:
        msg = '%s: No load data at %s with args %s' % (ba_name, datetime.utcnow().isoformat(),
                                                    kwargs)
        logger.warn(msg)

    # return
    return data

get_load(ba_name='PJM', kwargs={'latest': True})

"PJM: No load data at 2024-04-03T22:47:45.327834 with args {'latest': True}"

{options={'data': 'load', 'latest': True, 'start_at': None, 'end_at': None, 'forecast': False, 'sliceable': False}, NAME='PJM', session=<requests.sessions.Session object at 0x7fcc37745f10>}


def xldate_as_tuple(xldate, datemode):
    if datemode not in (0, 1):
        raise XLDateBadDatemode(datemode)
    if xldate == 0.00:
        return (0, 0, 0, 0, 0, 0)
    if xldate < 0.00:
        raise XLDateNegative(xldate)
    xldays = int(xldate)
    frac = xldate - xldays
    seconds = int(round(frac * 86400.0))
    assert 0 <= seconds <= 86400
    if seconds == 86400:
        hour = minute = second = 0
        xldays += 1
    else:
        # second = seconds % 60; minutes = seconds // 60
        minutes, second = divmod(seconds, 60)
        # minute = minutes % 60; hour    = minutes // 60
        hour, minute = divmod(minutes, 60)
    if xldays >= _XLDAYS_TOO_LARGE[datemode]:
        raise XLDateTooLarge(xldate)

    if xldays == 0:
        return (0, 0, 0, hour, minute, second)

    if xldays < 61 and datemode == 0:
        raise XLDateAmbiguous(xldate)

    jdn = xldays + _JDN_delta[datemode]
    yreg = (ifd(ifd(jdn * 4 + 274277, 146097) * 3, 4) + jdn + 1363) * 4 + 3
    mp = ifd(yreg % 1461, 4) * 535 + 333
    d = ifd(mp % 16384, 535) + 1
    # mp /= 16384
    mp >>= 14
    if mp >= 10:
        return (ifd(yreg, 1461) - 4715, mp - 9, d, hour, minute, second)
    else:
        return (ifd(yreg, 1461) - 4716, mp + 3, d, hour, minute, second)

xldate_as_tuple(xldate=2741.0, datemode=0)


def xldate_from_date_tuple(date_tuple, datemode):
    """Create an excel date from a tuple of (year, month, day)"""
    year, month, day = date_tuple

    if datemode not in (0, 1):
        raise XLDateBadDatemode(datemode)

    if year == 0 and month == 0 and day == 0:
        return 0.00

    if not (1900 <= year <= 9999):
        raise XLDateBadTuple("Invalid year: %r" % ((year, month, day),))
    if not (1 <= month <= 12):
        raise XLDateBadTuple("Invalid month: %r" % ((year, month, day),))
    if  day < 1 \
    or (day > _days_in_month[month] and not(day == 29 and month == 2 and _leap(year))):
        raise XLDateBadTuple("Invalid day: %r" % ((year, month, day),))

    Yp = year + 4716
    M = month
    if M <= 2:
        Yp = Yp - 1
        Mp = M + 9
    else:
        Mp = M - 3
    jdn = ifd(1461 * Yp, 4) + ifd(979 * Mp + 16, 32) + \
        day - 1364 - ifd(ifd(Yp + 184, 100) * 3, 4)
    xldays = jdn - _JDN_delta[datemode]
    if xldays <= 0:
        raise XLDateBadTuple("Invalid (year, month, day): %r" % ((year, month, day),))
    if xldays < 61 and datemode == 0:
        raise XLDateAmbiguous("Before 1900-03-01: %r" % ((year, month, day),))
    return float(xldays)

xldate_from_date_tuple(date_tuple=(1907, 7, 3), datemode=0)


def _add_notice_to_docstring(doc, no_doc_str, notice):
    """Adds a deprecation notice to a docstring."""
    if not doc:
        lines = [no_doc_str]

    else:
        lines = _normalize_docstring(doc).splitlines()

    notice = [''] + notice

    if len(lines) > 1:
        # Make sure that we keep our distance from the main body
        if lines[1].strip():
            notice.append('')

        lines[1:1] = notice
    else:
        lines += notice

    return '\n'.join(lines)

_add_notice_to_docstring(doc=None, no_doc_str='DEPRECATED FUNCTION', notice=['\n            .. warning::\n                **THIS FUNCTION IS DEPRECATED:** It will be removed after after 2018-09-30.\n                *Instructions for updating:* This API is deprecated. Please use as `tl.logging.warning`.\n        '])

['', '\n            .. warning::\n                **THIS FUNCTION IS DEPRECATED:** It will be removed after after 2018-09-30.\n                *Instructions for updating:* This API is deprecated. Please use as `tl.logging.warning`.\n        ']

['DEPRECATED FUNCTION', '', '\n            .. warning::\n                **THIS FUNCTION IS DEPRECATED:** It will be removed after after 2018-09-30.\n                *Instructions for updating:* This API is deprecated. Please use as `tl.logging.warning`.\n        ']


def calculate_r_wheels(tyre_dimensions):
    """
    Calculates the radius of the wheels [m] from the tyre dimensions.

    :param tyre_dimensions:
        Tyre dimensions.

        .. note:: The fields are : use, nominal_section_width, aspect_ratio,
           carcass, diameter, load_index, speed_rating, and additional_marks.
    :type tyre_dimensions: dict

    :return:
        Radius of the wheels [m].
    :rtype: float
    """
    if 'diameter' in tyre_dimensions:
        if tyre_dimensions['code'] == 'pax':
            return tyre_dimensions['diameter'] / 2000  # Diameter is in mm.
        return tyre_dimensions['diameter'] * 0.0254  # Diameter is in inches.
    a = tyre_dimensions['aspect_ratio'] / 100  # Aspect ratio is Height/Width.
    w = tyre_dimensions['nominal_section_width']
    if tyre_dimensions.get('code', 'iso') == 'iso':
        w /= 1000  # Width is in mm.
    else:
        w *= 0.0254  # Width is in inches.

    dr = tyre_dimensions['rim_diameter'] * 0.0254  # Rim is in inches.
    return a * w + dr / 2

calculate_r_wheels(tyre_dimensions={'code': 'iso', 'carcass': 'R', 'nominal_section_width': 265.0, 'use': 'LT', 'load_range': 'D', 'rim_diameter': 15.0, 'aspect_ratio': 75.0})


def create_dummy_class(klass, dependency, message=""):
    """
    When a dependency of a class is not available, create a dummy class which throws ImportError
    when used.

    Args:
        klass (str): name of the class.
        dependency (str): name of the dependency.
        message: extra message to print
    Returns:
        class: a class object
    """
    err = "Cannot import '{}', therefore '{}' is not available.".format(dependency, klass)
    if message:
        err = err + " " + message

    class _DummyMetaClass(type):
        # throw error on class attribute access
        def __getattr__(_, __):  # noqa: B902
            raise ImportError(err)

    class _Dummy(object, metaclass=_DummyMetaClass):
        # throw error on constructor
        def __init__(self, *args, **kwargs):
            raise ImportError(err)

    return _Dummy

create_dummy_class(klass='DeformConv', dependency='detectron2._C', message='detectron2 is not compiled successfully, please build following the instructions!')

"Cannot import 'detectron2._C', therefore 'DeformConv' is not available. detectron2 is not compiled successfully, please build following the instructions!"

"Cannot import 'detectron2._C', therefore 'DeformConv' is not available."


def create_dummy_func(func, dependency, message=""):
    """
    When a dependency of a function is not available, create a dummy function which throws
    ImportError when used.

    Args:
        func (str): name of the function.
        dependency (str or list[str]): name(s) of the dependency.
        message: extra message to print
    Returns:
        function: a function object
    """
    err = "Cannot import '{}', therefore '{}' is not available.".format(dependency, func)
    if message:
        err = err + " " + message

    if isinstance(dependency, (list, tuple)):
        dependency = ",".join(dependency)

    def _dummy(*args, **kwargs):
        raise ImportError(err)

    return _dummy

create_dummy_func(func='deform_conv', dependency='detectron2._C', message='detectron2 is not compiled successfully, please build following the instructions!')

"Cannot import 'detectron2._C', therefore 'deform_conv' is not available. detectron2 is not compiled successfully, please build following the instructions!"

"Cannot import 'detectron2._C', therefore 'deform_conv' is not available."

<function create_dummy_func.<locals>._dummy at 0x7f3337cdfd30>


def format_pair(prefix, arg, value):
    if arg is _arg_source_missing:
        arg_lines = []
        value_prefix = prefix
    else:
        arg_lines = indented_lines(prefix, arg)
        value_prefix = arg_lines[-1] + ': '

    looksLikeAString = value[0] + value[-1] in ["''", '""']
    if looksLikeAString:  # Align the start of multiline strings.
        value = prefixLinesAfterFirst(' ', value)

    value_lines = indented_lines(value_prefix, value)
    lines = arg_lines[:-1] + value_lines
    return '\n'.join(lines)

format_pair(prefix='    ', arg='multilineStr', value="'line1\nline2'")


def prefixLinesAfterFirst(prefix, s):
    lines = s.splitlines(True)

    for i in range(1, len(lines)):
        lines[i] = prefix + lines[i]

    return ''.join(lines)

prefixLinesAfterFirst(prefix=' ', s="'line1\nline2'")


def _sort(a, aux, lo, hi):
        if lo >= hi:
            return

        if hi - lo + 1 < MergeSort.CUTOFF:
            InsertionSort.sort(a, lo, hi)
            return

        mid = lo + (hi - lo) // 2
        MergeSort._sort(a, aux, lo, mid)
        MergeSort._sort(a, aux, mid + 1, hi)
        MergeSort._merge(a, aux, lo, mid, hi)

_sort(a=[4, 2, 1, 23, 4, 5, 6, 7, 8, 9, 20, 11, 13, 34, 66], aux=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], lo=0, hi=7)


def version_compare(self, other):
        "Compares version of the form [epoch:]upstream-version[-debian-revision]" \
        + " according to Debian package version number format."

        # compare epoch
        diff = self.epoch - other.epoch
        if diff != 0:
            return diff

        # compare upstream version and debian revision
        for slf, othr in (self.upstream_version, other.upstream_version), (self.revision, other.revision):
            i = 0
            while len(slf) > 0 or len(othr) > 0:
                decimal = (i % 2 == 1)
                slf_part, slf = self._get_part(slf, decimal=decimal)
                othr_part, othr = self._get_part(othr, decimal=decimal)
                diff = self._compare_parts(slf_part, othr_part, decimal=decimal)
                if diff != 0:
                    return diff
                i += 1

        # versions are equal
        return 0

version_compare(self=2.2.0~rc5, other=2.2.0~rc5, self.epoch=0, self.revision='0', self.revision_allowed_chars=('.', '+', '~'), self.upstream_version='2.2.0~rc5', self.upstream_version_allowed_chars=('.', '+', '~', '-', ':'), self.version='2.2.0~rc5')


def _setHeaderBaseData(array, coeff_name, hao, long_name) -> None:
        if not isinstance(array, (np.ndarray, np.float32, np.int32,np.float64)):
            print(type(array))
            raise HeaderArrayObj.UnsupportedArrayType("'array' must be of numpy.ndarray type.")

        # Defaults handling
        if coeff_name is None:
            coeff_name = " " * 12
        if long_name is None:
            long_name = coeff_name
        if len(coeff_name) < 12:
            coeff_name = coeff_name.ljust(12)
        if len(long_name) < 70:
            long_name = long_name.ljust(70)
        hao.array = array
        hao.coeff_name = coeff_name
        hao.long_name = long_name

_setHeaderBaseData(array=array(['at 2/03/2018 4:22:38 PM                                               '],      dtype='<U70'), coeff_name=None, hao={_coeff_name='', _array=None, _sets=None, _long_name=''}, long_name='Creation Date and Time                                                ')

'Creation Date and Time                                                '

{_coeff_name='            ', _array=array(['at 2/03/2018 4:22:38 PM                                               '],      dtype='<U70'), _sets=None, _long_name='Creation Date and Time                                                '}


def SetHeaderFromData(setName: str, setElements:'Union[List[str], np.array]',  long_name: str=None):
        if not isinstance(setName,str):
            raise TypeError("setName must be of type str")
        if len(setName.strip()) > 12 :
            raise ValueError("setName is restricted to 12 Characters")
        if long_name is None: long_name=""
        if isinstance(long_name, str):
            long_name="Set "+setName.strip()+" "+long_name.strip()
        else:
            raise TypeError("LongName must be string")

        if isinstance(setElements,(list,np.ndarray)):
            if not all([isinstance(el,str) for el in setElements]):
                raise TypeError("All Set Elements must be of type str")
            if not all([len(el)<=12 for el in setElements]):
                raise ValueError("Set Elelement strings must be 12 characters at most")

        if isinstance(setElements,list):
            array=np.array(setElements)
            setElDict={setName:setElements}
        elif isinstance(setElements,np.ndarray):
            array=setElements
            setElDict = {setName: setElements.tolist()}
        else:
            raise TypeError("SetElemenets must be list of str or np array of strings")

        return HeaderArrayObj.HeaderArrayFromData(array=array, long_name=long_name, sets=[setName], setElDict=setElDict)

SetHeaderFromData(setName='sect', setElements=array(['s1          ', 's2          '], dtype='<U12'), long_name=' Sectors                                                                        ')

' Sectors                                                                        '


def set_bbox(self, bbox: Rect) -> None:
        (x0, y0, x1, y1) = bbox
        self.x0 = x0
        self.y0 = y0
        self.x1 = x1
        self.y1 = y1
        self.width = x1 - x0
        self.height = y1 - y0
        self.bbox = bbox

set_bbox(self=REPR FAILED, bbox=[0, 100, 0, 100])


def calibrated_fps(calibrate):
    """Calibration of the dynamic frames per second engine.

    I've started with the equation y = log10(x + m) * k + n, where:
      y is the desired fps, m and n are horizontal and vertical translation,
      k is a calibration factor, computed from some user input c (see readme for details).

    Considering minfps and maxfps as given constants, I came to:
      fps = log10(x + 1) * k + minfps, which must be equal to maxfps for x = c,
    so the factor k = (maxfps - minfps) / log10(c + 1), and
      fps = log10(x + 1) * (maxfps - minfps) / log10(c + 1) + minfps

    Neat! ;)

    Args:
        calibrate (float): user provided

    Returns:
        a callable to calculate the fps

    """
    min_fps, max_fps = 2., 60.
    calibrate = max(1e-6, calibrate)
    adjust_log_curve = 100. / min(calibrate, 100.)  # adjust the curve for small numbers
    factor = (max_fps - min_fps) / math.log10((calibrate * adjust_log_curve) + 1.)

    def fps(rate):
        if rate <= 0:
            return 10.  # bootstrap speed
        if rate < calibrate:
            return math.log10((rate * adjust_log_curve) + 1.) * factor + min_fps
        return max_fps

    return fps

calibrated_fps(calibrate=-5.0)

<function calibrated_fps.<locals>.fps at 0x7f355669f1f0>


def getblockimpl(lines, first, last, pilcrow):
    max = len(lines) - 1
    first -= 1
    last -= 1
    i = first
    while i < max and not hastext(lines[i]):
        if i >= last and istoplevel(lines[i + 1]):
            return None, None, '# Nothing to send.' + pilcrow + eol
        i += 1
    while last < max and not istoplevel(lines[last + 1]):
        last += 1
    while first < last and not hastext(lines[first]):
        first += 1
    while first and not istoplevel(lines[first]):
        first -= 1
    lines[last] # Check for out of range.
    return first, last, eol.join(l for l in lines[first:last + 1] if hastext(l)) + pilcrow + eol

getblockimpl(lines=['', 'hello', 'function with', ' indented block', 'class with', '', '  block after blank', '  \tand its own indented block', '\t', '  and back again after a wrong blank', '', 'something else', '\t', ' \t', 'last'], first=10, last=11, pilcrow='')


def _from_timetuple(self, t):
        self.days_from_epoch = calendar.timegm(t) // Date.DAY

_from_timetuple(self=Date(0), t=time.struct_time(tm_year=2024, tm_mon=4, tm_mday=3, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=2, tm_yday=94, tm_isdst=-1))


def _insert(self, key, value):
        flat_key = self._serialize_key(key)
        i = self._index.get(flat_key, -1)
        if i >= 0:
            self._items[i] = (key, value)
        else:
            self._items.append((key, value))
            self._index[flat_key] = len(self._items) - 1

_insert(self=OrderedMapSerializedKey([]), key='みbob', value=199)


def stringified_dict_contains_value(key, value, str_dict):
    """Checks if dict in for of string like "{'test': 5}" contains
    key/value pair. This works faster, then creating actual dict
    from string since this operation is called for each task in case
    of kwargs search."""
    if not str_dict:
        return False
    value = str(value)
    try:
        # + 3 for key right quote, one for colon and one for space
        key_index = str_dict.index(key) + len(key) + 3
    except ValueError:
        return False
    try:
        comma_index = str_dict.index(',', key_index)
    except ValueError:
        # last value in dict
        comma_index = str_dict.index('}', key_index)
    return str(value) == str_dict[key_index:comma_index].strip('"\'')

stringified_dict_contains_value(key='test', value=5, str_dict="{'test': 5}")


def merge_args_into_config(args, config_params):
  final_args = copy.deepcopy(config_params)
  config_keys = config_params.keys()
  for key, value in args.items():
    if key in config_keys:
      if any([isinstance(value, t) for t in [str, bool, float, int]]):
        # Overwrites config value with args value.
        final_args[key] = value
      elif isinstance(value, list):
        # Appends args values to config values.
        final_args[key] = value + config_params[key]
      elif isinstance(value, dict):
        # Updates config params with args params.
        final_args[key].update(**value)
    else:
      final_args[key] = value
  return final_args

merge_args_into_config(args={'input_folder': 'foo/bar', 'resize_images': False, 'im_size': 500, 'compress_pdf': False, 'pdf_im_resolution': 500, 'images_allowlist': {'path1/': 1000}, 'commands_to_delete': ['\\todo1'], 'use_external_tikz': 'foo/bar/tikz'}, config_params={'input_folder': 'foo_/bar_', 'resize_images': True, 'im_size': 1000, 'compress_pdf': True, 'pdf_im_resolution': 1000, 'images_allowlist': {'path2/': 1000}, 'commands_to_delete': ['\\todo2'], 'use_external_tikz': 'foo_/bar_/tikz_'})

{'input_folder': 'foo/bar', 'resize_images': False, 'im_size': 500, 'compress_pdf': False, 'pdf_im_resolution': 500, 'images_allowlist': {'path2/': 1000, 'path1/': 1000}, 'commands_to_delete': ['\\todo1', '\\todo2'], 'use_external_tikz': 'foo_/bar_/tikz_'}

{'input_folder': 'foo/bar', 'resize_images': True, 'im_size': 1000, 'compress_pdf': True, 'pdf_im_resolution': 1000, 'images_allowlist': {'path2/': 1000}, 'commands_to_delete': ['\\todo2'], 'use_external_tikz': 'foo_/bar_/tikz_'}

{'input_folder': 'foo/bar', 'resize_images': False, 'im_size': 1000, 'compress_pdf': True, 'pdf_im_resolution': 1000, 'images_allowlist': {'path2/': 1000}, 'commands_to_delete': ['\\todo2'], 'use_external_tikz': 'foo_/bar_/tikz_'}

{'input_folder': 'foo/bar', 'resize_images': False, 'im_size': 500, 'compress_pdf': True, 'pdf_im_resolution': 1000, 'images_allowlist': {'path2/': 1000}, 'commands_to_delete': ['\\todo2'], 'use_external_tikz': 'foo_/bar_/tikz_'}

{'input_folder': 'foo/bar', 'resize_images': False, 'im_size': 500, 'compress_pdf': False, 'pdf_im_resolution': 1000, 'images_allowlist': {'path2/': 1000}, 'commands_to_delete': ['\\todo2'], 'use_external_tikz': 'foo_/bar_/tikz_'}

{'input_folder': 'foo/bar', 'resize_images': False, 'im_size': 500, 'compress_pdf': False, 'pdf_im_resolution': 500, 'images_allowlist': {'path2/': 1000}, 'commands_to_delete': ['\\todo2'], 'use_external_tikz': 'foo_/bar_/tikz_'}

{'input_folder': 'foo/bar', 'resize_images': False, 'im_size': 500, 'compress_pdf': False, 'pdf_im_resolution': 500, 'images_allowlist': {'path2/': 1000, 'path1/': 1000}, 'commands_to_delete': ['\\todo2'], 'use_external_tikz': 'foo_/bar_/tikz_'}

{'input_folder': 'foo/bar', 'resize_images': False, 'im_size': 500, 'compress_pdf': False, 'pdf_im_resolution': 500, 'images_allowlist': {'path2/': 1000, 'path1/': 1000}, 'commands_to_delete': ['\\todo1', '\\todo2'], 'use_external_tikz': 'foo/bar/tikz'}

dict_keys(['input_folder', 'resize_images', 'im_size', 'compress_pdf', 'pdf_im_resolution', 'images_allowlist', 'commands_to_delete', 'use_external_tikz'])


def _remove_command(text, command, keep_text=False):
  """Removes '\\command{*}' from the string 'text'.

  Regex `base_pattern` used to match balanced parentheses taken from:
  https://stackoverflow.com/questions/546433/regular-expression-to-match-balanced-parentheses/35271017#35271017
  """
  base_pattern = r'\\' + command + r'\{((?:[^{}]+|\{(?1)\})*)\}'
  # Loops in case of nested commands that need to retain text, e.g.,
  # \red{hello \red{world}}.
  while True:
    all_substitutions = []
    has_match = False
    for match in regex.finditer(base_pattern, text):
      # In case there are only spaces or nothing up to the following newline,
      # adds a percent, not to alter the newlines.
      has_match = True
      new_substring = (
          ''
          if not keep_text
          else text[match.span()[0] + len(command) + 2 : match.span()[1] - 1]
      )
      if match.span()[1] < len(text):
        next_newline = text[match.span()[1] :].find('\n')
        if next_newline != -1:
          text_until_newline = text[
              match.span()[1] : match.span()[1] + next_newline
          ]
          if (
              not text_until_newline or text_until_newline.isspace()
          ) and not keep_text:
            new_substring = '%'
      all_substitutions.append(
          (match.span()[0], match.span()[1], new_substring)
      )

    for start, end, new_substring in reversed(all_substitutions):
      text = text[:start] + new_substring + text[end:]

    if not keep_text or not has_match:
      break

  return text

_remove_command(text='A\\todo{B\nC}D\nE\n\\end{document}', command='todo', keep_text=False)

'A\\todo{B\nC}D\nE\n\\end{document}'

'A\\todo{B\nC}D\nE\n\\end{document}'

'AD\nE\n\\end{document}'

<regex.Match object; span=(1, 11), match='\\todo{B\nC}'>


def _search_reference(filename, contents, strict=False):
  """Returns a match object if filename is referenced in contents, and None otherwise.

  If not strict mode, path prefix and extension are optional.
  """
  if strict:
    # regex pattern for strict=True for path/to/img.ext:
    # \{[\s%]*path/to/img\.ext[\s%]*\}
    filename_regex = filename.replace('.', r'\.')
  else:
    filename_path = Path(filename)

    # make extension optional
    root, extension = filename_path.stem, filename_path.suffix
    basename_regex = '{}({})?'.format(
        regex.escape(root), regex.escape(extension)
    )

    # iterate through parent fragments to make path prefix optional
    path_prefix_regex = ''
    for fragment in reversed(filename_path.parents):
      if fragment.name == '.':
        continue
      fragment = regex.escape(fragment.name)
      path_prefix_regex = '({}{}{})?'.format(
          path_prefix_regex, fragment, os.sep
      )

    # Regex pattern for strict=True for path/to/img.ext:
    # \{[\s%]*(<path_prefix>)?<basename>(<ext>)?[\s%]*\}
    filename_regex = path_prefix_regex + basename_regex

  # Some files 'path/to/file' are referenced in tex as './path/to/file' thus
  # adds prefix for relative paths starting with './' or '.\' to regex search.
  filename_regex = r'(.' + os.sep + r')?' + filename_regex

  # Pads with braces and optional whitespace/comment characters.
  patn = r'\{{[\s%]*{}[\s%]*\}}'.format(filename_regex)
  # Picture references in LaTeX are allowed to be in different cases.
  return regex.search(patn, contents, regex.IGNORECASE)

_search_reference(filename='to/img.ext', contents='{img.ext}', strict=False)

'{img.ext}'

'{img.ext}'


def apply_changes(file_path: str, changes: List, confirm: bool = False):
    """
    Pass changes as loaded json (list of dicts)
    """
    with open(file_path) as f:
        original_file_lines = f.readlines()

    # Filter out explanation elements
    operation_changes = [change for change in changes if "operation" in change]
    explanations = [
        change["explanation"] for change in changes if "explanation" in change
    ]

    # Sort the changes in reverse line order
    operation_changes.sort(key=lambda x: x["line"], reverse=True)

    file_lines = original_file_lines.copy()
    for change in operation_changes:
        operation = change["operation"]
        line = change["line"]
        content = change["content"]

        if operation == "Replace":
            file_lines[line - 1] = content + "\n"
        elif operation == "Delete":
            del file_lines[line - 1]
        elif operation == "InsertAfter":
            file_lines.insert(line, content + "\n")

    # Print explanations
    cprint("Explanations:", "blue")
    for explanation in explanations:
        cprint(f"- {explanation}", "blue")

    # Display changes diff
    print("\nChanges to be made:")
    diff = difflib.unified_diff(original_file_lines, file_lines, lineterm="")
    for line in diff:
        if line.startswith("+"):
            cprint(line, "green", end="")
        elif line.startswith("-"):
            cprint(line, "red", end="")
        else:
            print(line, end="")

    if confirm:
        # check if user wants to apply changes or exit
        confirmation = input("Do you want to apply these changes? (y/n): ")
        if confirmation.lower() != "y":
            print("Changes not applied")
            sys.exit(0)

    with open(file_path, "w") as f:
        f.writelines(file_lines)
    print("Changes applied.")

apply_changes(file_path='/tmp/tmp6qrrn_j9', changes=[{'operation': 'Replace', 'line': 2, 'content': 'new second line'}], confirm=False)

'new second line'

['first line\n', 'new second line\n', 'third line']

<_io.TextIOWrapper name='/tmp/tmp6qrrn_j9' mode='r' encoding='UTF-8'>

<_io.TextIOWrapper name='/tmp/tmp6qrrn_j9' mode='w' encoding='UTF-8'>

['first line\n', 'second line\n', 'third line']

'new second line'

<generator object unified_diff at 0x7f5b71b2cba0>