Skip to content

Application Discovery

Edgy has many different ways of understanding the commands, one is via environment variables and another is via auto discovery.

Auto Discovery

If you are familiar with other frameworks like Django, you are surely familiar with the way the use the manage.py to basically run every command internally.

Although not having that same level, Edgy does a similar job by having "a guess" of what it should be and throws an error if not found or if no environment variables or --app are provided.

The application discovery works as an alternative to providing the --app or a EDGY_DEFAULT_APP environment variable.

So, what does this mean?

This means if you do not provide an --app or a EDGY_DEFAULT_APP, Edgy will try to find the application for you automatically.

Let us see a practical example of what does this mean.

Imagine the following folder and file structure:

myproject
.
├── Makefile
└── myproject
    ├── __init__.py
    ├── apps
       ├── __init__.py
    ├── configs
       ├── __init__.py
       ├── development
          ├── __init__.py
          └── settings.py
       ├── settings.py
       └── testing
           ├── __init__.py
           └── settings.py
    ├── main.py
    ├── tests
       ├── __init__.py
       └── test_app.py
    └── urls.py

Tip

The application can be anything from Esmerald, Starlette, Sanic and even FastAPI.

The structure above of myproject has a lot of files and the one higlighted is the one that contains the application object with the Migration from Edgy.

How does it work?

When no --app or no EDGY_DEFAULT_APP environment variable is provided, Edgy will automatically look for:

  • The current directory where edgy is being called contains a file called:

    • main.py
    • app.py
    • application.py

    Warning

    If none of these files are found, Edgy will look at the first children nodes, only, and repeats the same process. If no files are found then throws an CommandEnvironmentError exception.

  • Once one of those files is found, Edgy will analised the type of objects contained in the module and will check if any of them contains the Migration object attached and return it.

  • If Edgy understand that none of those objects contain the Migration, it will do one last attempt and try to find specific function declarations:

    • get_application()
    • get_app()

This is the way that Edgy can auto discover your application.

Note

Flask has a similar pattern for the functions called create_app. Edgy doesn't use the create_app, instead uses the get_application or get_app as a pattern as it seems cleaner.

Environment variables

When generating migrations, Edgy expects at least one environment variable to be present.

  • EDGY_DATABASE_URL - The database url for your database.

The reason for this is because Edgy is agnostic to any framework and this way it makes it easier to work with the migrations.

Also, gives a clean design for the time where it is needed to go to production as the procedure is very likely to be done using environment variables.

This variable must be present. So to save time you can simply do:

$ export EDGY_DATABASE_URL=postgresql+asyncpg://user:pass@localhost:5432/my_database

Or whatever connection string you are using.

Alternatively, you can simply pass --app as a parameter with the location of your application instead.

Example:

$ edgy --app myproject.main:app init

How to use and when to use it

Previously it was used a folder structure as example and then an explanation of how Edgy would understand the auto discovery but in practice, how would that work?

This is applied to any command within Edgy.

Let us see again the structure, in case you have forgotten already.

myproject
.
├── Makefile
└── src
    ├── __init__.py
    ├── apps
       ├── accounts
          ├── directives
             ├── __init__.py
             └── operations
                 └── __init__.py
    ├── configs
       ├── __init__.py
       ├── development
          ├── __init__.py
          └── settings.py
       ├── settings.py
       └── testing
           ├── __init__.py
           └── settings.py
    ├── main.py
    ├── tests
       ├── __init__.py
       └── test_app.py
    └── urls.py

The main.py is the file that contains the edgy migration. A file that could look like this:

myproject/src/main.py
#!/usr/bin/env python
import os
import sys
from pathlib import Path

from esmerald import Esmerald, Include
from my_project.utils import get_db_connection

from edgy import Migrate


def build_path():
    """
    Builds the path of the project and project root.
    """
    Path(__file__).resolve().parent.parent
    SITE_ROOT = os.path.dirname(os.path.realpath(__file__))

    if SITE_ROOT not in sys.path:
        sys.path.append(SITE_ROOT)
        sys.path.append(os.path.join(SITE_ROOT, "apps"))


def get_application():
    """
    This is optional. The function is only used for organisation purposes.
    """
    build_path()
    database, registry = get_db_connection()

    app = Esmerald(
        routes=[Include(namespace="my_project.urls")],
    )

    Migrate(app=app, registry=registry)
    return app


app = get_application()

This is a simple example with two endpoints, you can do as you desire with the patterns you wish to add and with any desired structure.

What will be doing now is run the following commands using the auto discovery and the --app or EDGY_DEFAULT_APP:

  • init - Starts the migrations and creates the migrations folder.
  • makemigrations - Generates the migrations for the application.

We will be also executing the commands inside myproject.

You can see more information about these commands, including parameters, in the next section.

Using the auto discover

init

Using the auto discover
$ edgy init

Yes! Simply this and because the --app or a EDGY_DEFAULT_APP was provided, it triggered the auto discovery of the application that contains the edgy information.

Because the application is inside src/main.py it will be automatically discovered by Edgy as it followed the discovery pattern.

Using the --app or EDGY_DISCOVERY_APP

This is the other way to tell Edgy where to find your application. Since the application is inside the src/main.py we need to provide the proper location is a <module>:<app> format.

--app

With the --app flag.

$ edgy --app src.main:app init
EDGY_DEFAULT_APP

With the EDGY_DEFAULT_APP.

Export the env var first:

$ export EDGY_DEFAULT_APP=src.main:app

And then run:

$ edgy init

makemigrations

You can see more details how to use it.

It is time to run this command.

Using the auto discover
$ edgy makemigrations

Again, same principle as before because the --app or a EDGY_DEFAULT_APP was provided, it triggered the auto discovery of the application.

Using the --app or EDGY_DISCOVERY_APP
--app

With the --app flag.

$ edgy --app src.main:app makemigrations
EDGY_DEFAULT_APP

With the EDGY_DEFAULT_APP.

Export the env var first:

$ export EDGY_DEFAULT_APP=src.main:app

And then run:

$ edgy makemigrations