Skip to content

Commit a8690ed

Browse files
committed
feat: create built-in template engine, create settings
1 parent fc58f8f commit a8690ed

File tree

21 files changed

+379
-57
lines changed

21 files changed

+379
-57
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
commit fc58f8f30efd759f59b4ec87800442a105f5c592
2+
Author: alexeev-prog <[email protected]>
3+
Date: Mon Oct 28 21:23:05 2024 +0700
4+
5+
docs/feat/fix: improve routing views (fix bugs), improve readme
6+
17
commit 313ad646d2fdb10c45692e564b4381b548fe3a55
28
Author: alexeev-prog <[email protected]>
39
Date: Mon Oct 28 00:34:48 2024 +0700

Doxyfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ PROJECT_NAME = "pyEchoNext"
4848
# could be handy for archiving the generated documentation or if some version
4949
# control system is used.
5050

51-
PROJECT_NUMBER = "0.2.1"
51+
PROJECT_NUMBER = "0.3.1"
5252

5353
# Using the PROJECT_BRIEF tag one can provide an optional one line description
5454
# for a project that appears at the top of each page and should give viewer a

README.md

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -107,37 +107,43 @@ Once installed, you can start using the library in your Python projects. Check o
107107
## 💻 Usage Examples
108108

109109
### Advanced app with flask-like and django-like routes
110-
Django-line classes with get-post methods and routing pages:
110+
Django-line classes with get-post methods and routing pages. And with the built-in template engine!
111111

112112
```python
113+
import os
113114
from pyechonext.app import ApplicationType, EchoNext
114115
from pyechonext.views import View
115116
from pyechonext.urls import URL, IndexView
117+
from pyechonext.config import Settings
118+
from pyechonext.template_engine.builtin import render_template
116119

117120

118121
class UsersView(View):
119122
def get(self, request, response, **kwargs):
120-
return "users get"
123+
return render_template(
124+
request, "index.html", user_name="User", friends=["Bob", "Anna", "John"]
125+
)
121126

122127
def post(self, request, response, **kwargs):
123-
return "users post"
128+
return {"users": "post"}
124129

125130

126-
url_patterns = [
127-
URL(url='/', view=IndexView),
128-
URL(url='/users', view=UsersView)
129-
]
130-
131-
echonext = EchoNext(__name__, urls=url_patterns, application_type=ApplicationType.HTML)
131+
url_patterns = [URL(url="/", view=IndexView), URL(url="/users", view=UsersView)]
132+
settings = Settings(
133+
BASE_DIR=os.path.dirname(os.path.abspath(__file__)), TEMPLATES_DIR="templates"
134+
)
135+
echonext = EchoNext(
136+
__name__, settings, urls=url_patterns, application_type=ApplicationType.HTML
137+
)
132138

133139

134140
@echonext.route_page("/book")
135141
class BooksResource(View):
136142
def get(self, request, response, **kwargs):
137-
return f"Books Page: {request.query_params}"
143+
return f"GET Params: {request.GET}"
138144

139145
def post(self, request, response, **kwargs):
140-
return "Endpoint to create a book"
146+
return f"POST Params: {request.POST}"
141147
```
142148

143149
<p align="right">(<a href="#readme-top">back to top</a>)</p>
@@ -146,14 +152,18 @@ class BooksResource(View):
146152
In this example we are using SQLSymphony ORM (our other project, a fast and simple ORM for python)
147153

