Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support for structured scaffold in create command #970

Open
wants to merge 66 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
9828c99
feat: added simple/structured scaffolding
ashupednekar Sep 25, 2024
56e174a
chore: adding auto discover routes
ashupednekar Sep 25, 2024
03918ac
chore: added discover routes
ashupednekar Sep 25, 2024
10d3c83
chore: updated server
ashupednekar Sep 25, 2024
0baab2b
feat: finished no db scaffolding
ashupednekar Sep 25, 2024
481bed8
chore: copied over no db stuff to db
ashupednekar Sep 25, 2024
c0c5dd4
chore: added db connection pool and envs to sqlalchemy structured sca…
ashupednekar Sep 25, 2024
a4c2730
feat: added sqlalchemy and pydantic example models to scaffold
ashupednekar Sep 25, 2024
e98ce50
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 25, 2024
cdcb947
feat: added alembic migration support
ashupednekar Sep 26, 2024
6005967
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 26, 2024
095916f
Merge branch 'sparckles:main' into feat_structured_scaffold
ashupednekar Sep 26, 2024
832bd8f
feat: added alembic migration setup to sqlalchemy structured scaffold
ashupednekar Sep 26, 2024
09b9262
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 26, 2024
2a16aff
style: formatted scaffold and helper code
ashupednekar Sep 26, 2024
a4b49b1
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 26, 2024
25840fa
dep: added sqlalchemy dep to scaffolding
ashupednekar Sep 26, 2024
6f2e58c
dep: added alembic to req in scaffold
ashupednekar Sep 26, 2024
4922b1a
dep: added psycopg2 binary to dep in scaffolding
ashupednekar Sep 26, 2024
f2ae1f7
chore: updated sqlalchemy scaffold structure
ashupednekar Sep 26, 2024
c964335
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 26, 2024
4391a39
fix: updated import in models init in sqlalchemy scaffold
ashupednekar Sep 26, 2024
9d66596
chore: reverted accidental change to simple sqlalchemy scaffold
ashupednekar Sep 26, 2024
43726fb
chore: added mutator/selector abc classes to sqlalchemy structured sc…
ashupednekar Sep 26, 2024
9159a71
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 26, 2024
b5895dd
chore: updated test for create_app, added additional test
ashupednekar Sep 28, 2024
f155900
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 28, 2024
182f9cf
chore: ignoring errors in case of docker N, if devops directory doesn…
ashupednekar Sep 28, 2024
054570b
chore: udpated ruff suggestions
ashupednekar Sep 28, 2024
3a93374
Merge branch 'sparckles:main' into feat_structured_scaffold
ashupednekar Sep 28, 2024
155acd7
fix: updated subrouter initializations in scaffold
ashupednekar Oct 1, 2024
d2ddba8
chore: upadated scaffold
ashupednekar Oct 1, 2024
d282b36
chore: updated handler to include pool from a global dependency
ashupednekar Oct 1, 2024
9d7fcf0
chore: added missing arg
ashupednekar Oct 1, 2024
8a3c2ab
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 1, 2024
8ce0753
style: ruff formatting on structured directory
ashupednekar Oct 2, 2024
0a9cbb6
chore: added sample selector and used "session" in sample handler in …
ashupednekar Oct 2, 2024
42c61fc
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 2, 2024
ffe6629
feat: switched to sqlalchemy async
ashupednekar Oct 5, 2024
138e530
fix: updated handler to await async selectors appropriately
ashupednekar Oct 5, 2024
646b58b
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 5, 2024
a6c6e13
doc: updated example app docs to include scaffold type
ashupednekar Oct 8, 2024
4eeab6d
doc: updated getting started docs as per structured scaffold
ashupednekar Oct 8, 2024
72b66f0
doc: added note about endpoints in class as static methos
ashupednekar Oct 8, 2024
af42e44
chore: added example handler outside class
ashupednekar Oct 8, 2024
da66936
chore: added comments on what alembic is
ashupednekar Oct 8, 2024
2a8209e
chore: re-triggering pre-commit ci
ashupednekar Oct 8, 2024
61bac98
doc: typo fix in scaffold docs
ashupednekar Oct 8, 2024
5ffbcfd
Merge remote-tracking branch 'upstream/main' into feat_structured_sca…
ashupednekar Oct 9, 2024
785dc1d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 9, 2024
793f882
style: formatted scaffold directory with ruff
ashupednekar Oct 10, 2024
7b98147
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 10, 2024
3f014bd
style: ran isort to sort imports
ashupednekar Oct 10, 2024
d855250
Update index.mdx
ashupednekar Oct 11, 2024
5a890cb
doc: udpated example app index.md
ashupednekar Oct 11, 2024
e627b59
chore: added aiosqlite dependency and commented env
ashupednekar Oct 11, 2024
c716a84
fix: updated alembic env.py to use sync connection and sessionmaker
ashupednekar Oct 16, 2024
20e1390
fix: updated alembic env.py to refer ini file
ashupednekar Oct 16, 2024
8939695
doc: updated example app docs for migrations
ashupednekar Oct 16, 2024
1289421
chore: removed class groups on handlers in favour of straigtforward h…
ashupednekar Oct 16, 2024
0d848b5
chore: deleted readme in migrations directory in sqlalchemy scaffold
ashupednekar Oct 16, 2024
3b3a51e
chore: changed global dependency name to db_connection_pool
ashupednekar Oct 16, 2024
f348cac
chore: renamed db pool function to be more descriptive
ashupednekar Oct 16, 2024
8976522
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 16, 2024
170e496
doc: added alembic readme, dep: added psycopg dep, style: ruff on sca…
ashupednekar Oct 16, 2024
662c009
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Oct 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 146 additions & 7 deletions docs_src/src/pages/documentation/example_app/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,25 @@ Batman wanted to create a Robyn app and was about to create an `src/app.py` befo
$ python -m robyn --create
```

This, would result in the following output.
You can choose to have a simple barebones format or an structured scaffold (recommended) ike so...

```bash
$ python -m robyn --create
? Directory Path: myproject
? Need Docker? (Y/N) Y
? Please choose if you'd like the scaffold to be a simple starter kit or an opinionated structure
Simple
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's call it barebones and recommended structured

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oki

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ashupednekar , I don't see an update here

