Life is short, You need Python!
+diff --git a/code/newsletter/N7/cli.py b/code/newsletter/N7/cli.py new file mode 100644 index 0000000..986b833 --- /dev/null +++ b/code/newsletter/N7/cli.py @@ -0,0 +1,56 @@ +import argparse +import pathlib + +import jinja2 + +ROOT = pathlib.Path(__file__).parent +TEMPLATE = ROOT / "templates/project" + +env = jinja2.Environment( + trim_blocks=True, + loader=jinja2.FileSystemLoader(TEMPLATE), +) + + +def setup_cli(): + parser = argparse.ArgumentParser() + subparser = parser.add_subparsers() + + startapp = subparser.add_parser("startapp") + startapp.add_argument( + "name", + type=str, + help="the app name", + ) + return parser + + +def build_layout(name: str): + app_dir = ROOT.joinpath(f"{name}") + if app_dir.exists(): + print(f"{name} directory has exists!") + return + else: + app_dir.mkdir() + + for base in TEMPLATE.iterdir(): + basename = base.stem + fpath = app_dir.joinpath(f"{basename}") + if basename == "__init__.py": + fpath.write_text("") + continue + + with open(fpath, mode="w+", encoding="utf-8") as f: + content = env.get_template(base.name).render(app_name=name) + f.write(content) + + +def main(): + parser = setup_cli() + args = parser.parse_args() + print(args) + build_layout(name=args.name) + + +if __name__ == '__main__': + main() diff --git a/code/newsletter/N7/quickstart.ipynb b/code/newsletter/N7/quickstart.ipynb new file mode 100644 index 0000000..7c2be67 --- /dev/null +++ b/code/newsletter/N7/quickstart.ipynb @@ -0,0 +1,397 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import jinja2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# variables" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "your variable value: 100gle\n", + "\n", + "inner set variable value: author\n" + ] + } + ], + "source": [ + "tpl = \"\"\"\\\n", + "your variable value: {{ name }}\n", + "{% set badge=\"author\" %}\n", + "inner set variable value: {{ badge }}\n", + "\"\"\"\n", + "\n", + "template = jinja2.Template(tpl)\n", + "s = template.render(name=\"100gle\")\n", + "print(s)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# comment" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'Hello, world\\n'" + ] + }, + "execution_count": 50, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tpl = \"\"\"\\\n", + "Hello, world\n", + "{# this line wouldn't be rendered. #}\n", + "\"\"\"\n", + "\n", + "template = jinja2.Template(tpl)\n", + "template.render()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# for loop" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " * Reading\n", + " * Home Work\n", + " * Exercise\n", + "\n" + ] + } + ], + "source": [ + "tpl = \"\"\"\\\n", + "{# use for-loop in jinja2 #}\n", + "{% for todo in todolist %}\n", + " * {{ todo }}\n", + "{% endfor %}\n", + "\"\"\"\n", + "\n", + "todolist = [\"Reading\", \"Home Work\", \"Exercise\"]\n", + "template = jinja2.Template(tpl, trim_blocks=True)\n", + "s = template.render(todolist=todolist)\n", + "print(s)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " name: Reading\n", + " priority: 2\n", + " name: Home Work\n", + " priority: 0\n", + " name: Exercise\n", + " priority: 1\n", + "\n" + ] + } + ], + "source": [ + "tpl = \"\"\"\\\n", + "{# use for-loop in jinja2 #}\n", + "{% for todo in todolist %}\n", + " {% for key, value in todo.items() %}\n", + " {{ key }}: {{ value }}\n", + " {% endfor %}\n", + "{% endfor %}\n", + "\"\"\"\n", + "\n", + "todolist = [\n", + " dict(name=\"Reading\", priority=2),\n", + " dict(name=\"Home Work\", priority=0),\n", + " dict(name=\"Exercise\", priority=1),\n", + "]\n", + "template = jinja2.Template(tpl, trim_blocks=True, lstrip_blocks=True)\n", + "s = template.render(todolist=todolist)\n", + "print(s)\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# if-else" + ] + }, + { + "cell_type": "code", + "execution_count": 52, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " Reading**\n", + " Home Work\n", + " Exercise*\n", + "\n" + ] + } + ], + "source": [ + "tpl = \"\"\"\\\n", + "{% for todo in todolist %}\n", + " {% if todo.priority == 2 %}\n", + " {{ todo.name }}**\n", + " {% elif todo.priority == 1 %}\n", + " {{ todo.name }}*\n", + " {% else %}\n", + " {{ todo.name }}\n", + " {% endif %}\n", + "{% endfor %}\n", + "\"\"\"\n", + "\n", + "todolist = [\n", + " dict(name=\"Reading\", priority=2),\n", + " dict(name=\"Home Work\", priority=0),\n", + " dict(name=\"Exercise\", priority=1),\n", + "]\n", + "\n", + "template = jinja2.Template(tpl, lstrip_blocks=True, trim_blocks=True)\n", + "s = template.render(todolist=todolist)\n", + "print(s)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# macros" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + " Reading**\n", + " Home Work\n", + " Exercise*\n", + "\n" + ] + } + ], + "source": [ + "tpl = \"\"\"\\\n", + "{% macro show_todo(name, priority) -%}\n", + " {% set marker=\"\" %}\n", + " {% if priority == 2 %}\n", + " {% set marker = \"**\" %}\n", + " {% elif priority == 1 %}\n", + " {% set marker = \"*\" %}\n", + " {% endif %}\n", + " {{ name }}{{ marker }}\n", + "{%- endmacro %}\n", + "\n", + "{% for todo in todolist %}\n", + " {{ show_todo(todo.name, todo.priority) }}\n", + "{% endfor %}\n", + "\"\"\"\n", + "\n", + "todolist = [\n", + " dict(name=\"Reading\", priority=2),\n", + " dict(name=\"Home Work\", priority=0),\n", + " dict(name=\"Exercise\", priority=1),\n", + "]\n", + "\n", + "template = jinja2.Template(tpl, trim_blocks=True, lstrip_blocks=True)\n", + "s = template.render(todolist=todolist)\n", + "print(s)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# filter" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " - before: $10.99, after: 10.99\n", + " - before: €0.99, after: 0.99\n", + " - before: ¥100, after: 100\n", + "\n" + ] + } + ], + "source": [ + "def remove_currerncy(val: str):\n", + " currencies = set(\"$€¥\")\n", + " if val[0] in currencies:\n", + " return val[1:]\n", + " return val\n", + "\n", + "tpl = \"\"\"\\\n", + "{% for value in money %}\n", + " - before: {{ value }}, after: {{ value|remove_currency}}\n", + "{% endfor %}\n", + "\"\"\"\n", + "\n", + "money = [\"$10.99\", \"€0.99\", \"¥100\"]\n", + "\n", + "\n", + "env = jinja2.Environment(trim_blocks=True)\n", + "env.filters[\"remove_currency\"] = remove_currerncy\n", + "\n", + "template = env.from_string(tpl)\n", + "s = template.render(money=money)\n", + "print(s)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# inheritance" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# bug: TemplateNotFound error should be fixed.\n", + "\n", + "Your environment:\n", + "\n", + " - python version: 3.9\n", + " - jinja2: 3.2.x\n", + " \n", + "---\n", + "\n", + "Bug detail:\n", + "\n", + "More description here:\n", + "\n", + " ```python\n", + " ...\n", + " ```\n", + "\n" + ] + } + ], + "source": [ + "env = jinja2.Environment(\n", + " trim_blocks=True,\n", + " loader=jinja2.FileSystemLoader(\"./templates/inheritance/\"),\n", + ")\n", + "\n", + "template = env.get_template(\"bug_report.md\")\n", + "s = template.render(\n", + " title=\"bug: TemplateNotFound error should be fixed.\",\n", + " setup=[\n", + " dict(name=\"python version\", detail=3.9),\n", + " dict(name=\"jinja2\", detail=\"3.2.x\"),\n", + " ],\n", + " description=\"\"\"\\\n", + "More description here:\n", + "\n", + " ```python\n", + " ...\n", + " ```\n", + " \"\"\".strip()\n", + ")\n", + "print(s)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.9.0 ('pandas-startup')", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.0" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "13977d4cc82dee5f9d9535ceb495bd0ab12a43c33c664e5f0d53c24cf634b67f" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/code/newsletter/N7/templates/inheritance/base.md b/code/newsletter/N7/templates/inheritance/base.md new file mode 100644 index 0000000..fad90bb --- /dev/null +++ b/code/newsletter/N7/templates/inheritance/base.md @@ -0,0 +1,11 @@ +# {% block title %}{% endblock %} + +Your environment: + +{% block environment %}{% endblock %} + +--- + +Bug detail: + +{% block description %}{% endblock %} diff --git a/code/newsletter/N7/templates/inheritance/bug_report.md b/code/newsletter/N7/templates/inheritance/bug_report.md new file mode 100644 index 0000000..fd09f6f --- /dev/null +++ b/code/newsletter/N7/templates/inheritance/bug_report.md @@ -0,0 +1,15 @@ +{% extends "base.md" %} + +{% block title %} +{{ title }} +{% endblock %} + +{% block environment %} + {% for item in setup %} + - {{ item.name }}: {{ item.detail }} + {% endfor %} +{% endblock %} + +{% block description %} +{{ description }} +{% endblock %} diff --git a/code/newsletter/N7/templates/project/__init__.py.jinja2 b/code/newsletter/N7/templates/project/__init__.py.jinja2 new file mode 100644 index 0000000..e69de29 diff --git a/code/newsletter/N7/templates/project/main.py.jinja2 b/code/newsletter/N7/templates/project/main.py.jinja2 new file mode 100644 index 0000000..2db12a4 --- /dev/null +++ b/code/newsletter/N7/templates/project/main.py.jinja2 @@ -0,0 +1,18 @@ +import uvicorn +from fastapi import FastAPI + +from {{ app_name }}.views import router + +app = FastAPI() + + +@app.get("/") +async def index(): + return {"msg": "index"} + + +app.include_router(router) + + +if __name__ == '__main__': + uvicorn.run(app) diff --git a/code/newsletter/N7/templates/project/views.py.jinja2 b/code/newsletter/N7/templates/project/views.py.jinja2 new file mode 100644 index 0000000..2ebd167 --- /dev/null +++ b/code/newsletter/N7/templates/project/views.py.jinja2 @@ -0,0 +1,8 @@ +from fastapi import APIRouter + +router = APIRouter(prefix="/{{ app_name }}/api") + + +@router.get("/") +async def index(): + return {"msg": "Hello, world"} diff --git a/code/newsletter/N7/templates/web/base.html b/code/newsletter/N7/templates/web/base.html new file mode 100644 index 0000000..1ba1483 --- /dev/null +++ b/code/newsletter/N7/templates/web/base.html @@ -0,0 +1,36 @@ + + +
+ + + +👋 Halo! Welcome to my website!
+ {% block body %}{% endblock %} +Life is short, You need Python!
+Users:
+| Id | +Name | +
|---|---|
| {{ user.id }} | +{{ user.name }} | +
Whoops! Do you not seem to add any user?
+ {% endif%} +