Skip to content

Comments

Stricter type annotations#120

Draft
pappnu wants to merge 94 commits intoInvestigamer:mainfrom
pappnu:dev
Draft

Stricter type annotations#120
pappnu wants to merge 94 commits intoInvestigamer:mainfrom
pappnu:dev

Conversation

@pappnu
Copy link
Contributor

@pappnu pappnu commented Aug 26, 2025

Adds stricter type annotations to most of the codebase excluding GUI code, as Kivy lacks proper type annotation support. The API data is mostly typed as dict[str, Any], so that still needs further work down the line, though the template classes access the data through the layout classes, which have better type annotations, so the lackluster API types aren't that big of an annoyance at this point. Since in many places it wasn't enough to just add type annotations, many smallish functional changes had to be done in various parts of the code.

I have included all of my previous PRs (#95, #96, #97, #100, #102, #103, #104, #107, #109, #110, #113, #114, #116, #117 and #118) to this PR because maintaining them separately would require a significant amount of extra work, as the type annotations touch so many places of the code. If you see value in this stricter typing, it would be great if these changes could be integrated before making other significant changes in the main branch, as mering new non-annotated changes to this can end up being laborious.

29.8.2025

Asynchronized the startup checks, which allows the user to interact with the GUI far sooner at startup than before. This also means that the startup won't hang while retrying/waiting API requests anymore if, e.g., Hexproof API responds slowly (which happened sometimes when you were improving your setup). Proxyshop used to wait Photoshop to start synchronously in __init__.py and working around this required changing the way the Photoshop Application instance is accessed, which is a breaking change.

31.8.2025

According to this, tomasbasham/ratelimit is not a reliable rate limiting library. It also lacks type annotations, so I switched to limits, which remedies the aforementioned shortcomings.

13.9.2025

Added the pawprint symbol from CardConjurer to the Proxyglyph font. I'm not sure what logic has been used to determine the character to symbol mapping, so I just set the pawprint to some empty slot.

29.9.2025

Added validation to Scryfall data using Pydantic models. Non-planar template test render cases seem to pass the validation, though it might prove to be too strict in the future when the fields receive new possible values. Also added a setting to use the printed texts even with English cards.

17.2.2026

I replaced the GUI with a PySide6 based one. My main motivator for switching the GUI library was that Kivy doesn't support type annotations and it doesn't seem likely that it would gain support for them any time soon. The new GUI is quite close to the old one in regards to the main workflow, but exposes more information. Noteworthy additions include:

  • The settings can be changed and new renders can be queued even when a render operation is running in the background.
  • The new GUI can process image and JSON file pairs, e.g. my_custom_card (artist).png and my_custom_card.json, where the JSON will be used as card data instead of fetching data from Scryfall.
  • The app remembers its position, size and template selections when restarted.
  • Template tests can be initiated from the regular GUI, so there's no more need to set an ENV variable in order to enter a separate testing view.

Additionally Pydantic is used even more widely to validate the various data files that the app uses.

For now the app's command line commands (./src/commands) are broken, but I'll hopefully get around to fixing them at some point.

Breaking Changes

Below are the breaking changes that I'm aware of and which are somewhat likely to cause issues. Generally speaking, if a plugin's template doesn't do a lot of overriding or other trickery it should still work as expected with these changes, excluding the breaking manifest format validation change.

  • AppConfig.get_setting doesn't default to returning a bool anymore, which makes it more straightforward to overload the function with more specificly typed variants.
  • There's a lot more checks for layer values being not None so if some plugin's template relied on catching type errors they won't work as expected anymore. This matters only for plugins, as I'm not aware of such code in Proxyshop's codebase.
  • There's no more multiple differently cased names for the same Action related functions, e.g., there's no executeaction anymore, instead the "standard" executeAction should be used.
  • RGB and CMYK colors are now expected to be tuples instead of lists.
  • BorderlessVectorTemplate now has pinlines_shapes and twins_shapes properties to denote that they return multiple layers instead of just one. Previously pinlines_shape and twins_shape were used for that.
  • BaseTemplate.run_tasks no longer takes args and kwargs as typing them genericly in the way that Proxyshop uses them is not possible or very tricky AFAIK. Luckily passing them wasn't necessary in terms of functionality, as wrapper functions can easily be used for mostly the same effect.
  • Some name changes/clarifications for (utility) functions that were not widely used.
  • The global Photoshop Application instance (from src import APP) has to be accessed via APP.instance instead of via APP as before. This was done in order to allow asynchronously instantiating the object in another thread.
  • Only the most specific plugin manifest format is supported anymore, as adding multiple formats makes the code more complicated and in my opinion doesn't bring extra value even to plugin developers since it necessitates learning multiple syntaxes that aren't ultimately that different from each other.

Tests (15.2.2026)

All the built-in templates of Proxyshop passed all render tests with the dev version of the new GUI, or at least I didn't spot any glaring issues. I also noticed the following problems within some of the templates themselves, which aren't caused by changes in this PR:

Colorshifted Template

Doesn't support "Land" color, though this is noted in the template's code as well. (try Arcane Lighthouse)

Crimson Fang Template

Doesn't have all the possible 3 color indicators. (try Optimus Prime, Autobot Leader)

Planar Template

The text can overlap with the curve at the bottom. (reproducible with the deep test case)

Planeswalker TF and the borderless variant

These lack some of the transform symbols. (try Arlinn Kord)

Transform Template

Doesn't have all the possible 3 color indicators. (try Optimus Prime, Autobot Leader)

Related PRs

I'm marking this as a draft since at least the pyproject.toml needs to be updated with proper newer versions of Omnitils and Hexproof API packages once they are out.

Please let me know what I should change in order to have this merged.

pappnu added 30 commits March 13, 2025 19:10
Expose blend mode, dither and method options for gradient overlays.
Adds a missing cached_property decorator to Saga layout check.
…lors

Generalizes the way pinline gradient definitions are constructed, which enables using an arbitrary amount of colors.
…tive

SagaLayout text processing depends on the number of leading lines, but it doesn't take into account that the first line might have been removed as a result of reminder text removal. This commit aims to fix that.
…cription

Not all Saga cards have a reminder description as the first line, which broke the existing Saga text parsing.
…is given to the text formatting class

Text fields in the PSD files usually have placeholder text in them, so in some rare situations, e.g. with Tokens, where the text should be cleared it isn't unless that specific case is separately handled in the template code. This change allows relying on the default text processing logic in such situations.
…ed repositories. Use Pydantic for validating configs
…ronment management

pydantic-settings allows validating environment variables in less verbose and more type safe manner than dynaconf

BREAKING CHANGE: None isn't interpreted as a default anymore for some of the env variables, so env variables that should use default values should not be defined at all, e.g., in the env files.
BREAKING CHANGE: Only the most specific plugin template definition format is supported by the new validator as supporting many different formats makes the code more complicated and makes it harder for plugin developers to understands the manifest file.
…more settings for manipulating the filling selection
…mpling other layers except the art layer

Remove Content fill requires the same workaround as Generate Fill for preventing, e.g., text layers being considered as part of the image to expand.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant