I have an app (let’s call it CommonComponents) that houses a lot of custom components I use across many apps. CommonComponents has one component that manages user authentication, so CommonComponents imports anvil.users somewhere.
I have a new app I’m writing that depends on a different element of CommonComponents and its own login_with_form() functionality. The issue is that when it comes to this standalone login_with_form(), my app is not using anvil.users.login_with_form(), but rather CommonComponents.anvil.users.login_with_form(). It works for a straight forward login, but when it comes to error handling, all of the wonderful builtin handling that login_with_form() does is broken because the exceptions raised are coming from the dependency import (e.g. CommonComponents.anvil.users.EmailNotAuthenticated).
Any ideas on how to work around this? I know I could just manually handle each exception I can think of given that it comes from the dependency, but that feels very fragile in the long run I think.
I have a new app I’m writing that depends on a different element of CommonComponents and its own login_with_form() functionality. The issue is that when it comes to this standalone login_with_form(), my app is not using anvil.users.login_with_form(), but rather CommonComponents.anvil.users.login_with_form().
If the child app has its own login_with_form functionality, why is it using CommonComponents.login_with_form() and not importing login_with_form itself?
I don’t think I precisely understand the problem yet, but the solution may be to use the custom user flow library:
It uses the slightly-lower-level user management functions such as login_with_email to build a signup/login system out of Anvil components so you can modify it however you like.
Below is a longer explanation, but in short, I needed a component shared across all of my apps that manages user login/logout, so I made a custom component to be placed in the app bar that has a ‘Log Out’ button, ‘User Settings’ button, etc using the standard anvil.users user management tools. In this particular case, it appears that a usage of anvil.users in an app dependent on this ‘shared components’ app imports the module from the dependency app rather than from Anvil itself.
The longer explanation:
So I have App A, which has a custom component in it that utilizes anvil.users as an import. From anvil.users, the login_with_form() method is used in the custom component.
I use App A as a dependency in App B, and from App A I use the login custom component I created. The login flow works wonderfully just as if I called anvil.users.login_with_form() from inside App B with no dependency at all.
Now, if I use App A in another app (App C) as a dependency, but I import anvil.users in an App C module and call anvil.users.login_with_form(), everything works fine until an exception is thrown, such as EmailNotConfirmed or AuthenticationFailed. If I print the class using the code below:
# In an App C form
import anvil.users
try:
anvil.users.login_with_form()
except Exception as e:
print(type(e))
raise e
The string that is printed is <class 'App_A.anvil.users.AuthenticationFailed'>, so any except statement built into the standard login_with_form() method designed to catch anvil.users.AuthenticationFailed won’t catch this exception. See below for the output from the code above where I mistyped my password.
I hope this explanation helps to clarify what’s going on. Thanks for your help.