❯ Structured
```


This, would result in the following output if you choose scaffold type as `simple`

```bash
$ python3 -m robyn --create
? Directory Path: .
? Need Docker? (Y/N) Y
? Please choose if you would like the scaffold to be a barebones starter kit or a recommended structure
? Please select project type (Mongo/Postgres/Sqlalchemy/Prisma):
❯ No DB
Sqlite
Expand All @@ -40,12 +53,7 @@ $ python3 -m robyn --create
Prisma
```

and the following directory structure.


Batman was asked a set of questions to configure the application. He chose to use the default values for most of the questions.

And he was done! The Robyn CLI created a new application with the following structure.
and the following directory structure

```bash

Expand All @@ -65,3 +73,134 @@ And he was done! The Robyn CLI created a new application with the following stru
/>
</div>

If you choose to go with the structured scaffold, this is how your project will look like

> note: at the moment, only no-db and sqlalchemy are supported here, you can always plug in other integrations as you see fit
ashupednekar marked this conversation as resolved.
Show resolved Hide resolved

```bash
├── adaptors
│   ├── __init__.py
│   ├── models
│   │   ├── __init__.py
│   │   └── user.py
│   ├── mutators
│   │   └── __init__.py
│   └── selectors
│   ├── __init__.py
│   └── misc.py
├── alembic.ini
├── api
│   ├── handlers
│   │   ├── __init__.py
│   │   ├── probes.py
│   │   └── sample.py
│   └── middlewares
│   └── __init__.py
├── conf.py
├── config.env
├── devops
│   ├── Dockerfile
│   ├── Dockerfile.src
│   └── docker-compose.yaml
├── migrations
│   ├── README
│   ├── env.py
│   ├── script.py.mako
Comment on lines +105 to +108
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to read more about this

│   └── versions
│   └── __init__.py
├── requirements.txt
├── server.py
└── utils
├── __init__.py
└── db.py

12 directories, 24 files
```

Here's what each of these stand for

- server.py

This is where you instantiate your robyn server and inject global dependencies

```python
from robyn.helpers import discover_routes
from robyn import Robyn

from utils.db import get_pool
from conf import settings

app: Robyn = discover_routes("api.handlers")
Comment on lines +127 to +133
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't have a discover_routes function

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's added in helpers as part of this PR...

def discover_routes(handler_path: str = "api.handlers") -> Robyn:
    mux: Robyn = Robyn(__file__)
    package = importlib.import_module(handler_path)
    for _, module_name, _ in pkgutil.iter_modules(package.__path__, package.__name__ + "."):
        module = importlib.import_module(module_name)
        logger.info(f"member: {module}")
        mux.include_router(module.router)
    return mux

# note: if you prefer to manuall refine routes, use your build_routes function instead

app.inject_global(pool=get_pool())


if __name__ == "__main__":
app.start(host="0.0.0.0", port=settings.service_port)
```

