Repository navigation
feat: update data contract fields to use nested nouns and verbs (#714) - #715
Conversation
…be-org#714) - Update data contracts in assets with new nouns and verbs structure from Scribe-Data - Update DataContract data classes to support nouns, number pairs, and verbs - Update GenderDataManager, PluralFormsManager, ConjugateDataManager, KeyboardDataHandler, and ConjugationSelectionScreen - Update existing plural forms test and add ContractDataLoaderTest - Update CHANGELOG.md
| @@ -1,103 +1,109 @@ | |||
| # Database column mappings that are read by Scribe applications to structure how data is displayed to the user. | |||
| # Includes interface titles and the order that values should be presented (chronological or alphabetical). | |||
| # Contracts are also how Scribe-Data generates queries. All data type end values are query lexeme forms. | |||
There was a problem hiding this comment.
Thanks for the PR, @prince-0408: One thing is that ideally we'd be able to have this work without the contracts in the repo as they should be being sent by Scribe-Server with the data. Could we remove these files and write it so that it works with the contracts that are being sent by the server?
CC @DeleMike, @angrezichatterbox and @Roniscend for this point :)
There was a problem hiding this comment.
So let's remove all contracts in data-contracts and just have this directory saved with the .gitkeep that's in there. We can then verify that new contracts from the server are always being used 😊
Note @Roniscend that your work on the conjugate verb UI depends on this. We can try to bring this in via reviews in the coming days!
There was a problem hiding this comment.
Thank you, @andrewtavis! It makes perfect sense to make the APK independent of bundled contracts and load them on the fly from the server.
The following changes have been committed to resolve the issue:
- Removed all 8 contract YAML files from
app/src/main/assets/data-contracts/except for the.gitkeep. - Modified
ContractDataLoaderto check for and load the contract files from local application storage (filesDir/data-contracts/) falling back to assets. - Added methods
saveContractandparseContracttoContractDataLoaderto save contracts downloaded from the server. - Modified unit tests of
ContractDataLoaderto check the contract downloading and saving from the local storage.
@DeleMike @andrewtavis - For the wiring of the downloading of the contract, please let me know the following:
- Does the contract file come inside the response of the
GET /api/v1/data/{lang}request? - Or does the client need to make a separate
GET /api/v1/contracts?lang={lang}request when downloading language packs?
Based on your answer, it will not be a problem to wire the saving functionality to DataDownloadViewModel.
…undled assets (scribe-org#714) - Remove bundled YAML contracts from assets/data-contracts preserving .gitkeep - Update ContractDataLoader to load from local app storage with assets fallback - Add saveContract helper in ContractDataLoader to persist downloaded contracts - Update ContractDataLoaderTest and CHANGELOG.md
| Log.d("ContractDataLoader", "Attempting to load contract: $contractName") | ||
| Log.d(TAG, "Attempting to load contract: $contractName") | ||
|
|
||
| val localFile = File(File(context.filesDir, CONTRACTS_DIR), contractName) |
There was a problem hiding this comment.
@prince-0408 Connect the contract download to the app or keep the bundled contracts until thats done. Right now nothing saves contracts, so after merge nobody will have one and the Conjugate screen and keyboard features will stop working.
CC @andrewtavis you can give more clarity on this
There was a problem hiding this comment.
Thanks @Roniscend! Yes we should be connecting the contract download to the apps in this PR. This means that we won't have contracts until we get them from Scribe-Server, but also we'll know that things are working with the contracts we're getting from the server rather than maybe working with the ones we have saved to the repo and then things break if we switch to the ones from the server.
Appreciate the point here!
|
Checking in here with @angrezichatterbox right now, who confirmed that the contracts are not being saved. Let's plan on getting this done today or tomorrow at the latest, and then we can move on to the following two issues:
|
|
Quick note that I've updated the commit message to also close #598 when this is merged, as @angrezichatterbox and I agreed that we need to verify that all verbs are working before this is brought in :) |
|
@prince-0408, do let us know what your availability is to finalize this PR, as it'd be great if we could finish it tonight or tomorrow. @angrezichatterbox has offered to finish it up, in case you're a bit busy (no stress, if so!) 😊 |
|
@angrezichatterbox, FYI @prince-0408 is working on this today, so we should be good for a review soon and then we can move on to other issues 😊 |
c820d7e to
9c57c45
Compare
|
@DeleMike, can you let everyone here know when the changes from scribe-org/Scribe-Server#114 are live so that we can look into finalizing this? CC @angrezichatterbox, @prince-0408 and @Roniscend 👋 |
|
Writing in from my work account quickly. FYI @DeleMike, @angrezichatterbox, @Roniscend and @prince-0408: There's currently a security incident with PHP that is affecting WMF services. See: https://wikitech.wikimedia.org/wiki/Incidents/2026-10-21_PHP_security_update/Community. Scribe-Server is thus down, with the quote from the link that relates to this being:
Let's follow this and see when we can get this up and running! |
|
Thanks @andrewtavis for the update! This is sad. I was looking forward to updating the live server today, but I will be watching, as stated on their updates page, that things might be up by 14:00 UTC. Let's be hopeful. |
|
Note that what we're hearing is that Toolforge will be down for a bit. I assume/hope that it will be up and running by the end of the week. |
…ribe-org#714) - Add getContract endpoint in ApiService for Scribe-Server /contracts route - Add downloadAndSaveContract and hasContract helpers in ContractDataLoader - Connect contract download to DataDownloadViewModel and ConjugateDataDownloadViewModel - Add on-demand contract download fallback in ConjugationSelectionScreen - Support JSON contracts and add unit tests in ContractDataLoaderTest - Update CHANGELOG.md
- Add kotlinx-serialization-json dependency to app/build.gradle.kts - Refine exception handling in ContractDataLoader for specific parsing and network exceptions - Fix ktlint formatting issues in ApiService, ConjugateDataDownloadViewModel, and tests
|
Quick note all that there's a hope that parts of Toolforge will be up and running again in the next 24 hours. This isn't to say that we'll be able to get the server back on line, but progress is being made :) |
|
Scribe-Server is back up and running after some amazing work by @DeleMike! @Roniscend and @angrezichatterbox, would you two have a moment to check this out? |
|
Quick note on the usability of the changes here :) It looks like this PR so far solves #714, but I'm not able to get conjugations for valid verbs, meaning so far #598 isn't finalized. I think it would be great if we could get to that before bringing this in! 😊 CC @angrezichatterbox, as you'd said you'd looked into potential fixes 👋 |
| val extension = if (isJson) "json" else "yaml" | ||
| val file = File(dir, "$lang.$extension") | ||
| return try { | ||
| file.writeText(yamlContent) |
There was a problem hiding this comment.
Parse check the content before writeText, and write to a temp file then rename, so a bad 200 response can’t overwrite a working contract , reject column names that fail SqlIdentifier.isValid in the same check, since they now come from the network and reach sql
| dbHelper.syncDatabase(response) | ||
|
|
||
| val contractLoader = ContractDataLoader(getApplication()) | ||
| contractLoader.downloadAndSaveContract(langCode) |
There was a problem hiding this comment.
The Boolean result is ignored, so a failed contract download still shows success and saves the timestamp. Existing users also never get a contract until they tap download, so please handle the failure and add a one-time backfill
| dbHelper.syncConjugateDatabase(response) | ||
|
|
||
| val contractLoader = ContractDataLoader(getApplication()) | ||
| contractLoader.downloadAndSaveContract(langCode) |
There was a problem hiding this comment.
Again the result of downloadAndSaveContract is ignored, so a failed download still reports success. Handle the false case here too
…oad failures (scribe-org#714) - Add SqlIdentifier utility to validate column names and prevent SQL injection - Parse-check and SQL-validate contract before writing, and use temporary file with atomic rename in ContractDataLoader - Handle contract download failures in DataDownloadViewModel and ConjugateDataDownloadViewModel to prevent false success and timestamps - Add backfillMissingContracts in download view models for existing users with downloaded databases - Add unit tests for SqlIdentifier, atomic save, and invalid contract rejection
…date validation in ContractDataLoader
|
@prince-0408 Did some quick changes here so that we could finalise the PR a bit quicker. Really thanks for your help. @andrewtavis this PR is ready for review. |
Thanks @angrezichatterbox for pushing those final touches for complex verb forms! Everything looks good on my end as well, and all requested changes are in place. Looking forward to your review @andrewtavis! |
andrewtavis
left a comment
There was a problem hiding this comment.
praise: All's looking and working great well here, @prince-0408! Thanks for getting this done, and thanks also @Roniscend and @angrezichatterbox for the detailed reviews/improvements! 🚀 Really getting close! 😊
Contributor checklist
./gradlew lintKotlin detekt testcommand as directed in the testing section of the contributing guideDescription
In upstream Scribe-Data (PRs #717 and #721), data contracts were restructured to group linguistic columns under
nounsandverbstop-level keys to allow query generation.This PR updates
Scribe-Androidto align with the new contract specification:Updated Asset Data Contracts (
app/src/main/assets/data-contracts/):de.yaml,en.yaml,es.yaml,fr.yaml,it.yaml,pt.yaml,ru.yaml,sv.yaml) with upstream Scribe-Data.numbersandgendersare now nested undernouns, andconjugationsis nested underverbs.numbersmaps indices toNumberPair(singular, plural).Model Layer (
DataContract.kt):@Serializable data class Nouns(val genders: Genders, val numbers: Map<Int, NumberPair>).@Serializable data class NumberPair(val singular: String, val plural: String).@Serializable data class Verbs(val conjugations: Map<Int, TenseGroup>).DataContractto containnouns,verbs, andtranslations.Consumers & Managers:
GenderDataManager: Updated noun column name and gender lookup paths tocontract.nouns.numbers.values.firstOrNull()?.singularandcontract.nouns.genders.*.PluralFormsManager: UpdatedgetAllPluralFormsandfindPluralOfWordto read fromcontract.nouns.numbers.ConjugateDataManager: Updated conjugation lookups and label extraction toyamlData?.verbs?.conjugations.KeyboardDataHandler: UpdatednumbersColumnsresolution to flat-mapit.singularandit.pluralfromdataContract?.nouns?.numbers?.values.ConjugationSelectionScreen: Updated conjugation grouping to iterate overcontract.verbs.conjugations.values.Testing & Documentation:
PluralFormsManagerTest.ktto match the newNounsandNumberPairstructure.ContractDataLoaderTest.ktunit test suite covering valid YAML parsing with nestednounsandverbs, file-not-found handling, malformed YAML fallback, and verifying that all 8 language contracts in assets parse successfully.CHANGELOG.mdunder### 🗃️ Data.How Was This Tested
./gradlew formatKotlinto ensure ktlint formatting../gradlew lintKotlin detekt testpassing all 143 Gradle tasks across debug and release flavors with 0 errors.Related issue