Skip to content

Commit b5a6ed6

Browse files
committed
Rewrote some docs and added docs on modulesetup and dynamic setup
1 parent b6a69d1 commit b5a6ed6

30 files changed

+690
-188
lines changed

docs/background-task.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
## Coming Soon

docs/basics/api-docs.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
## Coming Soon

docs/basics/commands.md

Whitespace-only changes.

docs/basics/events.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
## Coming Soon

docs/basics/testing.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
## Coming Soon

docs/basics/versioning.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
## Coming Soon

docs/caching.md

Lines changed: 65 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,64 @@ By caching data in a faster, more local storage location, the system can quickly
77
In Ellar, we provided several cache backends interface that interacts with different cache types to assist in cache endpoint responses or other relevant data.
88

99
## Setting up the cache
10-
It's very simple to set up cache in Ellar but the crucial part is picking the cache type that is suitable for your application because some cache type behave differently and perform better and faster than others.
10+
It's very simple to set up cache in Ellar but the crucial part is picking the cache type that is suitable for your application
11+
because some cache type behave differently and perform better and faster than others.
1112

12-
The configuration of your cache defined in `CACHES` variable in `config.py` file.
13+
To set up cache, we need to use `CacheModule`. `CacheModule` provides two methods, `CacheModule.register_setup` and `CacheModule.setup`, for setting up `cache` in ellar applications.
1314

14-
```python
15-
# project_name/config.py
15+
=== "CacheModule Register Setup"
16+
This setup method requires you to defined `CACHES` variable containing
17+
key value pairs of cache backends in `config.py` file.
18+
19+
for example:
20+
21+
```python
22+
# project_name/config.py
23+
24+
from ellar.core import ConfigDefaultTypesMixin
25+
from ellar.cache.backends.local_cache import LocalMemCacheBackend
26+
27+
class DevelopmentConfig(ConfigDefaultTypesMixin):
28+
CACHES = {
29+
'default': LocalMemCacheBackend(ttl=300, key_prefix='local', version=1)
30+
}
31+
```
32+
33+
After that you register `CacheModule` to application modules
34+
```python
35+
# project_name/root_module.py
36+
from ellar.cache import CacheModule
37+
from ellar.common import Module
38+
39+
@Module(modules=[CacheModule.register_setup()])
40+
class ApplicationModule:
41+
pass
42+
```
43+
The `register_setup` will read `CACHES` from application config and setup the `CacheService` appropriately.
1644

17-
from ellar.core import ConfigDefaultTypesMixin
18-
from ellar.cache.backends.local_cache import LocalMemCacheBackend
45+
=== "CacheModule Setup"
46+
The setup method requires direct definition of cache backend on the `CacheModule` setup function.
47+
48+
for example:
1949

20-
class DevelopmentConfig(ConfigDefaultTypesMixin):
21-
CACHES = {
22-
'default': LocalMemCacheBackend(timeout=300, key_prefix='local', version=1)
23-
}
24-
```
50+
```python
51+
# project_name/root_module.py
52+
from ellar.cache import CacheModule
53+
from ellar.cache.backends.local_cache import LocalMemCacheBackend
54+
from ellar.common import Module
55+
56+
@Module(modules=[
57+
CacheModule.setup(
58+
default=LocalMemCacheBackend(ttl=300, key_prefix='default', version=1),
59+
local=LocalMemCacheBackend(key_prefix='local'),
60+
others=LocalMemCacheBackend(key_prefix='others'),
61+
)
62+
])
63+
class ApplicationModule:
64+
pass
65+
```
66+
In CacheModule.`setup`, the `default` parameter must be provided and other cache
67+
backends will be defined as keyword-arguments just like `local` and `others` incase you want to set up more than one cache backend.
2568

2669
### **Memcached**
2770
[Memcached](https://memcached.org/) is an entirely memory-based cache server, originally developed to handle high loads at LiveJournal.com and subsequently open-sourced by Danga Interactive.
@@ -273,7 +316,7 @@ class DevelopmentConfig(ConfigDefaultTypesMixin):
273316
'default': PyMemcacheCacheBackend(
274317
servers=['127.0.0.1:11211'],
275318
options={'default_noreply': True},
276-
timeout=300,
319+
ttl=300,
277320
version=1,
278321
key_prefix='project_name'
279322
)
@@ -296,7 +339,7 @@ from ellar.cache.backends.local_cache import LocalMemCacheBackend
296339
class DevelopmentConfig(ConfigDefaultTypesMixin):
297340
CACHES = {
298341
'default': RedisCacheBackend(servers=['redis://127.0.0.1:6379'], key_prefix='project_name'),
299-
'secondary': LocalMemCacheBackend(timeout=300, key_prefix='project_name', version=1)
342+
'secondary': LocalMemCacheBackend(ttl=300, key_prefix='project_name', version=1)
300343
}
301344
```
302345

@@ -313,14 +356,14 @@ The CacheService class provides methods like:
313356

314357
- **get**_**(key: str, version: str = None, backend: str = None)**_: gets `key` value from a specified cache backend.
315358
- **get_async**_**(key: str, version: str = None, backend: str = None)**_: asynchronous version of `get` action
316-
- **set**_**(key: str, value: t.Any, timeout: t.Union[float, int] = None, version: str = None,backend: str = None)**_: sets value to a key to a specified cache backend.
317-
- **set_async**_**(key: str, value: t.Any, timeout: t.Union[float, int] = None, version: str = None,backend: str = None)**_: asynchronous version of `set` action
359+
- **set**_**(key: str, value: t.Any, ttl: t.Union[float, int] = None, version: str = None,backend: str = None)**_: sets value to a key to a specified cache backend.
360+
- **set_async**_**(key: str, value: t.Any, ttl: t.Union[float, int] = None, version: str = None,backend: str = None)**_: asynchronous version of `set` action
318361
- **delete**_**(key: str, version: str = None, backend: str = None)**_: deletes a key from a specified cache backend.
319362
- **delete_async**_**(key: str, version: str = None, backend: str = None)**_: asynchronous version of `delete` action
320363
- **has_key**_**(key: str, version: str = None, backend: str = None)**_: checks if a key exist in a specified backend
321364
- **has_key_async**_**(key: str, version: str = None, backend: str = None)**_: asynchronous version of `has_key` action
322-
- **touch**_**(key: str, timeout: t.Union[float, int] = None, version: str = None, backend: str = None)**_: sets a new expiration for a key
323-
- **touch_async**_**(key: str, timeout: t.Union[float, int] = None, version: str = None, backend: str = None)**_: asynchronous version of `touch` action
365+
- **touch**_**(key: str, ttl: t.Union[float, int] = None, version: str = None, backend: str = None)**_: sets a new expiration for a key
366+
- **touch_async**_**(key: str, ttl: t.Union[float, int] = None, version: str = None, backend: str = None)**_: asynchronous version of `touch` action
324367
- **incr**_**(key: str, delta: int = 1, version: str = None, backend: str = None)**_: increments a value for a key by delta
325368
- **incr_async**_**(key: str, delta: int = 1, version: str = None, backend: str = None)**_: asynchronous version of `incr` action
326369
- **decr**_**(key: str, delta: int = 1, version: str = None, backend: str = None)**_: decrement a value for a key by delta
@@ -373,7 +416,7 @@ Ellar provides a cache decorator that can be used to cache the responses of rout
373416

374417
The cache decorator takes the following arguments:
375418

376-
- `timeout`: the amount of time (in seconds) for which the response data should be cached.
419+
- `ttl`(time to live): the amount of time (in seconds) for which the response data should be cached.
377420
- `key_prefix` (optional): a string that is used to prefix the cache key, allowing for easy differentiation between different cache items.
378421
- `version` (optional): a string that is used to version the cache key, allowing for cache invalidation when the data schema changes.
379422
- `backend` (optional): the name of the cache backend to use for storing the cached data. By default, the `default` cache backend is used.
@@ -386,7 +429,7 @@ We can rewrite the above example using `cache` decorator:
386429

387430
...
388431
@get('/cache-test')
389-
@cache(timeout=300, version='v1', key_prefix='project_name')
432+
@cache(ttl=300, version='v1', key_prefix='project_name')
390433
def my_route_function(self):
391434
processed_value = 'some-value'
392435
return processed_value
@@ -397,7 +440,7 @@ We can rewrite the above example using `cache` decorator:
397440

398441
...
399442
@get('/cache-test')
400-
@cache(timeout=300, version='v1', key_prefix='project_name')
443+
@cache(ttl=300, version='v1', key_prefix='project_name')
401444
async def my_route_function(self):
402445
processed_value = 'some-value'
403446
return processed_value
@@ -422,7 +465,7 @@ Here's an example of how to use a custom `make_key_callback` function with the c
422465

423466
...
424467
@get("/my_endpoint")
425-
@cache(timeout=60, make_key_callback=make_key_function)
468+
@cache(ttl=60, make_key_callback=make_key_function)
426469
def my_endpoint(self):
427470
# Code to generate response data here
428471
processed_value = 'some-value'
@@ -442,7 +485,7 @@ Here's an example of how to use a custom `make_key_callback` function with the c
442485

443486
...
444487
@get("/my_endpoint")
445-
@cache(timeout=60, make_key_callback=make_key_function)
488+
@cache(ttl=60, make_key_callback=make_key_function)
446489
async def my_endpoint(self):
447490
# Code to generate response data here
448491
processed_value = 'some-value'

docs/commands/command-grouping.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
2+
Ella CLI provides a way by which commands can be grouped.
3+
4+
For instance, a `db` command may have sub-commands like `makemigrations`, `migrate`, `reset-db` etc.
5+
6+
To achieve this use-case, let us create a file `commands.py` in the root level of the project.
7+
8+
```python
9+
from ellar.commands import EllarTyper
10+
11+
db = EllarTyper(name="db")
12+
13+
14+
@db.command(name="make-migrations")
15+
def makemigrations():
16+
"""Create DB Migration """
17+
18+
@db.command()
19+
def migrate():
20+
"""Applies Migrations"""
21+
```
22+
23+
## Register EllarTyper Command
24+
25+
Lets, make the `db` visible on the CLI.
26+
27+
In other for Ellar CLI to identify custom command, its has to be registered to a `@Module` class.
28+
29+
```python
30+
from ellar.common import Module
31+
from ellar.core import ModuleBase
32+
from .commands import db
33+
34+
@Module(commands=[db])
35+
class ApplicationModule(ModuleBase):
36+
pass
37+
```
38+
39+
open your terminal and navigate to project directory and run the command below
40+
```shell
41+
ellar db --help
42+
```
43+
44+
command output
45+
```shell
46+
Usage: Ellar, Python Web framework db [OPTIONS] COMMAND [ARGS]...
47+
48+
Options:
49+
--help Show this message and exit.
50+
51+
Commands:
52+
make-migrations Create DB Migration
53+
migrate Applies Migrations
54+
55+
```
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
This command helps you create an Ellar project module, like a small app within a project.
3+
It depends on the existence of an Ellar project.
4+
5+
```shell
6+
ellar create-module my_project_module
7+
```
8+
9+
will create a folder as follows:
10+
```angular2html
11+
john_doe/
12+
├─ apps/
13+
│ ├─ my_project_module/
14+
│ │ ├─ tests/
15+
│ │ │ ├─ __init__.py
16+
│ │ ├─ controllers.py
17+
│ │ ├─ module.py
18+
│ │ ├─ routers.py
19+
│ │ ├─ services.py
20+
│ │ ├─ __init__.py
21+
│ ├─ __init__.py
22+
├─ core/
23+
├─ domain/
24+
├─ tests/
25+
│ ├─ __init__.py
26+
├─ __init__.py/
27+
├─ config.py
28+
├─ root_module.py dsssss cxccccccxxcxxnew_file
29+
├─ server.py
30+
31+
```
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
This command helps you create just an Ellar project provided the `"pyproject.toml"` file exists in the working directory(`CWD`)
3+
4+
```shell
5+
ellar create-project my_new_project
6+
```
7+
8+
will create a folder as follows:
9+
```angular2html
10+
my_new_project/
11+
├─ apps/
12+
│ ├─ __init__.py
13+
├─ core/
14+
├─ config.py
15+
├─ domain
16+
├─ root_module.py
17+
├─ server.py
18+
├─ __init__.py
19+
```

docs/commands/custom-commands.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
In this section, we are going to go over how to create a custom command and throw more light on how Ella CLI works.
2+
3+
## Create Custom Command
4+
Let's create a file called `commands.py` at the root level of the project.
5+
6+
```python
7+
# project_name/commands.py
8+
9+
from ellar.common import command
10+
11+
@command
12+
def my_new_command():
13+
"""my_new_command cli description """
14+
```
15+
16+
## Custom Command with Context
17+
18+
Ellar CLI tools is a wrapper round [typer](https://typer.tiangolo.com/).
19+
So, therefore, we can easily get the command context by adding a parameter with the annotation of `typer.Context`
20+
21+
Ellar CLI adds some meta-data CLI context that provides an interface for interaction with the Ellar project.
22+
23+
For example:
24+
25+
```python
26+
import typing as t
27+
import typer
28+
from ellar.common import command
29+
from ellar_cli.service import EllarCLIService
30+
from ellar_cli.constants import ELLAR_META
31+
32+
@command
33+
def my_new_command(ctx:typer.Context):
34+
"""my_new_command CLI Description """
35+
ellar_cli_service = t.cast(t.Optional[EllarCLIService], ctx.meta.get(ELLAR_META))
36+
app = ellar_cli_service.import_application()
37+
```
38+
`EllarCLIService` is an Ellar CLI meta-data for interacting with Ellar project.
39+
40+
Some important method that may be of interest:
41+
42+
- `import_application`: returns application instance.
43+
- `get_application_config`: gets current application config.
44+
45+
## Register a Custom Command
46+
47+
Lets, make the `my_new_command` visible on the CLI.
48+
In other for Ellar CLI to identify custom command, its has to be registered to a `@Module` class.
49+
50+
For example:
51+
52+
```python
53+
# project_name/root_module.py
54+
from ellar.common import Module
55+
from ellar.core import ModuleBase
56+
from .commands import my_new_command
57+
58+
@Module(commands=[my_new_command])
59+
class ApplicationModule(ModuleBase):
60+
pass
61+
```
62+
63+
open your terminal and navigate to project directory and run the command below
64+
```shell
65+
ellar --help
66+
```
67+
68+
command output
69+
```shell
70+
Usage: Ellar, Python Web framework [OPTIONS] COMMAND [ARGS]...
71+
72+
Options:
73+
-p, --project TEXT Run Specific Command on a specific project
74+
--install-completion [bash|zsh|fish|powershell|pwsh]
75+
Install completion for the specified shell.
76+
--show-completion [bash|zsh|fish|powershell|pwsh]
77+
Show completion for the specified shell, to
78+
copy it or customize the installation.
79+
--help Show this message and exit.
80+
81+
Commands:
82+
create-module - Scaffolds Ellar Application Module -
83+
create-project - Scaffolds Ellar Application -
84+
my-new-command - my_new_command cli description
85+
new - Runs a complete Ellar project scaffold and creates...
86+
runserver - Starts Uvicorn Server -
87+
say-hi
88+
```

0 commit comments

Comments
 (0)