Problems importing modules

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
2 Likes

I am at the third day working on the imports, and I found (one of the reasons) why the imports in a server module work in Anvil and not in PyCharm.

Python and PyCharm seem to be happy after modifying the __init__.py like this:

# from this:
__path__ = [__path__[0] + "/server_code", __path__[0] + "/client_code"]

# to this:
__path__ = [__path__[0] + "/server_code", __path__[0] + "/client_code", __path__[0]]

Can I safely apply this change too all my apps?
Or do I risk to break something?

Sometimes Anvil changes the folder structure and applies automatic upgrades to the apps. Would this change break the apps at the next automatic change?

EDIT

I don’t have an answer yet, and, with the assumption that this change is not dangerous, I describe here how I’m setting up a few new apps now. This new setup does include this change.

1 Like