Skip to content

Commit 3911aa1

Browse files
authored
Merge pull request #73 from eadwinCode/module_configuration_2
Module configuration
2 parents df022e5 + 5a57e08 commit 3911aa1

File tree

90 files changed

+1934
-597
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+1934
-597
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ doc-deploy: ## Run Deploy Documentation
3939
mkdocs gh-deploy --force --ignore-version
4040

4141
doc-serve: ## Launch doc local server
42-
make mkdoc serve
42+
mkdocs serve
4343

4444
pre-commit-lint: ## Runs Requires commands during pre-commit
4545
make clean

README.md

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,15 @@ If you are familiar with these frameworks, you will find it easy to understand a
4040
## Installation
4141
### Poetry Installation
4242
For [Poetry](https://python-poetry.org/) usages
43+
4344
```shell
44-
poetry add ellar[standard]
45+
poetry add ellar-cli
4546
```
4647

4748
### Pip Installation
4849
For normal pip installation
4950
```shell
50-
pip install ellar[standard]
51-
```
52-
### NB:
53-
Some shells may treat square braces (`[` and `]`) as special characters. If that's the case here, then use a quote around the characters to prevent unexpected shell expansion.
54-
```shell
55-
pip install "ellar[standard]"
51+
pip install ellar-cli
5652
```
5753

5854
## Create a project
@@ -234,7 +230,6 @@ Ellar is not aware of `CarModule` yet, so we need to add it to the `modules` lis
234230
```python
235231
from ellar.common import Module, exception_handler
236232
from ellar.core import IHostContext, ModuleBase
237-
from ellar.core.connection import Request
238233
from ellar.core.response import JSONResponse, Response
239234

240235
from ellar.samples.modules import HomeModule
@@ -256,7 +251,7 @@ import os
256251

257252
from ellar.constants import ELLAR_CONFIG_MODULE
258253
from ellar.core.factory import AppFactory
259-
from ellar.openapi import OpenAPIDocumentModule, OpenAPIDocumentBuilder
254+
from ellar.openapi import OpenAPIDocumentModule, OpenAPIDocumentBuilder, SwaggerDocumentGenerator
260255
from .root_module import ApplicationModule
261256

262257
application = AppFactory.create_from_app_module(
@@ -273,8 +268,12 @@ document_builder.set_title('CarSite API') \
273268
.set_license('MIT Licence', url='https://www.google.com')
274269

275270
document = document_builder.build_document(application)
276-
module = application.install_module(OpenAPIDocumentModule, document=document)
277-
module.setup_swagger_doc()
271+
module = OpenAPIDocumentModule.setup(
272+
document=document,
273+
document_generator=SwaggerDocumentGenerator(),
274+
guards=[]
275+
)
276+
application.install_module(module)
278277
```
279278

280279
Now we can test our API at [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs#/)
@@ -303,4 +302,3 @@ Project is still in development
303302
- Documentation - (in progress)
304303
- Interceptors - [Aspect Oriented Programming](https://en.wikipedia.org/wiki/Aspect-oriented_programming) (AOP) technique
305304
- Database Plugin with [Encode/ORM](https://github.com/encode/orm)
306-
- API Throttling

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+
```

0 commit comments

Comments
 (0)