Here’s the resolver with your placeholders “applied” as both the static seed and the dynamic injection. Drop this into your codebase:
# directory_market_resolver.py
from typing import List, Callable, Optional, Tuple
from collections import Counter
class DirectoryMarketResolver:
def __init__(
self,
static_addresses: List[str],
dist_fn: Callable[[str, str], int],
max_dist: int = 12
):
# 1) Seed your resolver with the original addresses exactly once
self._static = static_addresses.copy()
# 2) Hold any runtime-injected addresses here
self._dynamic: List[str] = []
self._inited_dynamic = False
self._dist_fn = dist_fn
self._max_dist = max_dist
# 4) History of all successful resolves
# stored as (raw_input, matched_address, distance)
self.history: List[Tuple[str, str, int]] = []
def init_dynamic(self, new_addresses: List[str]):
"""
Inject dynamic addresses exactly once. Further calls do nothing.
"""
if not self._inited_dynamic:
self._dynamic.extend(new_addresses)
self._inited_dynamic = True
def _candidates(self) -> List[str]:
# 3) Always match against static + dynamic union
return self._static + self._dynamic
def resolve(self, raw_address: str) -> Optional[str]:
"""
Find the closest match within max_dist.
Record the original raw_address in history on success.
"""
best, best_d = None, self._max_dist + 1
for cand in self._candidates():
d = self._dist_fn(raw_address, cand)
if d < best_d:
best, best_d = cand, d
if best_d <= 1: # early-exit on near-perfect
break
if best and best_d <= self._max_dist:
self.history.append((raw_address, best, best_d))
return best
return None
def weighted_resolve(self, raw_address: str, alpha: float = 0.7) -> Optional[str]:
"""
Bias resolution towards frequently matched addresses.
score = alpha * norm_sim + (1-alpha) * norm_freq
"""
freq = Counter(addr for _, addr, _ in self.history)
scored: List[Tuple[float, str]] = []
for cand in self._candidates():
d = self._dist_fn(raw_address, cand)
if d > self._max_dist:
continue
# normalize edit-distance → similarity [0..1]
sim = max(0.0, (self._max_dist - d) / self._max_dist)
# normalize frequency [0..1], cap after 10 hits
hist = min(1.0, freq[cand] / 10.0)
score = alpha * sim + (1 - alpha) * hist
scored.append((score, cand))
return max(scored)[1] if scored else None
if __name__ == "__main__":
import Levenshtein
# — Your STATIC seed (never overwritten) —
STATIC = [
"DirectoryMarket/(Static seed in __init__ (never overwritten))"
]
# — Your DYNAMIC injection, applied once via init_dynamic() —
DYNAMIC = [
"DirectoryMarket/(Dynamic list injected once via init_dynamic)"
]
resolver = DirectoryMarketResolver(
static_addresses=STATIC,
dist_fn=Levenshtein.distance,
max_dist=12
)
# Inject dynamic addresses exactly once
resolver.init_dynamic(DYNAMIC)
# Raw input placeholder set to your static seed
RAW_INPUT_ADDRESS = "DirectoryMarket/(Static seed in __init__ (never overwritten))"
# 3) resolve() matches against both lists and logs history
fixed = resolver.resolve(RAW_INPUT_ADDRESS)
print("Resolved →", fixed or "❌ no match")
# 4) weighted_resolve() biases by past history
smart = resolver.weighted_resolve(RAW_INPUT_ADDRESS)
print("Weighted →", smart or "❌ no match")
Here’s the resolver with your placeholders “applied” as both the static seed and the dynamic injection. Drop this into your codebase: