Here are a few reasons for my import
problems, followed by the question.
Invisible folders
The file structure in cloned apps is defined by Anvil, and includes the folders server_code
and client_code
that are invisible when importing by the app, but are visible by an uplink script.
Order of import
The modules are imported in alphabetical order, so when everything works in PyCharm because you start from MainModule
, it doesn’t work in Anvil because you may have a module that comes before in alphabetical order, and end up with circular imports.
Server modules
A server module of App1 can be imported by:
- another server module in the same app, while running on the Anvil server
- another server module in the same app, while running on an uplink script
- another server module in App2 that depends on App1, while running on the Anvil server
- another server module in App2 that depends on App1, while running on an uplink script
Modules
A module of App1 can be imported by:
- a client module in the same app, while the app is running
- a client module in App2 that depends on App1, while the app is running
- a server module in the same app, while running on the Anvil server
- a server module in the same app, while running on an uplink script
- a server module in App2 that depends on App1, while running on the Anvil server
- a server module in App2 that depends on App1, while running on an uplink script
Question
Is there a clean way to setup an app so it runs smoothly on the Anvil server and on all other configurations on my computer, specifically inside PyCharm, where all the apps are cloned to the same folder?
In PyCharm I can add the folders of the dependent apps to the project structure, and add server_code
and client_code
as content roots, so the problem of the invisible folders is partially solved. But this introduces a new problem: all the modules of all the server_code
folders are mushed together and there is no way to say from App1 import Module1
vs from App2 import Module1
.
I have similar setup for dozens of apps: the production apps run on the server, their http endpoints work both on the server and on an uplink script running on my computer, and I can run tests inside PyCharm.
But with every new app I always struggle to figure out how to import and to avoid circular imports.
In some simple apps I’m lucky and something like this works, but in most cases I need to figure it out by trial and error:
if anvil.server.context.type == 'uplink':
# running tests on pc - import from the manually added content
# root, because it's impossible to import from the dependency
from CacheTtl import cache_ttl
else:
# running on Anvil server - specify the name of the dependency
from KeyValueCache.CacheTtl import cache_ttl