Пример #1
0
 def _address_rxp(self, addr):
     """ Create a regex string for addresses, that matches several representations:
         - with(out) '0x' prefix
         - `pex` version
         This function takes care of maintaining additional lookup keys for substring matches.
         In case the given string is no address, it returns the original string.
     """
     try:
         addr = str(to_checksum_address(addr))
         rxp = "(?:0x)?" + pex(
             to_canonical_address(addr)) + f"(?:{addr.lower()[10:]})?"
         self._extra_keys[pex(to_canonical_address(addr))] = addr.lower()
         self._extra_keys[addr[2:].lower()] = addr.lower()
     except ValueError:
         rxp = addr
     return rxp
Пример #2
0
def shortened_artifacts_storage(test_node) -> Optional[str]:
    """Return a pathname based on the test details.

    Some platforms have a limit to the length of a file path. This function
    will compute a path name based on the test details, and if necessary trim
    it down to fit 300 characters.
    """
    artifacts_dir = get_artifacts_storage()

    if artifacts_dir is None:
        return None

    path = os.path.join(artifacts_dir, test_node.name)

    # Paths longer than 286 will be reject on CircleCI
    if len(path) >= 286:
        original_name = test_node.originalname
        shortened_args = pex(test_node.name.encode("utf8"))
        path = os.path.join(artifacts_dir, f"{original_name}-{shortened_args}")

    msg = (
        "Trimming the tests arguments didn't result in a path short enough, the "
        "base_dir has to be trimmed.")
    assert len(path) < 286, msg

    return path
Пример #3
0
def transform_records(
        log_records: Iterable[Optional[Record]],
        replacements: Dict[str, Any]) -> Generator[Record, None, None]:
    def replace(value: Any) -> Any:
        # Use `type(value)()` construction to preserve exact (sub-)type
        if isinstance(value, tuple) and hasattr(value, "_fields"):
            # namedtuples have a different signature, *sigh*
            return type(value)(*[replace(inner) for inner in value])
        if isinstance(value, (list, tuple)):
            return type(value)(replace(inner) for inner in value)
        elif isinstance(value, dict):
            return {replace(k): replace(v) for k, v in value.items()}
        str_value = str(value).casefold()
        if isinstance(value, str):
            keys_in_value = [
                key for key in replacement_keys if key in str_value
            ]
            for key in keys_in_value:
                try:
                    repl_start = str_value.index(key)
                except ValueError:
                    # Value no longer in string due to replacement
                    continue
                # We use this awkward replacement code since matching is done on a lowercased
                # version of the string but we want to keep the original case in the output
                value = f"{value[:repl_start]}{replacements[key]}{value[repl_start + len(key):]}"
                str_value = value.casefold()
        return replacements.get(str_value, value)

    replacements = {str(k).casefold(): v for k, v in replacements.items()}
    for k, v in copy(replacements).items():
        # Special handling for `pex()`ed and repr'd binary eth addresses
        if isinstance(k, str) and k.startswith("0x") and is_address(k):
            bytes_address = to_canonical_address(k)
            replacements[pex(bytes_address)] = v
            replacements[repr(bytes_address).casefold()] = v
    replacement_keys = replacements.keys()
    for record in log_records:
        yield replace(record)