Skip to content

Commit 8bbe0a0

Browse files
committed
Bump version to 0.3.0a5 with major updates of routing and erro page
1 parent 25b6e8a commit 8bbe0a0

9 files changed

Lines changed: 969 additions & 99 deletions

File tree

README.md

Lines changed: 396 additions & 14 deletions
Large diffs are not rendered by default.

index.html

Lines changed: 0 additions & 10 deletions
This file was deleted.

mallo/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from mallo.request import Request
77
from mallo.response import Response
88
from mallo.cli import cli
9+
from mallo.template import render_template, render_template_file
910

10-
__version__ = "0.3.0a4"
11-
__all__ = ['Mallo', 'Request', 'Response', 'cli' ]
11+
__version__ = "0.3.0a5"
12+
__all__ = ['Mallo', 'Request', 'Response', 'cli', 'render_template', 'render_template_file' ]

mallo/app.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from mallo.router import Router
1515
from mallo.request import Request
1616
from mallo.response import Response
17-
from mallo.template import render_template_file
17+
from mallo.template import render_template, render_template_file
1818
from mallo.utils import generate_etag
1919
from mallo.hot_reload import HotReloader
2020

@@ -146,12 +146,12 @@ def delete(self, path):
146146
"""
147147
return self.route(path, methods=['DELETE'])
148148

149-
def render_template(self, template_path, **context):
149+
def render_template(self, template_name, **context):
150150
"""
151151
Render a template from any file path
152152
153153
Args:
154-
template_path: path to template file (absolute or relative)
154+
template_name: template file name relative to template folder
155155
**context: Variable to pass to template
156156
157157
Returns:
@@ -160,15 +160,22 @@ def render_template(self, template_path, **context):
160160
Example:
161161
@app.route('/')
162162
def home(request):
163-
return app.render_template('templates/home.html', name = 'Mallo User')
163+
return app.render_template('home.html', name='Mallo User')
164164
165165
166-
:param template_path:
166+
:param template_name:
167167
:param context:
168168
:return:
169169
"""
170170
auto_escape = self.config.get('auto_escape', True)
171-
return render_template_file(template_path, auto_reload=self.debug, auto_escape=auto_escape, **context)
171+
template_folder = self.config.get('template_folder', 'templates')
172+
return render_template(
173+
template_name,
174+
template_folder=template_folder,
175+
auto_reload=self.debug,
176+
auto_escape=auto_escape,
177+
**context
178+
)
172179

173180
def before_request(self, func):
174181
self.before_request_funcs.append(func)

mallo/cli.py

Lines changed: 278 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -49,25 +49,289 @@ def api_data(request):
4949
f.write(app_content)
5050

5151
# Create index.html
52-
index_content = '''<!DOCTYPE html>
53-
<html>
52+
index_content = '''
53+
<!DOCTYPE html>
54+
<html lang="en">
5455
<head>
55-
<title>Mallo App</title>
56-
<style>
57-
body { font-family: Arial, sans-serif; max-width: 800px; margin: 50px auto; }
58-
h1 { color: #333; }
59-
</style>
56+
<meta charset="UTF-8" />
57+
<meta name="viewport" content="width=device-width, initial-scale=1" />
58+
<title>Mallo Framework</title>
59+
<style>
60+
@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;700&family=Space+Mono:wght@400;700&display=swap');
61+
62+
:root {
63+
--bg: #f8f5ef;
64+
--paper: #fffdf9;
65+
--ink: #16130f;
66+
--muted: #655a4d;
67+
--accent: #bb5a1d;
68+
--accent-2: #1f7a7a;
69+
--line: #e7dccd;
70+
--shadow: 0 24px 60px rgba(31, 22, 12, 0.14);
71+
--radius: 18px;
72+
}
73+
74+
* {
75+
box-sizing: border-box;
76+
}
77+
78+
body {
79+
margin: 0;
80+
font-family: "Outfit", "Segoe UI", sans-serif;
81+
color: var(--ink);
82+
background:
83+
radial-gradient(1000px 500px at 10% 0%, #efe4d3 0%, rgba(239, 228, 211, 0) 60%),
84+
radial-gradient(900px 450px at 90% 0%, #ddeeea 0%, rgba(221, 238, 234, 0) 56%),
85+
var(--bg);
86+
line-height: 1.5;
87+
}
88+
89+
.page {
90+
max-width: 1080px;
91+
margin: 0 auto;
92+
padding: 38px 20px 70px;
93+
}
94+
95+
.top {
96+
display: flex;
97+
justify-content: space-between;
98+
align-items: center;
99+
margin-bottom: 30px;
100+
}
101+
102+
.brand {
103+
font-weight: 700;
104+
letter-spacing: 0.08em;
105+
text-transform: uppercase;
106+
font-size: 0.86rem;
107+
color: var(--accent);
108+
}
109+
110+
.chip {
111+
border: 1px solid var(--line);
112+
background: var(--paper);
113+
border-radius: 999px;
114+
padding: 8px 12px;
115+
font-size: 0.84rem;
116+
color: var(--muted);
117+
}
118+
119+
.hero {
120+
background: var(--paper);
121+
border: 1px solid var(--line);
122+
border-radius: var(--radius);
123+
box-shadow: var(--shadow);
124+
padding: 34px;
125+
margin-bottom: 20px;
126+
position: relative;
127+
overflow: hidden;
128+
}
129+
130+
.hero::after {
131+
content: "";
132+
position: absolute;
133+
right: -60px;
134+
top: -60px;
135+
width: 220px;
136+
height: 220px;
137+
border-radius: 50%;
138+
background: radial-gradient(circle, rgba(187, 90, 29, 0.2) 0%, rgba(187, 90, 29, 0) 70%);
139+
pointer-events: none;
140+
}
141+
142+
h1 {
143+
margin: 0 0 12px;
144+
font-size: clamp(2rem, 5vw, 3.5rem);
145+
line-height: 1.05;
146+
max-width: 760px;
147+
}
148+
149+
.lead {
150+
margin: 0;
151+
max-width: 700px;
152+
color: var(--muted);
153+
font-size: 1.05rem;
154+
}
155+
156+
.actions {
157+
display: flex;
158+
gap: 10px;
159+
margin-top: 22px;
160+
flex-wrap: wrap;
161+
}
162+
163+
.btn {
164+
text-decoration: none;
165+
border-radius: 12px;
166+
padding: 11px 16px;
167+
font-weight: 600;
168+
transition: transform 140ms ease, box-shadow 140ms ease;
169+
display: inline-block;
170+
}
171+
172+
.btn.primary {
173+
background: var(--accent);
174+
color: #fff;
175+
box-shadow: 0 12px 24px rgba(187, 90, 29, 0.28);
176+
}
177+
178+
.btn.secondary {
179+
background: #fff;
180+
color: var(--ink);
181+
border: 1px solid var(--line);
182+
}
183+
184+
.btn:hover {
185+
transform: translateY(-1px);
186+
}
187+
188+
.grid {
189+
display: grid;
190+
grid-template-columns: repeat(12, 1fr);
191+
gap: 14px;
192+
margin-top: 14px;
193+
}
194+
195+
.card {
196+
background: var(--paper);
197+
border: 1px solid var(--line);
198+
border-radius: 14px;
199+
padding: 20px;
200+
}
201+
202+
.card h3 {
203+
margin: 0 0 8px;
204+
font-size: 1.05rem;
205+
}
206+
207+
.card p {
208+
margin: 0;
209+
color: var(--muted);
210+
font-size: 0.96rem;
211+
}
212+
213+
.span-4 { grid-column: span 4; }
214+
.span-6 { grid-column: span 6; }
215+
.span-8 { grid-column: span 8; }
216+
217+
.snippet {
218+
background: #151a22;
219+
color: #ecf1ff;
220+
border-radius: 14px;
221+
padding: 18px;
222+
margin-top: 14px;
223+
border: 1px solid #202838;
224+
font-family: "Space Mono", monospace;
225+
font-size: 0.9rem;
226+
overflow-x: auto;
227+
}
228+
229+
.snippet .prompt {
230+
color: #8dd6d0;
231+
}
232+
233+
.footer {
234+
margin-top: 20px;
235+
color: var(--muted);
236+
font-size: 0.9rem;
237+
text-align: center;
238+
}
239+
240+
@media (max-width: 900px) {
241+
.span-4,
242+
.span-6,
243+
.span-8 {
244+
grid-column: span 12;
245+
}
246+
.hero {
247+
padding: 26px;
248+
}
249+
}
250+
</style>
60251
</head>
61252
<body>
62-
<h1>Welcome to Mallo, {{ name }}!</h1>
63-
<p>Your lightweight Flask alternative is working!</p>
64-
<p>Try:</p>
65-
<ul>
66-
<li><a href="/hello/World">/hello/World</a></li>
67-
<li><a href="/api/data">/api/data</a></li>
68-
</ul>
253+
<div class="page">
254+
<div class="top">
255+
<div class="brand">Mallo Framework</div>
256+
<div class="chip">Minimal Web Core • Fast Iteration</div>
257+
</div>
258+
259+
<section class="hero">
260+
<h1>Build web apps with a clean Python workflow, and help shape Mallo.</h1>
261+
<p class="lead">
262+
Mallo gives you routing, templates, static files, error pages, and development reload in a small readable codebase.
263+
You keep control while moving quickly, and your contributions directly improve the framework.
264+
</p>
265+
<div class="actions">
266+
<a class="btn primary" href="https://pypi.org/project/mallo/" target="_blank" rel="noreferrer">Install from PyPI</a>
267+
<a class="btn secondary" href="https://github.com/Betrand-dev/mallo-fr.git" target="_blank" rel="noreferrer">Contribute on GitHub</a>
268+
</div>
269+
</section>
270+
271+
<section class="grid">
272+
<article class="card span-4">
273+
<h3>Simple Routing</h3>
274+
<p>Register endpoints with decorators and typed URL params without extra ceremony.</p>
275+
</article>
276+
<article class="card span-4">
277+
<h3>Template Rendering</h3>
278+
<p>Use <code>render_template()</code> for the <code>templates/</code> folder or <code>render_template_file()</code> for explicit paths.</p>
279+
</article>
280+
<article class="card span-4">
281+
<h3>Safe Defaults</h3>
282+
<p>Auto-escaped templates, security headers, CSRF checks, and structured error pages.</p>
283+
</article>
284+
<article class="card span-6">
285+
<h3>Production Path</h3>
286+
<p>Run with Gunicorn, package from PyPI, and keep improving with versioned pre-releases.</p>
287+
</article>
288+
<article class="card span-6">
289+
<h3>Developer Experience</h3>
290+
<p>Live reload in debug mode, readable internals, and a small surface area for faster onboarding.</p>
291+
</article>
292+
</section>
293+
294+
<div class="snippet">
295+
<span class="prompt">from</span> mallo <span class="prompt">import</span> Mallo, render_template<br><br>
296+
app = Mallo(__name__)<br><br>
297+
@app.get('/')<br>
298+
def home(request):<br>
299+
&nbsp;&nbsp;&nbsp;&nbsp;return render_template('index.html', title='Welcome to Mallo')<br><br>
300+
if __name__ == '__main__':<br>
301+
&nbsp;&nbsp;&nbsp;&nbsp;app.run(debug=True)
302+
</div>
303+
304+
<section class="grid">
305+
<article class="card span-8">
306+
<h3>Call for Contributors</h3>
307+
<p>
308+
Mallo is actively evolving. If you work with Python web apps, your help can directly improve architecture,
309+
developer experience, and production readiness.
310+
</p>
311+
</article>
312+
<article class="card span-4">
313+
<h3>Start Here</h3>
314+
<p>Open issues, propose improvements, or submit a pull request for docs, tests, or core features.</p>
315+
</article>
316+
<article class="card span-4">
317+
<h3>Good First PRs</h3>
318+
<p>Template improvements, middleware polish, test coverage, and CLI usability.</p>
319+
</article>
320+
<article class="card span-4">
321+
<h3>Join the Core Work</h3>
322+
<p>Help harden sessions, request parsing, and deployment workflows for stable production use.</p>
323+
</article>
324+
<article class="card span-4">
325+
<h3>Repository</h3>
326+
<p><a href="https://github.com/Betrand-dev/mallo-fr.git" target="_blank" rel="noreferrer">github.com/Betrand-dev/mallo-fr</a></p>
327+
</article>
328+
</section>
329+
330+
<div class="footer">Mallo • lightweight Python web framework</div>
331+
</div>
69332
</body>
70333
</html>
334+
71335
'''
72336

73337
with open(os.path.join(name, 'templates', 'index.html'), 'w') as f:

0 commit comments

Comments
 (0)