Rewrite the fast run mode with scoped SPARQL queries - #333
Merged
Conversation
LeMyst
force-pushed
the
new-fastrun
branch
2 times, most recently
from
May 13, 2022 17:49
f385ea5 to
2d58257
Compare
LeMyst
force-pushed
the
new-fastrun
branch
6 times, most recently
from
May 28, 2022 13:10
572355a to
e4f3711
Compare
Closed
4 tasks
LeMyst
force-pushed
the
new-fastrun
branch
3 times, most recently
from
May 30, 2022 20:57
d9e6e67 to
aeca219
Compare
LeMyst
force-pushed
the
new-fastrun
branch
6 times, most recently
from
May 8, 2023 10:39
2f17582 to
63349a6
Compare
LeMyst
force-pushed
the
new-fastrun
branch
3 times, most recently
from
January 2, 2024 21:46
fa07a05 to
d91a485
Compare
LeMyst
force-pushed
the
new-fastrun
branch
2 times, most recently
from
January 8, 2024 11:45
3ae0a5a to
7c3671b
Compare
LeMyst
force-pushed
the
new-fastrun
branch
2 times, most recently
from
December 19, 2024 11:03
cf48aba to
3b00b3b
Compare
LeMyst
force-pushed
the
new-fastrun
branch
2 times, most recently
from
December 26, 2024 20:59
5816349 to
041153e
Compare
LeMyst
marked this pull request as ready for review
July 8, 2026 19:55
Features: - Restrict write_required() to the entity being edited: baseentity now passes entity_filter=self.id, so data existing on another entity no longer inhibits a required write - Support action_if_exists in write_required(); FORCE_APPEND always reports a write as required - Port the language data checking (labels, descriptions, aliases) from the old implementation: init_language_data(), get_language_data() and check_language_data(), backed by the shared base filter - Implement the case insensitive mode: string values are compared casefolded, the SPARQL data is keyed casefolded at load time - Add a clear() method and a module docstring Fixes: - write_required() crashed with an IndexError when no claim matched the property filter; it now reports a write as required - The deep comparison returned early on the first mismatching statement: an entity holding duplicate statements (one matching, one not) was wrongly reported as requiring a write. The comparison now looks for at least one entity holding a matching statement for every claim - A load restricted to a value or to qualifiers (cache disabled) was reused as a complete cache, poisoning later comparisons; partial loads are no longer marked as complete - _load_qualifiers()/_load_references() crashed when building datatypes: the full property URI was passed as prop_nr; it is now reduced to the bare property ID - _load_references() duplicated references spanning two result pages - A base filter mixing a valueless property and a property path crashed in the base filter string generation - Datatypes without from_sparql_value() support and unparseable values no longer crash the load; they are skipped with a warning and the statements are reported as requiring a write - Lazily loaded qualifiers, references and ranks are memoized per statement, honoring the cache flag Tests: rebuild test/test_wbi_fastrun.py on the offline MockWikibase infrastructure with a per-query-type SPARQL dispatcher (45 tests). Docs: rewrite the fast run README section around the actual API (base filter forms, write_required() options, language data checking, limitations) and remove the outdated WikidataIntegrator-era example. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The simple value of a quantity statement does not carry the unit: two amounts only differing by their unit were considered equal and a required write could be skipped. load_statements() now loads the unit from the value node (OPTIONAL, so only quantities bind it) and the normalized unit becomes part of the comparison key. The unit is normalized to the format of the JSON representation: the RDF export of any Wikibase instance represents a unitless quantity with the Wikidata Q199 entity, which maps back to '1', and the other units are reduced to their bare entity ID. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Guard the re.search() results before reading the match groups - Import ItemEntity instead of a string annotation Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Port the idea behind the generic parse_sparql_value() of the old fastrun implementation (PR #1001) to the from_sparql_value() mechanism: give BaseDataType a working generic implementation for the data types whose RDF representation is the literal value itself, instead of a stub returning None. A generic implementation is not enough for the data types backed by a URI: storing the raw URI would never match the value held by a local claim. Implement from_sparql_value() for each of them, extracting the value the local claim holds: - Property, Lexeme, Form and Sense: the entity ID - GeoShape and TabularData: the Commons page title, percent-decoded - CommonsMedia: the file name, percent-decoded Before this change, Property, Lexeme, Form, Sense, GeoShape and TabularData were skipped with a warning and their statements were always reported as requiring a write, a limitation the README documented. CommonsMedia was worse: it inherited the URL implementation, silently stored the whole Commons URL, and could never match a local claim without even a warning. Every reachable datatype is now compared. Only EntitySchema is left out, since it has no PTYPE mapping to the Wikibase ontology and is therefore never resolved from the SPARQL property type. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rewrite of the fast run mode: the mechanism that lets a synchronisation bot skip the entities that are already up to date, without loading each of them through the MediaWiki API.
This PR replaces the previous implementation rather than patching it. #1001 was the alternative proposal, patching the existing architecture in place; it has been closed in favour of this one, and the one thing it still had over this branch (datatype coverage) has been ported here.
Why a rewrite
The previous implementation loaded the whole data corpus with a single paginated SPARQL query per property, pulling statements, qualifiers, references and ranks in one go. That query is the scaling wall: on a benchmark of only 95 entities it repeatedly hit consecutive WDQS 504 timeouts, and at the scale of a large corpus it simply cannot run. Once it succeeds the comparison is very fast, but a cold load that cannot complete is not a usable trade-off.
This implementation scopes its queries instead: the statements of a property are loaded for the corpus, and the qualifiers, references and ranks are loaded lazily, per statement, only when a deep comparison is actually needed. Each query stays small enough to complete.
What it does
entity.write_required(base_filter=...)returnsFalseonly when at least one entity already holds every compared claim with the same value, and the same qualifiers, references and rank depending on the options. When the entity ID is known (the entity was loaded withwbi.item.get()), the comparison is automatically restricted to that entity, so a bot editing a known entity no longer needs a unique identifying value in its data.The base filter defines the corpus and accepts three forms: a property with a value, a property with any value, and a property path given as a list of two datatypes.
The README section Examples (in "fast run" mode) documents the whole API, with a full bot example, the options, the language-data checking and the measured performance figures.
Breaking changes
The fastrun API is not backwards compatible. Anything using
wbi_fastrundirectly needs updating:FastRunContainer.get_items()becomesget_entities().FastRunContainer.__init__()now takesbase_filteras its first, mandatory argument;base_data_typebecomes optional.use_refsbecomesuse_references, joined byuse_qualifiers(defaultTrue),use_rankandcache.FastRunContainer.write_required()gainsentity_filterandproperty_filterand dropscqid.BaseEntity.write_required()now requiresbase_filterinstead of defaulting toNone.PTYPEclass attribute (their URI in the Wikibase ontology) and afrom_sparql_value()method taking the SPARQL binding dict. It replacesparse_sparql_value(), which fastrun no longer calls.This needs a changelog entry and a version note.
Datatype coverage
BaseDataType.from_sparql_value()was a stub returningNone, so any datatype not implementing it was skipped with a warning and its statements were always reported as requiring a write. The last commit gives it a working generic implementation for the data types whose RDF representation is the literal value itself, plus URI-specific implementations that extract the value a local claim actually holds:CommonsMedia was the worst case, and a silent one: it inherited the URL implementation, stored the whole Commons URL and could therefore never match a local claim, without even emitting the warning the other data types produce.
Every reachable datatype is now compared. Only EntitySchema is left out, since it has no
PTYPEand is never resolved from the SPARQL property type.Known limitations
Documented in the README:
Tests
253 tests pass, all offline: the 48 fastrun tests run against the
MockWikibaseemulation with a per-query-type SPARQL dispatcher, so no network access is involved. mypy, isort, codespell and flynt are clean.Rebased on master.