- conf.py/config.env

Comes with initial settings you need to work with the database. The `BaseConfig` class slight enhancement on pydantic-settings's `BaseSettings` class

- Your endpoint and middleware handlers live under the `api` package.
> note: the example where the handlers are in a class as static methods is completely up to the developer preference and doesn't impact the actual routing in any way

- It also comes pre-configured with alembic for database migrations

- The database mutations and queries will be living under the `adaptors` package where you would do the following
- define your sqlalchemy and pydantic models
- define selectors for reusable query functions
- define mutators for any mutations over the model along with related functionality, usually in a transaction block

> note: by default, we include sqlalchemy async pool, you can always change it as per your requirements

Once you have set up your project like so, make sure to update the `sqlalchemy.url` field in your `alembic.ini`file to point to your DB like so...

```
sqlalchemy.url = postgresql+psycopg://consoleuser:buddy123@localhost:5432/console
```

Then, once you are done writing your sqlalchemy model classes, you can go ahead and generate your migration files like so

```bash
alembic revision --autogenerate -m initial
```
You should see an output like so

```
/home/batman/.virtualenvs/base/lib/python3.12/site-packages/pydantic/_internal/_config.py:334: UserWarning: Valid config keys have changed in V2:
* 'orm_mode' has been renamed to 'from_attributes'
warnings.warn(message, UserWarning)
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.autogenerate.compare] Detected added table 'users'
INFO [alembic.autogenerate.compare] Detected added index ''ix_users_id'' on '('id',)'
INFO [alembic.autogenerate.compare] Detected added index ''ix_users_username'' on '('username',)'
INFO [alembic.ddl.postgresql] Detected sequence named 'transactions_id_seq' as owned by integer column 'transactions(id)', assuming SERIAL and omitting
INFO [alembic.autogenerate.compare] Detected removed index 'idx_user_id' on 'transactions'
INFO [alembic.autogenerate.compare] Detected removed table 'transactions'
Generating /home/ashu/Desktop/aaa/migrations/versions/cefc632435c7_initial.py ... done
```

This will generate the migration files like so

```bash
$ tree migrations/
migrations/
├── env.py
├── README
├── script.py.mako
└── versions
├── cefc632435c7_initial.py
└── __init__.py

2 directories, 5 files
```

Now you can apply the migrations with `alembic upgrade head`

Batman was asked a set of questions to configure the application. He chose to use the default values for most of the questions.

And he was done! The Robyn CLI created a new application with the following structure.
18 changes: 17 additions & 1 deletion integration_tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,27 @@


# Unit tests
def test_create_robyn_app():
def test_create_robyn_app_simple():
with patch("robyn.cli.prompt") as mock_prompt:
mock_prompt.return_value = {
"directory": "test_dir",
"docker": "N",
"scaffold_type": "simple",
"project_type": "no-db",
}
with patch("robyn.cli.os.makedirs") as mock_makedirs:
with patch("robyn.cli.shutil.copytree") as mock_copytree, patch("robyn.os.remove") as _mock_remove:
Comment on lines +15 to +16
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not move this to line 8 ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didn't follow...

added additional key in mock return value scaffold_type
and added two tests for the two possible values

create_robyn_app()
mock_makedirs.assert_called_once()
mock_copytree.assert_called_once()