148154
```python
155+
import os
149156
from pyechonext.app import ApplicationType, EchoNext
157+
from pyechonext.config import Settings
150158
from sqlsymphony_orm.datatypes.fields import IntegerField, RealField, TextField
151159
from sqlsymphony_orm.models.session_models import SessionModel
152160
from sqlsymphony_orm.models.session_models import SQLiteSession
153-
from sqlsymphony_orm.queries import QueryBuilder
154161

155162

156-
echonext = EchoNext(__name__, application_type=ApplicationType.HTML)
163+
settings = Settings(
164+
BASE_DIR=os.path.dirname(os.path.abspath(__file__)), TEMPLATES_DIR="templates"
165+
)
166+
echonext = EchoNext(__name__, settings, application_type=ApplicationType.HTML)
157167
session = SQLiteSession("echonext.db")
158168

159169

@@ -170,7 +180,7 @@ class User(SessionModel):
170180

171181
@echonext.route_page("/")
172182
def home(request, response):
173-
user = User(name='John', cash=100.0)
183+
user = User(name="John", cash=100.0)
174184
session.add(user)
175185
session.commit()
176186
response.body = "Hello from the HOME page"
@@ -179,8 +189,9 @@ def home(request, response):
179189
@echonext.route_page("/users")
180190
def about(request, response):
181191
users = session.get_all_by_model(User)
182-
192+
183193
response.body = f"Users: {[f'{user.name}: {user.cash}$' for user in users]}"
194+
184195
```
185196

186197
<p align="right">(<a href="#readme-top">back to top</a>)</p>

SECURITY.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ currently being supported with security updates.
77

88
| Version | Supported |
99
| ------- | ------------------ |
10+
| 0.3.1 | :white_check_mark: |
1011
| 0.2.1 | :white_check_mark: |
1112
| 0.1.1 | :white_check_mark: |
12-
| 0.1.0 | :white_check_mark: |
13+
| 0.1.0 | :x |
1314

1415
## Reporting a Vulnerability
1516

examples/advanced_app.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import os
12
from pyechonext.app import ApplicationType, EchoNext
23
from pyechonext.views import View
34
from pyechonext.urls import URL, IndexView
5+
from pyechonext.config import Settings
46

57

68
class UsersView(View):
@@ -12,14 +14,18 @@ def post(self, request, response, **kwargs):
1214

1315

1416
url_patterns = [URL(url="/", view=IndexView), URL(url="/users", view=UsersView)]
15-
16-
echonext = EchoNext(__name__, urls=url_patterns, application_type=ApplicationType.HTML)
17+
settings = Settings(
18+
BASE_DIR=os.path.dirname(os.path.abspath(__file__)), TEMPLATES_DIR="templates"
19+
)
20+
echonext = EchoNext(
21+
__name__, settings, urls=url_patterns, application_type=ApplicationType.HTML
22+
)
1723

1824

1925
@echonext.route_page("/book")
2026
class BooksResource(View):
2127
def get(self, request, response, **kwargs):
22-
return f"Books Page: {request.query_params}"
28+
return f"Books Page: {request.GET}"
2329

2430
def post(self, request, response, **kwargs):
2531
return "Endpoint to create a book"

examples/simple_api.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import os
2+
from pyechonext.app import ApplicationType, EchoNext
3+
from pyechonext.views import View
4+
from pyechonext.urls import URL, IndexView
5+
from pyechonext.response import Response
6+
from pyechonext.config import Settings
7+
8+
9+
class UsersView(View):
10+
def get(self, request, response, **kwargs):
11+
return Response(body={"users": "get"})
12+
13+
def post(self, request, response, **kwargs):
14+
return {"users": "post"}
15+
16+
17+
url_patterns = [URL(url="/", view=IndexView), URL(url="/users", view=UsersView)]
18+
19+
settings = Settings(
20+
BASE_DIR=os.path.dirname(os.path.abspath(__file__)), TEMPLATES_DIR="templates"
21+
)
22+
23+
echonext = EchoNext(
24+
__name__, settings, urls=url_patterns, application_type=ApplicationType.JSON
25+
)
26+
27+
28+
@echonext.route_page("/book")
29+
class BooksResource(View):
30+
def get(self, request, response, **kwargs):
31+
return {"params": {request.GET}, "page": "books"}
32+
33+
def post(self, request, response, **kwargs):
34+
return {"params": {request.POST}, "page": "books"}

examples/simple_app.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1+
import os
12
from pyechonext.app import ApplicationType, EchoNext
3+
from pyechonext.config import Settings
24
from sqlsymphony_orm.datatypes.fields import IntegerField, RealField, TextField
35
from sqlsymphony_orm.models.session_models import SessionModel
46
from sqlsymphony_orm.models.session_models import SQLiteSession
57

