Skip to content

build(deps): bump nomenklatura from 4.10.0 to 4.13.2 - #1240

Open
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/pip/nomenklatura-4.13.2
Open

build(deps): bump nomenklatura from 4.10.0 to 4.13.2#1240
dependabot[bot] wants to merge 1 commit into
mainfrom
dependabot/pip/nomenklatura-4.13.2

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Aug 24, 2026

Copy link
Copy Markdown
Contributor

Bumps nomenklatura from 4.10.0 to 4.13.2.

Release notes

Sourced from nomenklatura's releases.

Nomenklatura 4.13.1

This release covers everything since 4.12.0, including the unreleased 4.12.1–4.13.0 tags. The bulk of it is a rework of blocker candidate ranking so that rare tokens drive the ordering, a lossless CSV round-trip for resolver state, and substantially faster statement loading.

Blocking

  • Blocker candidates are ranked by token rarity instead of raw term frequency (#349). Token weights are now presence-based (boost × IDF, smoothed so ubiquitous tokens keep their boost), name-part and symbol tokens are dampened by the square root of the entity's name count, and per pair and field the best shared token counts in full while additional ones earn only logarithmic credit. Previously a shared common forename scored the same as a shared distinctive company name, and every additional alias diluted the evidence of the name that actually matched: on the sanctions scope 3.5% of exact-name duplicate pairs never surfaced within a 1M-pair budget, the worst ranked at ~1M of 11.2M candidates. On the same scope every exact-name duplicate pair now ranks within the first ~21k candidates. pairs() and match_entities() share the weighting, and both orderings carry deterministic tie-breaks.
  • Candidate truncation moved into the DuckDB query: each subject's list is cut to max_candidates and floored at min_score_ratio (default 0.1) of its best candidate's score, so rows discarded in Python are no longer sorted and shipped. Subjects present in the indexed view no longer receive themselves as candidates, and mid-chunk subjects no longer received max_candidates + 1 candidates. The relative floor replaces zavod's max_bin walk, whose rounded-absolute-score binning the rarity-based scoring broke.
  • Removed match_batch chunking. Measured against a 273k-entity index with 50k subjects it produced identical candidate lists slightly slower, and DuckDB's own spilling handles constrained memory down to a 512MB limit. Tune NOMENKLATURA_DUCKDB_THREADS instead.
  • Tokenizer fixes: matchable email values are now indexed (they fell through every type branch despite the index defining a 10.0 boost for the field), the 3–30 character gate on name parts checks the string actually emitted (part.comparable, not part.form), and address-derived tokens accumulate term frequency instead of being deduplicated per entity, so a word appearing in several of an entity's addresses outweighs an incidental one.

Resolver

  • Fixed Resolver.dump() silently resurrecting reverted judgements: soft-deleted edges were written out, but the jsonl line format has no deleted_at field, so a dump/load roundtrip reinstated every judgement that had ever been reverted. Dumps are now also actually sorted by created_at.
  • dump-resolver and load-resolver gain -f/--format {jsonl,csv}, defaulting to the existing jsonl. CSV rows carry a deleted_at column, so dump-resolver -f csv --include-deleted preserves tombstones through a roundtrip — this is now the lossless way to move resolver state between databases. The flag is rejected for jsonl, which cannot represent deleted edges.
  • New nk dump-mapping command writes a two-column entity_id,canonical_id CSV for consumers that need a join table rather than the full edge history. Every known identifier gets a row, including canonicals themselves and stale intermediate canonicals absorbed by later merges, so any past reference resolves via a plain join.
  • Serialization moved onto two format-agnostic primitives: Resolver.all_edges() yields edges in chronological order (with opt-in flags for soft-deleted edges and NO_JUDGEMENT suggestions) and Resolver.load_edges() registers a stream of edges. Edge.from_dict() now tolerates csv.DictReader rows, where every value is a string and missing values arrive as "".
  • Indexed resolver.created_at and resolver.deleted_at to lighten the refresh-from-database path that runs on every decide().

Cross-referencing

  • xref patience is now measured over pairs that were actually scored, not over blocker ranks. In mature scopes, hundreds of thousands of already-decided pairs sit at the top of the blocking index ranking; each was skipped almost for free but still advanced the patience counter, so the scan gave up long before reaching any undecided candidates.
  • Removed a duplicated stop condition that hardcoded a factor of 10 instead of respecting limit_factor, and the progress log now reports the scored-pair count.

Matching

  • logic_v2 no longer literal-matches names with contradicting part tags. The early exit in name_match compared whitespace-normalized comparable strings only, so a structured query with firstName/lastName swapped (firstName=putin, lastName=vladimir) scored a 1.0 literalMatch against any "Family, Given"-form alias, even though the query's GIVEN part was being matched against the result's FAMILY part. The exit is now gated on NamePartTag.can_match per position; contradicting pairs fall through to the full symbol/alignment machinery, landing the reversed query at ~0.51. Untagged names are unaffected — "Smith, John" still literal-matches "John Smith". Fixes #247 (the literal-match half).

Performance

  • Statements are inserted via executemany instead of an inline VALUES clause. Building insert(table).values(batch) per batch made every batch a distinct statement, so SQLAlchemy recompiled a fresh multi-row VALUES clause each time — 88ms per 1500 rows against 0.04ms for the cacheable parameterised form, capping the loader at ~17k statements/s while parsing and canonicalising run at ~400k/s. Measured on 200k statements into a fully-indexed table: 9.8k → 15.2k stmt/s on PostgreSQL, 12.6k → 95k stmt/s on SQLite. Dialect dispatch is hoisted into dialect_insert, so an unsupported dialect now raises before the DELETE rather than on the first batch.

Wikidata and Wikipedia

  • Transient Wikidata API errors are retried with exponential backoff, then the item is skipped. Wikidata reports internal failures (DB lag, rate limits, connection errors) in-band as HTTP 200 with an error body, so the session's status-code retries never saw them and a single blip on one QID could abort an entire wd_peps crawl. Once the retry budget is exhausted a warning is logged and the item reads as absent for this run without being cached, so a later run refetches it. Permanent no-such-entity responses stay cached misses.
  • Fixed Wikipedia hosts for variant-language sitelinks. Wikidata site codes use underscores where the wiki subdomain uses hyphens (zh_yuewikizh-yue.wikipedia.org), producing unresolvable hosts once rigour started resolving BCP 47-style tags via their primary subtag. Site codes are now translated to hostname form, and the plain-language wiki (zhwiki) is preferred over variant wikis resolving to the same language code, so summaries come from the main edition regardless of sitelink order.
  • fetch_summary now swallows all request-level errors and returns None rather than raising. Failures are logged and not cached, so later runs retry them.

Enrichment

  • The enricher topics config option (including "all" expansion) is resolved once in BaseEnricher.__init__ and exposed as filter_topics, so callers that gate further processing on the same topics — such as zavod's topic-gated enrichment expansion — can consume the identical set instead of re-interpreting the raw config. Behavior is unchanged.

Code quality

  • Ruff lint rules moved from the pre-commit hook's hardcoded --select I into [tool.ruff.lint], so an editor, a bare ruff check and CI now agree. The selection covers rule families already clean across the package, tests and contrib; individual codes are pinned where the wider family still has open findings (notably UP031 printf-style formatting, with 46 remaining sites, which is not selected).
  • Fixed bug-prone patterns the new rules surfaced: shared class-level containers (feature lists, matcher CONFIG dicts, index BOOSTS, Textual BINDINGS) are annotated ClassVar; mutable argument defaults replaced with None sentinels; zip() strictness made explicit, with strict=True on the feature/coefficient pairings where a length mismatch would silently misattribute model weights; and blanket # type: ignore comments narrowed to the codes mypy actually reports.

Compatibility

  • WikidataAPIError has been removed. It existed only to make callers fail loudly, which the retry-then-skip behavior supersedes; consumers that started catching it after 4.12.0 should drop the handler.
  • Resolver.dump() no longer includes soft-deleted edges. Use dump-resolver -f csv --include-deleted if you were relying on them being present.

... (truncated)

Commits
  • c9c7a79 Bump version: 4.13.1 → 4.13.2
  • 856668e Merge pull request #358 from opensanctions/xref-skip-external-pairs
  • 98fb680 Mark external candidates in the dedupe comparison header
  • 8e4ebe7 Skip xref pairs where both candidates are external
  • eed08fd Bump version: 4.13.0 → 4.13.1
  • 576db79 Merge pull request #357 from opensanctions/ruff-lint-config
  • 8e4bf66 Merge pull request #356 from opensanctions/ruff-bugprone-fixes
  • e9bffc7 Merge pull request #354 from opensanctions/ruff-safe-fixes
  • d8cd4be Configure ruff lint rules in pyproject.toml
  • d137b74 Fix mutable class defaults, zip strictness and blanket type ignores
  • Additional commits viewable in compare view

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

Bumps [nomenklatura](https://github.com/opensanctions/nomenklatura) from 4.10.0 to 4.13.2.
- [Release notes](https://github.com/opensanctions/nomenklatura/releases)
- [Commits](opensanctions/nomenklatura@4.10.0...4.13.2)

---
updated-dependencies:
- dependency-name: nomenklatura
  dependency-version: 4.13.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot dependabot Bot added dependencies Pull requests that update a dependency file python Pull requests that update Python code labels Aug 24, 2026
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedpypi/​nomenklatura@​4.10.0 ⏵ 4.13.297100100100100

View full report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file python Pull requests that update Python code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants