Skip to content

Commit

Permalink
CHanges:
Browse files Browse the repository at this point in the history
- provide/update more docs
- add asgi import discovery
  • Loading branch information
devkral committed Nov 15, 2024
1 parent dbb1000 commit 250d430
Show file tree
Hide file tree
Showing 16 changed files with 148 additions and 171 deletions.
9 changes: 4 additions & 5 deletions docs/edgy-people.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# Edgy People
# Edgy Contributors

## The Special Ones

Currently there are no special ones but we are hoping this will change soon.
Edgy wouldn't be possible in this way without this people.

## The Legends
- @kokoserver

Currently there are no legends but we are hoping this will change soon.
He provided a lot of valuable bug reports and PRs. Especially related to migrations.
18 changes: 18 additions & 0 deletions docs/extensions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Extensions

Edgy has extension support build on the Monkay extensions system. Adding extensions
is possible in settings via the attribute/parameter `extensions`.

They must implement the monkay extension protocol or return as a callable a class implementing the extension protocol.
This sounds hard but it isn't:

``` python
{!> ../docs_src/extensions/settings !}
```

You can also lazily provide them via add_extension (should happen before the instance is set)


``` python
{!> ../docs_src/extensions/add_extension !}
```
21 changes: 17 additions & 4 deletions docs/migrations/discovery.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,16 @@ When no `--app` or no `EDGY_DEFAULT_APP` environment variable is provided, Edgy
* **main.py**
* **app.py**
* **application.py**
* **asgi.py**

(Or are otherwise importable by python without the .py stem)

!!! 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 check if the instance was set.

This is the way that Edgy can `auto discover` your application.
Expand Down Expand Up @@ -160,23 +164,32 @@ We will be also executing the commands inside `myproject`.
$ edgy init
```

Yes! Simply this and because the `--app` or a `EDGY_DEFAULT_APP` was provided, it triggered the
Yes! Simply this and because not the `--app` or a `EDGY_DEFAULT_APP` was provided nor preloads were found, 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](#how-does-it-work).

##### Using the --app or EDGY_DISCOVERY_APP
##### Using preloads

Edgy has an automatic registration pattern. All what `--app` or `EDGY_DEFAULT_APP` does is to import a file.
The registration is expected to take place in the module automatically.
Thanks to Monkay you can also provide such an import path as preload under
`preloads` in settings.
When the instance is set in a preloaded file, the auto-discovery is skipped.


##### Using the --app or EDGY_DEFAULT_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.
inside the `src/main.py` we need to provide the proper location is a `<module>` format.

###### --app

With the `--app` flag.

```shell
$ edgy --app src.main:app init
$ edgy --app src.main init
```

###### EDGY_DEFAULT_APP
Expand Down
79 changes: 30 additions & 49 deletions docs/migrations/migrations.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,37 +72,39 @@ This makes Edgy unique and extremely flexible to be used within any of the Frame
such as [Esmerald](https://esmerald.dymmond.com), Starlette, FastAPI, Sanic... You choose.

```python
from edgy import Migrate
from edgy import Instance, monkay

monkay.set_instance(Instance(registry=registry, app=None))
```

### Parameters

The parameters availabe when using instantiating a [Migrate](#migration) object are the following:
The parameters availabe when using instantiating a [Instance](#migration) object are the following:

* **app** - The application instance. Any application you want your migrations to be attached to.
* **registry** - The registry being used for your models. The registry **must be** an instance
of `edgy.Registry` or an `AssertationError` is raised.
* **model_apps** - A dictionary like object containing the string name and the location of the models
used for inspection.
* **compare_type** - Flag option that configures the automatic migration generation subsystem
to detect column type changes.
* **app** - Optionally an application instance.

<sup>Default: `True`</sup>
### Settings

* **render_as_batch** - This option generates migration scripts using batch mode, an operational
mode that works around limitations of many ALTER commands in the SQLite database by implementing
a "move and copy" workflow. Enabling this mode should make no difference when working with other
databases.
The following settings are available in the main settings object:

<sup>Default: `True`</sup>
- multi_schema (bool / regexstring / regexpattern) - Activate multi schema migrations (Default: False).
- ignore_schema_pattern (None / regexstring / regexpattern) - When using multi schema migrations, ignore following regex pattern (Default "information_schema")
- alembic_ctx_kwargs (dict) - Extra arguments for alembic. By default:
``` python
{
"compare_type": True,
"render_as_batch": True,
}
```
- migration_directory (str / PathLike) - Migrations directory. Absolute or relative. By default: "migrations".

* **kwargs** - A python dictionary with any context variables to be added to alembic.

<sup>Default: `None`</sup>

### How to use it

Using the [Migration](#migration) class is very simple in terms of requirements. In the
Using the [Instance](#migration) class is very simple in terms of requirements. In the
[tips and tricks](../tips-and-tricks.md) you can see some examples in terms of using the
[LRU cache technique](../tips-and-tricks.md#the-lru-cache). If you haven't seen it,
it is recommended you to have a look.
Expand Down Expand Up @@ -215,32 +217,11 @@ There is where your models for the `accounts` application will be placed. Someth
{!> ../docs_src/migrations/accounts_models.py !}
```

Now we want to tell the **Migrate** object to make sure it knows about this.

##### Via dictionary

```python
{!> ../docs_src/migrations/via_dict.py !}
```

As you can see the `model_apps = {"accounts": "accounts.models"}` was added in a simple fashion.
Every time you add new model or any changes, it should behave as normal as before with the key difference
that **now Edgy has a way to know exactly where your models are specifically**.

##### Via tuple

```python
{!> ../docs_src/migrations/via_tuple.py !}
```

The same for the tuple. You can simply pass `("accounts.models",)` as the location for the models.

##### Via list
Now we want to tell the **Instance** object to make sure it knows about this.

```python
{!> ../docs_src/migrations/via_list.py !}
{!> ../docs_src/migrations/instance.py !}
```
Finally, for the `list`. You can pass `["accounts.models"]` as the location for the models.

## Generating and working with migrations

Expand Down Expand Up @@ -327,28 +308,28 @@ $ export EDGY_DATABASE_URL=postgresql+asyncpg://user:pass@localhost:5432/my_data

Or whatever connection string you are using.

### Initialise the migrations folder
### Initialize the migrations folder

It is now time to generate the migrations folder. As mentioned before in the
[environment variables section](#environment-variables), Edgy does need to have the
`EDGY_DATABASE_URL` to generate the `migrations` folder. So, without further ado let us generate
our `migrations`.

```shell
edgy --app myproject.main:app init
edgy --app myproject.main init
```

What is happenening here? Well, `edgy` is always expecting an `--app` parameter to be
provided.

This `--app` is the location of your application in `module:app` format and this is because of
This `--app` is the location of your application in `module_app` format and this is because of
the fact of being **framework agnostic**.

Edgy needs to know where your application object is located in order to hook it to that same
application.
Edgy needs the module automatically setting the instance (see [Connections](connection.md)) to know the registry
which shall be used as well as the application object.

Remember when it was mentioned that is important the location where you generate the migrations
folder? Well, this is why, because when you do `my_project.main:app` you are telling that
folder? Well, this is why, because when you do `my_project.main` you are telling that
your application is inside the `myproject/main/app.py` and your migration folder should be placed
**where the command was executed**.

Expand Down Expand Up @@ -454,7 +435,7 @@ There are many ways of exposing your models of course, so feel free to use any a
Now it is time to generate the migration.

```shell
$ edgy --app my_project.main:app makemigrations
$ edgy --app my_project.main makemigrations
```

Yes, it is this simple 😁
Expand All @@ -479,7 +460,7 @@ Your new migration should now be inside `migrations/versions/`. Something like t
Or you can attach a message your migration that will then added to the file name as well.

```shell
$ edgy --app my_project.main:app makemigrations -m "Initial migrations"
$ edgy --app my_project.main makemigrations -m "Initial migrations"
```

```shell hl_lines="10"
Expand Down Expand Up @@ -519,13 +500,13 @@ for any other ORM and when you are happy run the migrations and apply them again
**Generate new migrations**

```shell
$ edgy --app my_project.main:app makemigrations
$ edgy --app my_project.main makemigrations
```

**Apply them to your database**

```shell
$ edgy --app my_project.main:app migrate
$ edgy --app my_project.main migrate
```

### More migration commands
Expand Down
8 changes: 5 additions & 3 deletions docs/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@ hide:
- Breaking: EdgyExtra and Migrate are replaced by `edgy.Instance` but are still available.
- Breaking: EdgyExtra is provided by the also obsolete Migrate.
- Breaking: `model_apps` is replaced by `preloads` but still available during the migration time.
- Breaking:
An automatic registration is assumed. See [Connection](connection.md) for examples.

### Fixed

- Migrations with ManyToMany fields are broken.
- get_engine_url_and_metadata was broken for some operations (thanks kososerver).
- get_engine_url_and_metadata was broken for some operations (thanks @kokoserver).

### Unresolved
### Contributors

- When copying a registry through models aren't copied properly.
Thanks a lot to @kokoserver. He provided a *lot* of valuable bug reports and PRs.


## 0.22.0
Expand Down
13 changes: 12 additions & 1 deletion docs/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ widely applied across the system.

#### Custom settings

When creating your own custom settings class, you should inherit from `EdgySettings` which is
When creating your own custom settings class, you should inherit from `EdgySettings` (or the subclass `TenancySettings` in case of multi tenancy). `EdgySettings` is
the class responsible for all internal settings of Edgy and those can be extended and overriden
with ease.

Expand All @@ -44,6 +44,14 @@ has some which are used across the codebase and those can be overriden easily.

##### Parameters

* **preloads** - List of imports preloaded. Non-existing imports are simply ignored.ng the `edgy shell`.

<sup>Default: `[]`</sup>

* **extensions** - List of Monkay extensions for edgy.

<sup>Default: `[]`</sup>

* **ipython_args** - List of arguments passed to `ipython` when starting the `edgy shell`.

<sup>Default: `["--no-banner"]`</sup>
Expand All @@ -64,6 +72,9 @@ settings should be called like this:
$ EDGY_SETTINGS_MODULE=myproject.configs.settings.MyCustomSettings edgy <COMMAND>
```

Optional prequesite: set one of the preload imports to the application path. This way you can skip
providing the `--app` parameter or providing the `EDGY_DEFAULT_APP`.

Example:

**Starting the default shell**
Expand Down
7 changes: 2 additions & 5 deletions docs/shell.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ The following examples and explanations will be using the [auto discovery](./mig
but [--app and environment variables](./migrations/discovery.md#environment-variables) approach but the
is equally valid and works in the same way.

!!! Tip
See the [extras](./extras.md) section after getting familiar with the previous. There offers
a way of using the shell without going through the **Migrate** object.

## How does it work

Expand Down Expand Up @@ -80,13 +77,13 @@ $ edgy shell --kernel ptpython
**--app**

```shell
$ edgy --app myproject.main:app shell
$ edgy --app myproject.main shell
```

**Environment variables**

```shell
$ export EDGY_DEFAULT_APP=--app myproject.main
$ export EDGY_DEFAULT_APP=myproject.main
$ edgy shell --kernel ptpython
```

Expand Down
2 changes: 1 addition & 1 deletion docs_src/connections/django.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.core.asgi import get_asgi_application


from edgy import Registry, Migrate
from edgy import Registry, Instance

models = Registry(database="sqlite:///db.sqlite", echo=True)

Expand Down
24 changes: 24 additions & 0 deletions docs_src/extensions/add_extension.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from dataclasses import dataclass

import edgy


@dataclass
class Extension(ExtensionProtocol[edgy.Instance, edgy.Registry]):
name: str = "hello"

def apply(self, monkay_instance: Monkay[edgy.Instance, edgy.Registry]) -> None:
"""Do something here"""


@dataclass
class ExtensionLessTyped(ExtensionProtocol):
name: str = "hello"

def apply(self, monkay_instance: Monkay) -> None:
"""Do something here"""


edgy.monkay.add_extension(Extension())

edgy.monkay.add_extension(ExtensionLessTyped())
22 changes: 22 additions & 0 deletions docs_src/extensions/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from typing import Any
from edgy import EdgySettings


@dataclass
class Extension(ExtensionProtocol[edgy.Instance, edgy.Registry]):
name: str = "hello"

def apply(self, monkay_instance: Monkay[edgy.Instance, edgy.Registry]) -> None:
"""Do something here"""


@dataclass
class ExtensionLessTyped(ExtensionProtocol):
name: str = "hello"

def apply(self, monkay_instance: Monkay) -> None:
"""Do something here"""


class ExtensionSettings(EdgySettings):
extensions: list[Any] = [Extension(), ExtensionLessTyped()]
Loading

0 comments on commit 250d430

Please sign in to comment.