def test_create_robyn_app_structured():
with patch("robyn.cli.prompt") as mock_prompt:
mock_prompt.return_value = {
"directory": "test_dir",
"docker": "N",
"scaffold_type": "structured",
"project_type": "no-db",
}
with patch("robyn.cli.os.makedirs") as mock_makedirs:
Expand Down
56 changes: 56 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
argcomplete==2.0.6 ; python_version >= "3.8" and python_version < "4.0"
attrs==24.2.0 ; python_version >= "3.8" and python_version < "4.0"
black==23.1.0 ; python_version >= "3.8" and python_version < "4.0"
certifi==2024.8.30 ; python_version >= "3.8" and python_version < "4"
cffi==1.15.1 ; python_version >= "3.8" and python_version < "4.0"
cfgv==3.4.0 ; python_version >= "3.8" and python_version < "4.0"
charset-normalizer==2.1.1 ; python_version >= "3.8" and python_version < "4.0"
click==8.1.7 ; python_version >= "3.8" and python_version < "4.0"
colorama==0.4.6 ; python_version >= "3.8" and python_version < "4.0"
colorlog==6.8.2 ; python_version >= "3.8" and python_version < "4.0"
commitizen==2.40.0 ; python_version >= "3.8" and python_version < "4.0"
decli==0.5.2 ; python_version >= "3.8" and python_version < "4.0"
dill==0.3.8 ; python_version >= "3.8" and python_version < "4.0"
distlib==0.3.8 ; python_version >= "3.8" and python_version < "4.0"
exceptiongroup==1.2.2 ; python_version >= "3.8" and python_version < "3.11"
filelock==3.16.1 ; python_version >= "3.8" and python_version < "4.0"
identify==2.6.1 ; python_version >= "3.8" and python_version < "4.0"
idna==3.10 ; python_version >= "3.8" and python_version < "4"
iniconfig==2.0.0 ; python_version >= "3.8" and python_version < "4.0"
inquirerpy==0.3.4 ; python_version >= "3.8" and python_version < "4.0"
isort==5.11.5 ; python_version >= "3.8" and python_version < "4.0"
jinja2==3.0.1 ; python_version >= "3.8" and python_version < "4.0"
markupsafe==2.1.5 ; python_version >= "3.8" and python_version < "4.0"
maturin==0.14.12 ; python_version >= "3.8" and python_version < "4.0"
multiprocess==0.70.14 ; python_version >= "3.8" and python_version < "4.0"
mypy-extensions==1.0.0 ; python_version >= "3.8" and python_version < "4.0"
nestd==0.3.1 ; python_version >= "3.8" and python_version < "4.0"
nodeenv==1.9.1 ; python_version >= "3.8" and python_version < "4.0"
nox==2023.4.22 ; python_version >= "3.8" and python_version < "4.0"
orjson==3.10.7 ; python_version >= "3.8" and python_version < "4.0"
packaging==24.1 ; python_version >= "3.8" and python_version < "4.0"
pathspec==0.12.1 ; python_version >= "3.8" and python_version < "4.0"
pfzy==0.3.4 ; python_version >= "3.8" and python_version < "4.0"
platformdirs==4.3.6 ; python_version >= "3.8" and python_version < "4.0"
pluggy==1.5.0 ; python_version >= "3.8" and python_version < "4.0"
pre-commit==2.21.0 ; python_version >= "3.8" and python_version < "4.0"
prompt-toolkit==3.0.48 ; python_version >= "3.8" and python_version < "4.0"
pycparser==2.22 ; python_version >= "3.8" and python_version < "4.0"
pytest-codspeed==1.2.2 ; python_version >= "3.8" and python_version < "4.0"
pytest==7.2.1 ; python_version >= "3.8" and python_version < "4.0"
pyyaml==6.0.2 ; python_version >= "3.8" and python_version < "4.0"
questionary==1.10.0 ; python_version >= "3.8" and python_version < "4.0"
requests==2.28.2 ; python_version >= "3.8" and python_version < "4"
ruff==0.1.3 ; python_version >= "3.8" and python_version < "4.0"
rustimport==1.5.0 ; python_version >= "3.8" and python_version < "4.0"
termcolor==2.4.0 ; python_version >= "3.8" and python_version < "4.0"
toml==0.10.2 ; python_version >= "3.8" and python_version < "4.0"
tomli==2.0.1 ; python_version >= "3.8" and python_version < "3.11"
tomlkit==0.13.2 ; python_version >= "3.8" and python_version < "4.0"
typing-extensions==4.12.2 ; python_version >= "3.8" and python_version < "4.0"
urllib3==1.26.20 ; python_version >= "3.8" and python_version < "4"
uvloop==0.19.0 ; sys_platform != "win32" and sys_platform != "cygwin" and platform_python_implementation != "PyPy" and python_version >= "3.8" and python_version < "4.0"
virtualenv==20.26.6 ; python_version >= "3.8" and python_version < "4.0"
watchdog==4.0.1 ; python_version >= "3.8" and python_version < "4.0"
wcwidth==0.2.13 ; python_version >= "3.8" and python_version < "4.0"
websocket-client==1.5.0 ; python_version >= "3.8" and python_version < "4.0"
62 changes: 47 additions & 15 deletions robyn/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,24 +38,53 @@ def create_robyn_app():
},
{
"type": "list",
"message": "Please select project type (Mongo/Postgres/Sqlalchemy/Prisma): ",
"choices": [
Choice("no-db", name="No DB"),
Choice("sqlite", name="Sqlite"),
Choice("postgres", name="Postgres"),
Choice("mongo", name="MongoDB"),
Choice("sqlalchemy", name="SqlAlchemy"),
Choice("prisma", name="Prisma"),
Choice("sqlmodel", name="SQLModel"),
],
"default": Choice("no-db", name="No DB"),
"name": "project_type",
"name": "scaffold_type",
"choices": [Choice("simple", name="Simple"), Choice("structured", name="Structured")],
"message": "Please choose if you'd like the scaffold to be a simple starter kit or an opinionated structure",
},
]
result = prompt(questions=questions)
project_dir_path = Path(str(result["directory"])).resolve()
docker = result["docker"]
project_type = str(result["project_type"])
scaffold_type: str = str(result["scaffold_type"])
if scaffold_type == "simple":
scaffold_type: str = "simple"
result = prompt(
questions=[
{
"type": "list",
"message": "Please select project type (Mongo/Postgres/Sqlalchemy/Prisma): ",
"choices": [
Choice("no-db", name="No DB"),
Choice("sqlite", name="Sqlite"),
Choice("postgres", name="Postgres"),
Choice("mongo", name="MongoDB"),
Choice("sqlalchemy", name="SqlAlchemy"),
Choice("prisma", name="Prisma"),
Choice("sqlmodel", name="SQLModel"),
],
"default": Choice("no-db", name="No DB"),
"name": "project_type",
}
]
)
project_type = str(result["project_type"])
else:
result = prompt(
questions=[
{
"type": "list",
"message": "Please select project type (Mongo/Postgres/Sqlalchemy/Prisma): ",
"choices": [
Choice("no-db", name="No DB"),
Choice("sqlalchemy", name="SqlAlchemy"),
],
"default": Choice("no-db", name="No DB"),
"name": "project_type",
}
]
)
project_type = str(result["project_type"])