68

7-
echonext = EchoNext(__name__, application_type=ApplicationType.HTML)
9+
settings = Settings(
10+
BASE_DIR=os.path.dirname(os.path.abspath(__file__)), TEMPLATES_DIR="templates"
11+
)
12+
echonext = EchoNext(__name__, settings, application_type=ApplicationType.HTML)
813
session = SQLiteSession("echonext.db")
914

1015

examples/templates/index.html

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Document</title>
7+
</head>
8+
<body>
9+
<h1>{{ user_name }}</h1>
10+
<h3>Friends</h3>
11+
{% for friend in friends %}
12+
<p>{{ friend }}</p>
13+
{% endblock %}
14+
</body>
15+
</html>

examples/webapp.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import os
2+
from pyechonext.app import ApplicationType, EchoNext
3+
from pyechonext.views import View
4+
from pyechonext.urls import URL, IndexView
5+
from pyechonext.config import Settings
6+
from pyechonext.template_engine.builtin import render_template
7+
8+
9+
class UsersView(View):
10+
def get(self, request, response, **kwargs):
11+
return render_template(
12+
request, "index.html", user_name="User", friends=["Bob", "Anna", "John"]
13+
)
14+
15+
def post(self, request, response, **kwargs):
16+
return {"users": "post"}
17+
18+
19+
url_patterns = [URL(url="/", view=IndexView), URL(url="/users", view=UsersView)]
20+
settings = Settings(
21+
BASE_DIR=os.path.dirname(os.path.abspath(__file__)), TEMPLATES_DIR="templates"
22+
)
23+
echonext = EchoNext(
24+
__name__, settings, urls=url_patterns, application_type=ApplicationType.HTML
25+
)
26+
27+
28+
@echonext.route_page("/book")
29+
class BooksResource(View):
30+
def get(self, request, response, **kwargs):
31+
return f"GET Params: {request.GET}"
32+
33+
def post(self, request, response, **kwargs):
34+
return f"POST Params: {request.POST}"

pyechonext/app.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
WebError,
1616
)
1717
from pyechonext.utils import _prepare_url
18+
from pyechonext.config import Settings
1819

1920

2021
class ApplicationType(Enum):
@@ -24,18 +25,20 @@ class ApplicationType(Enum):
2425

2526
JSON = "application/json"
2627
HTML = "text/html"
28+
PLAINTEXT = "text/plain"
2729

2830

2931
class EchoNext:
3032
"""
3133
This class describes an EchoNext WSGI Application.
3234
"""
3335

34-
__slots__ = ("app_name", "application_type", "urls", "routes")
36+
__slots__ = ("app_name", "settings", "application_type", "urls", "routes")
3537

3638
def __init__(
3739
self,
3840
app_name: str,
41+
settings: Settings,
3942
urls: Optional[List[URL]] = [],
4043
application_type: Optional[ApplicationType] = ApplicationType.JSON,
4144
):
@@ -46,6 +49,7 @@ def __init__(
4649
:type app_name: str
4750
"""
4851
self.app_name = app_name
52+
self.settings = settings
4953
self.application_type = application_type
5054
self.routes = {}
5155
self.urls = urls
@@ -107,7 +111,7 @@ def _get_request(self, environ: dict) -> Request:
107111
:returns: The request.
108112
:rtype: Request
109113
"""
110-
return Request(environ)
114+
return Request(environ, self.settings)
111115

112116
def _get_response(self) -> Response:
113117
"""
@@ -201,7 +205,12 @@ def _handle_request(self, request: Request) -> Response:
201205
if handler is None:
202206
raise MethodNotAllow(f"Method not allowed: {request.method}")
203207

204-
response.body = handler(request, response, **kwargs)
208+
result = handler(request, response, **kwargs)
209+
210+
if isinstance(result, Response):
211+
response = result
212+
else:
213+
response.body = result
205214
else:
206215
raise URLNotFound(f'URL "{request.path}" not found.')
207216

0 commit comments

Comments
 (0)