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
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
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)