final_project_dir_path = (CURRENT_WORKING_DIR / project_dir_path).resolve()

Expand All @@ -64,12 +93,15 @@ def create_robyn_app():
# Create a new directory for the project
os.makedirs(final_project_dir_path, exist_ok=True)

selected_project_template = (SCAFFOLD_DIR / Path(project_type)).resolve()
selected_project_template = (SCAFFOLD_DIR / Path(scaffold_type) / Path(project_type)).resolve()
shutil.copytree(str(selected_project_template), str(final_project_dir_path), dirs_exist_ok=True)

# If docker is not needed, delete the docker file
if docker == "N":
os.remove(f"{final_project_dir_path}/Dockerfile")
if scaffold_type == "simple":
os.remove(f"{final_project_dir_path}/Dockerfile")
else:
shutil.rmtree(f"{final_project_dir_path}/devops", ignore_errors=True)

print(f"New Robyn project created in '{final_project_dir_path}' ")

Expand Down
43 changes: 43 additions & 0 deletions robyn/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import importlib
import logging
import pkgutil
from typing import Any, Tuple, Type

from pydantic import ConfigDict
from pydantic_settings import BaseSettings, EnvSettingsSource, PydanticBaseSettingsSource

from robyn import Robyn

logger = logging.getLogger(__name__)


def discover_routes(handler_path: str = "api.handlers") -> Robyn:
mux: Robyn = Robyn(__file__)
package = importlib.import_module(handler_path)
for _, module_name, _ in pkgutil.iter_modules(package.__path__, package.__name__ + "."):
module = importlib.import_module(module_name)
logger.info(f"member: {module}")
mux.include_router(module.router)
return mux


class AcceptArrayEnvsSource(EnvSettingsSource):
def prepare_field_value(self, field_name: str, field: Any, value: Any, value_is_complex: bool) -> Any:
if isinstance(field.annotation, type) and issubclass(field.annotation, list) and isinstance(value, str):
return [x.strip() for x in value.split(",") if x]
return value


class BaseConfig(BaseSettings):
@classmethod
def settings_customise_sources(
cls,
settings_cls: Type[BaseSettings],
init_settings: PydanticBaseSettingsSource,
env_settings: PydanticBaseSettingsSource,
dotenv_settings: PydanticBaseSettingsSource,
file_secret_settings: PydanticBaseSettingsSource,
) -> Tuple[PydanticBaseSettingsSource, ...]:
return (AcceptArrayEnvsSource(settings_cls),)

model_config = ConfigDict(extra="ignore") # Ignore extra environment variables
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Empty file.
Loading
Loading