igorbenav / FastAPI-boilerplate

An extendable async API using FastAPI, Pydantic V2, SQLAlchemy 2.0, PostgreSQL and Redis.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Enhance import packages system

YousefAldabbas opened this issue · comments

condensing import statements for brevity:

from app.crud import crud_users, crud_tiers, crud_rate_limits

instead of

from app.crud.crud_users import crud_users
from app.crud.crud_tier import crud_tiers
from app.crud.crud_rate_limit import crud_rate_limits

This makes imports more concise and groups related items together

Hey, @YousefAldabbas, thanks again for the issue!

This is actually more of a coding style issue, since this change would indeed make the import statements more concise, but would make the code in general more verbose:

Current style:

# ------- verbose imports -------
from app.crud.crud_users import crud_users
from app.crud.crud_tier import crud_tiers
from app.crud.crud_rate_limit import crud_rate_limits

# ------- more concise in usage -------
db_user = crud_users.get(...)
db_tiers = crud_tiers.get_multi(...)
...

Proposed style:

# ------- more concise imports -------
from app.crud import crud_users, crud_tiers, crud_rate_limits

# ------- more verbose in usage -------
db_user = crud_users.crud_users.get(...)
db_tiers = crud_tier.crud_tiers.get_multi(...)
...

To be honest, I'm not completely sold on any of the options. The advantage of the proposed style would be knowing exactly where the crud_ class comes from, but since it always comes from a crud_ file, I don't think it would do any good.

A third possibility would be:
Creating crud_all.py:

# app/crud/crud_all.py

from crud_users import crud_users
from crud_tier import crud_tiers
...

Importing what's necessary directly from crud_all:

# ------- concise imports -------
from app.crud.crud_all import crud_users, crud_tiers, crud_rate_limits

# ------- concise in usage -------
db_user = crud_users.get(...)
db_tiers = crud_tiers.get_multi(...)

Pros:

  • Would be cleaner for multiple crud_<object> in the same file (might be worth it if it happens often)
  • Might make it easier to refactor (changing stuff in crud_all instead of doing it for every crud_<objects>)

Cons:

  • It adds another file to maintain (you'll have to import the new crud_<object> to this file every time you create one)
  • Might cause circular imports, specially for beginners using
  • Reduces clarity: you do not know exactly where the import is coming from (maybe this one isn't as strong since - again - the original module and the class have the same name)

I don't think the added complexity is necessary for smaller projects, but maybe it is for larger projects. I'll leave this issue open for some time so you (or someone else) can keep this discussion going until I'm actually certain what to do.

thanks for your patient,
yeah i totally agree its more coding style, you can close this issue if you see its not reasonable or doesn't consider as enhancement
you could use all in the __init__.py it will become
from this

# ------- more concise imports -------
from app.crud import crud_users, crud_tiers, crud_rate_limits

# ------- more verbose in usage -------
db_user = crud_users.crud_users.get(...)
db_tiers = crud_tier.crud_tiers.get_multi(...)

to

from app.crud import crud_users, crud_tiers, crud_rate_limits

# ------- more verbose in usage -------
db_user = crud_users.get(...)
db_tiers = crud_tiers.get_multi(...)

__inti__.py file will look like

from .crud_users import crud_users
...
__all__ = ("crud_users", ...)

True, didn't think about it, but is definitely better than creating a crud_all script.

I'll convert it to a discussion because it may be useful for people who choose this style, but I think it's better leaving the decision to who's using the boilerplate.