Remove RSVP

This commit is contained in:
Remi Rampin 2022-08-17 09:12:40 -04:00
parent fd18c064d9
commit e8fb2ef5c7
24 changed files with 102 additions and 735 deletions

35
france/.gitignore vendored
View File

@ -1,35 +0,0 @@
.env
# python
__pycache__
*.py[co]
.ipynb_checkpoints
# Unit test / coverage reports
.coverage
.tox
nosetests.xml
# Eclipse PyDev
.project
.pydevproject
# PyCharm
.idea
# ViM
.*.swp
# Emacs
\#*#
# OS files
.DS_Store
desktop.ini
# Archives
*.tar
*.tar.gz
*.tar.bz2
*.zip
*.whl

View File

@ -1,69 +0,0 @@
import logging
import random
import sys
from .database import get_db
ALPHABET = '0123456789bcdefghjkmnpqrstuvwxyz'
assert len(ALPHABET) == 32
LENGTH = 4
CORRECT = {
'i': '1',
'l': '1',
'o': '0',
}
def correct_code(code):
code = code.lower()
fixed_code = ''.join(CORRECT.get(c, c) for c in code)
return fixed_code
def list_errors(code):
for place in range(LENGTH):
for replacement in ALPHABET:
if replacement == code[place]:
continue
new_code = code[:place] + replacement + code[place + 1:]
yield new_code
def main():
logging.basicConfig(level=logging.INFO)
if len(sys.argv) <= 1:
number = 1
elif len(sys.argv) == 2:
number = int(sys.argv[1], 10)
else:
raise ValueError
# Get the current codes
with get_db() as db:
correct_codes = set(row[0] for row in db.execute(
'''\
SELECT code FROM families;
''',
))
# Augment them with possible errored codes
errored_codes = set()
for code in correct_codes:
errored_codes.update(list_errors(code))
assert len(errored_codes) == LENGTH * (len(ALPHABET) - 1) * len(correct_codes)
# Generate new codes
generated = 0
while generated < number:
code = ''.join(random.choice(ALPHABET) for _ in range(LENGTH))
if code in correct_codes or code in errored_codes:
continue
correct_codes.add(code)
errored_codes.update(list_errors(code))
print(code)
generated += 1

View File

@ -1,77 +0,0 @@
import contextlib
from datetime import datetime
import logging
import os
import sqlite3
logger = logging.getLogger(__name__)
DATABASE_FILE = os.environ['DATABASE']
assert os.path.isfile(DATABASE_FILE)
@contextlib.contextmanager
def get_db():
db = sqlite3.connect(DATABASE_FILE)
try:
yield db
finally:
db.close()
def get_name_and_replies(code):
with get_db() as db:
rows = db.execute(
'''\
WITH latest_reply AS (
SELECT
adults, children
FROM replies
WHERE family_code = :code
ORDER BY date DESC
LIMIT 1
)
SELECT
families.name,
(SELECT adults FROM latest_reply) AS adults,
(SELECT children FROM latest_reply) AS children
FROM families
WHERE families.code = :code
LIMIT 1;
''',
dict(code=code),
)
try:
return next(rows)
except StopIteration:
raise ValueError("Invalid code")
def record_reply(code, adults, children):
assert isinstance(adults, int)
assert isinstance(children, int)
assert 0 <= adults and 0 <= children
assert adults > 0 or children == 0
with get_db() as db:
# Insert update
cursor = db.cursor()
date = datetime.utcnow()
cursor.execute(
'''\
INSERT INTO replies(family_code, date, adults, children)
VALUES(:code, :date, :adults, :children);
''',
dict(code=code, date=date, adults=adults, children=children),
)
cursor.execute('COMMIT;')
logger.info(
"Recorded update for code=%r date=%r adults=%d children=%d",
code,
date,
adults,
children,
)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,36 +0,0 @@
{% extends "layout.html" %}
{% block title %}RSVP -{% endblock %}
{% block navitems %}
<li class="nav-item">
<a class="nav-link" href="{{ url_for('index') }}">Info</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="{{ url_for('form') }}">RSVP <span class="visually-hidden">(actuel)</span></a>
</li>
{% endblock %}
{% block content %}
{% if error %}
<p class="error text-danger">{{ error }}</p>
{% endif %}
<form action="{{ url_for('form') }}" method="POST">
<div class="row g-3 align-items-center">
<div class="col-auto">
<label for="code" class="col-form-label text-dark">Code sur l'invitation :</label>
</div>
<div class="col-auto">
<input type="text" name="code" id="code" class="form-control" placeholder="ABCD">
</div>
</div>
<button type="submit" value="RSVP" class="btn btn-primary btn-lg mt-3">RSVP</button>
</form>
{% endblock %}

View File

@ -1,93 +0,0 @@
{% extends "layout.html" %}
{% block navitems %}
<li class="nav-item">
<a class="nav-link active" href="#">Info <span class="visually-hidden">(actuel)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('form') }}">RSVP</a>
</li>
{% endblock %}
{% block content %}
<h1>Rémi &amp; Vicky renouvellent leurs voeux de mariage ! </h1>
<p class="text-dark">Rémi &amp; Vicky se sont mariés lors d'une petite cérémonie au Massachusetts le 30 janvier 2021. Exactement un an et demi plus tard, nous pouvons enfin venir en France pour célébrer avec tout le monde et renouveler nos voeux ! Nous espérons vous y voir.</p>
<a class="btn btn-primary btn-lg mb-3" href="{{ url_for('form') }}" role="button">RSVP <i class="bi bi-heart-arrow"></i></a>
<h4><i class="bi bi-geo-alt"></i> La Chapelle-Taillefert</h4>
<h4><i class="bi bi-calendar-heart"></i> 30 juillet 2022</h4>
<div class="container">
<div class="row">
<div class="col offset-sm-1 align-self-end">
<ul class="timeline-with-icons">
<li class="timeline-item mb-5">
<span class="timeline-icon">
<i class="bi bi-house-heart"></i>
</span>
<h4 class="fw-bold">Cérémonie en mairie</h4>
<p class="mb-2 fw-bold">11h</p>
<p class="text-muted mb-2 fw-bold">La Mairie de La Chapelle-Taillefert</p>
</li>
<li class="timeline-item mb-5">
<span class="timeline-icon">
<i class="bi bi-person-hearts"></i>
</span>
<h4 class="fw-bold">Vin d'honneur</h4>
<p class="mb-2 fw-bold">11h30</p>
</li>
<li class="timeline-item mb-5">
<span class="timeline-icon">
<i class="bi bi-egg-fried"></i>
</span>
<h4 class="fw-bold">Repas</h4>
<p class="mb-2 fw-bold">12h30</p>
<p class="text-muted mb-2 fw-bold">Salle des fêtes</p>
</li>
<li class="timeline-item mb-5">
<span class="timeline-icon">
<i class="bi bi-dribbble"></i>
</span>
<h4 class="fw-bold">Décontraction et pétanque</h4>
<p class="mb-2 fw-bold">16h00</p>
<p class="text-muted mb-2 fw-bold">Apportez vos boules de pétanques !</p>
</li>
<li class="timeline-item mb-5">
<span class="timeline-icon">
<i class="bi bi-balloon-heart"></i>
</span>
<h4 class="fw-bold">Apéro et BBQ</h4>
<p class="mb-2 fw-bold">19h30</p>
<p class="text-muted mb-2 fw-bold">Salle des fêtes</p>
</li>
<li class="timeline-item mb-5">
<span class="timeline-icon">
<i class="bi bi-speaker"></i>
</span>
<h4 class="fw-bold">Karaoké, musique et danse</h4>
<p class="mb-2 fw-bold">21h30</p>
<p class="text-muted mb-2 fw-bold">Salle des fêtes</p>
</li>
</ul>
</div>
</div>
</div>
{% endblock %}

View File

@ -1,38 +0,0 @@
<!doctype html>
<html lang="fr">
<head>
{% block head %}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{{ url_for('static', filename='/css/bootstrap.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='/css/bootstrap-icons.css') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='/css/custom.css') }}">
<title>{% block title %}{% endblock %} Rémi &amp; Vicky</title>
{% endblock %}
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<span class="navbar-text pe-3">Rémi &amp; Vicky</span>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button>
<div class="collapse navbar-collapse" id="navbarText">
<ul class="navbar-nav mr-auto">
{% block navitems %}{% endblock %}
</ul>
</div>
</div>
</nav>
<div id="content" class="container mt-2">
{% block content %}{% endblock %}
</div>
<div id="footer" class="mt-3">
<div class="text-center container mb-2 text-dark">En cas de problème, e-mailez-moi à <a href="mailto:remi@rampin.org">remi@rampin.org</a></div>
</div>
<script src="{{ url_for('static', filename='/js/bootstrap.bundle.js') }}"></script>
</body>
</html>

View File

@ -1,57 +0,0 @@
{% extends "layout.html" %}
{% block title %}RSVP -{% endblock %}
{% block navitems %}
<li class="nav-item">
<a class="nav-link" href="{{ url_for('index') }}">Info</a>
</li>
{% endblock %}
{% block content %}
{% if error %}
<p class="error">{{ error }}</p>
{% endif %}
<form action="" method="POST">
<div class="row g-3 align-items-center">
<div class="col-auto">
<label for="adults" class="col-form-label text-dark">Adultes :</label>
</div>
<div class="col-auto">
<input
type="number" class="form-control"
name="adults" id="adults"
min="1" max="5"
{% if adults is not none %}
value="{{ adults }}"
{% else %}
value="1"
{% endif %}
/>
</div>
</div>
<div class="row g-3 align-items-center">
<div class="col-auto">
<label for="children" class="col-form-label text-dark">Enfants :</label>
</div>
<div class="col-auto">
<input
type="number" class="form-control"
name="children" id="children"
min="0" max="5"
{% if children is not none %}
value="{{ children }}"
{% else %}
value="0"
{% endif %}
/>
</div>
</div>
<button type="submit" value="RSVP" class="btn btn-lg btn-primary mt-3">RSVP</button>
</form>
{% endblock %}

View File

@ -1,15 +0,0 @@
{% extends "layout.html" %}
{% block title %}MERCI -{% endblock %}
{% block navitems %}
<li class="nav-item">
<a class="nav-link" href="{{ url_for('index') }}">Info</a>
</li>
{% endblock %}
{% block content %}
<h1>Merci !</h1>
<p class="text-dark">Nous avons hâte de vous voir. Pour le programme et les adresses, voir <a href="{{ url_for('index') }}">la page d'info</a>.</p>
{% endblock %}

View File

@ -1,70 +0,0 @@
from flask import Flask, render_template, redirect, request, url_for
import logging
from .codes import correct_code
from .database import get_name_and_replies, record_reply
logger = logging.getLogger(__name__)
app = Flask('france_rsvp')
@app.route('/france/')
def index():
return render_template('index.html')
@app.route('/france/rsvp', methods=['GET', 'POST'])
def form():
error = None
if request.method == 'POST':
if (
'code' in request.form
and len(request.form['code']) == 4
):
code = correct_code(request.form['code'])
try:
get_name_and_replies(code)
except ValueError:
error = "Code invalide"
else:
return redirect(url_for('rsvp', code=code))
else:
error = "Code invalide"
return render_template('form.html', error=error)
@app.route('/france/thanks')
def thanks():
return render_template('thanks.html')
@app.route('/france/<code>', methods=['GET', 'POST'])
def rsvp(code):
# Lookup guests from code
adults = None
children = None
try:
name, adults, children = get_name_and_replies(code)
except ValueError:
return render_template('form.html', error="Code invalide")
error = None
if request.method == 'POST':
try:
adults = int(request.form['adults'], 10)
children = int(request.form['children'], 10)
except (KeyError, ValueError, OverflowError):
logger.warning("Invalid reply", exc_info=True)
error = "Nombres invalides"
else:
record_reply(code, adults, children)
return redirect(url_for('thanks'))
return render_template(
'rsvp.html',
adults=adults,
children=children,
error=error,
)

View File

Before

Width:  |  Height:  |  Size: 167 KiB

After

Width:  |  Height:  |  Size: 167 KiB

102
france/index.html Normal file
View File

@ -0,0 +1,102 @@
<!doctype html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/france/css/bootstrap.css">
<link rel="stylesheet" href="/france/css/bootstrap-icons.css">
<link rel="stylesheet" href="/france/css/custom.css">
<title>Rémi &amp; Vicky, France, 2022</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<span class="navbar-text pe-3">Rémi &amp; Vicky, France, 2022</span>
</div>
</nav>
<div id="content" class="container mt-2">
<h1>Rémi &amp; Vicky renouvellent leurs voeux de mariage ! </h1>
<p class="text-dark">Rémi &amp; Vicky se sont mariés lors d'une petite cérémonie au Massachusetts le 30 janvier 2021. Exactement un an et demi plus tard, nous avons pu enfin venir en France pour célébrer avec tout le monde et renouveler nos voeux ! Merci à tous ceux qui sont venus partager ce moment avec nous.</p>
<h4><i class="bi bi-geo-alt"></i> La Chapelle-Taillefert</h4>
<h4><i class="bi bi-calendar-heart"></i> 30 juillet 2022</h4>
<div class="container">
<div class="row">
<div class="col offset-sm-1 align-self-end">
<ul class="timeline-with-icons">
<li class="timeline-item mb-5">
<span class="timeline-icon">
<i class="bi bi-house-heart"></i>
</span>
<h4 class="fw-bold">Cérémonie en mairie</h4>
<p class="mb-2 fw-bold">11h</p>
<p class="text-muted mb-2 fw-bold">La Mairie de La Chapelle-Taillefert</p>
</li>
<li class="timeline-item mb-5">
<span class="timeline-icon">
<i class="bi bi-person-hearts"></i>
</span>
<h4 class="fw-bold">Vin d'honneur</h4>
<p class="mb-2 fw-bold">11h30</p>
</li>
<li class="timeline-item mb-5">
<span class="timeline-icon">
<i class="bi bi-egg-fried"></i>
</span>
<h4 class="fw-bold">Repas</h4>
<p class="mb-2 fw-bold">12h30</p>
<p class="text-muted mb-2 fw-bold">Salle des fêtes</p>
</li>
<li class="timeline-item mb-5">
<span class="timeline-icon">
<i class="bi bi-dribbble"></i>
</span>
<h4 class="fw-bold">Décontraction et pétanque</h4>
<p class="mb-2 fw-bold">16h00</p>
<p class="text-muted mb-2 fw-bold">Cap'tain Bernie !</p>
</li>
<li class="timeline-item mb-5">
<span class="timeline-icon">
<i class="bi bi-balloon-heart"></i>
</span>
<h4 class="fw-bold">Apéro et BBQ</h4>
<p class="mb-2 fw-bold">19h30</p>
<p class="text-muted mb-2 fw-bold">Salle des fêtes</p>
</li>
<li class="timeline-item mb-5">
<span class="timeline-icon">
<i class="bi bi-speaker"></i>
</span>
<h4 class="fw-bold">Karaoké, musique et danse</h4>
<p class="mb-2 fw-bold">21h30</p>
<p class="text-muted mb-2 fw-bold">Salle des fêtes</p>
</li>
</ul>
</div>
</div>
</div>
</div>
<script src="/france/js/bootstrap.bundle.js"></script>
</body>
</html>

201
france/poetry.lock generated
View File

@ -1,201 +0,0 @@
[[package]]
name = "click"
version = "8.1.3"
description = "Composable command line interface toolkit"
category = "main"
optional = false
python-versions = ">=3.7"
[package.dependencies]
colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]]
name = "colorama"
version = "0.4.4"
description = "Cross-platform colored terminal text."
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "flask"
version = "2.1.2"
description = "A simple framework for building complex web applications."
category = "main"
optional = false
python-versions = ">=3.7"
[package.dependencies]
click = ">=8.0"
importlib-metadata = {version = ">=3.6.0", markers = "python_version < \"3.10\""}
itsdangerous = ">=2.0"
Jinja2 = ">=3.0"
Werkzeug = ">=2.0"
[package.extras]
async = ["asgiref (>=3.2)"]
dotenv = ["python-dotenv"]
[[package]]
name = "importlib-metadata"
version = "4.11.3"
description = "Read metadata from Python packages"
category = "main"
optional = false
python-versions = ">=3.7"
[package.dependencies]
zipp = ">=0.5"
[package.extras]
docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"]
perf = ["ipython"]
testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)", "importlib-resources (>=1.3)"]
[[package]]
name = "itsdangerous"
version = "2.1.2"
description = "Safely pass data to untrusted environments and back."
category = "main"
optional = false
python-versions = ">=3.7"
[[package]]
name = "jinja2"
version = "3.1.2"
description = "A very fast and expressive template engine."
category = "main"
optional = false
python-versions = ">=3.7"
[package.dependencies]
MarkupSafe = ">=2.0"
[package.extras]
i18n = ["Babel (>=2.7)"]
[[package]]
name = "markupsafe"
version = "2.1.1"
description = "Safely add untrusted strings to HTML/XML markup."
category = "main"
optional = false
python-versions = ">=3.7"
[[package]]
name = "uwsgi"
version = "2.0.20"
description = "The uWSGI server"
category = "main"
optional = true
python-versions = "*"
[[package]]
name = "werkzeug"
version = "2.1.2"
description = "The comprehensive WSGI web application library."
category = "main"
optional = false
python-versions = ">=3.7"
[package.extras]
watchdog = ["watchdog"]
[[package]]
name = "zipp"
version = "3.8.0"
description = "Backport of pathlib-compatible object wrapper for zip files"
category = "main"
optional = false
python-versions = ">=3.7"
[package.extras]
docs = ["sphinx", "jaraco.packaging (>=9)", "rst.linker (>=1.9)"]
testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "jaraco.itertools", "func-timeout", "pytest-black (>=0.3.7)", "pytest-mypy (>=0.9.1)"]
[extras]
uwsgi = ["uWSGI"]
[metadata]
lock-version = "1.1"
python-versions = "^3.8"
content-hash = "22dc31ed2f24fc96f3cd412113fe05f63b85c9bbc73c92b74c8d4d915d3cd092"
[metadata.files]
click = [
{file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
{file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
]
colorama = [
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
]
flask = [
{file = "Flask-2.1.2-py3-none-any.whl", hash = "sha256:fad5b446feb0d6db6aec0c3184d16a8c1f6c3e464b511649c8918a9be100b4fe"},
{file = "Flask-2.1.2.tar.gz", hash = "sha256:315ded2ddf8a6281567edb27393010fe3406188bafbfe65a3339d5787d89e477"},
]
importlib-metadata = [
{file = "importlib_metadata-4.11.3-py3-none-any.whl", hash = "sha256:1208431ca90a8cca1a6b8af391bb53c1a2db74e5d1cef6ddced95d4b2062edc6"},
{file = "importlib_metadata-4.11.3.tar.gz", hash = "sha256:ea4c597ebf37142f827b8f39299579e31685c31d3a438b59f469406afd0f2539"},
]
itsdangerous = [
{file = "itsdangerous-2.1.2-py3-none-any.whl", hash = "sha256:2c2349112351b88699d8d4b6b075022c0808887cb7ad10069318a8b0bc88db44"},
{file = "itsdangerous-2.1.2.tar.gz", hash = "sha256:5dbbc68b317e5e42f327f9021763545dc3fc3bfe22e6deb96aaf1fc38874156a"},
]
jinja2 = [
{file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"},
{file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"},
]
markupsafe = [
{file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"},
{file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a"},
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e"},
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5"},
{file = "MarkupSafe-2.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4"},
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f"},
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e"},
{file = "MarkupSafe-2.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933"},
{file = "MarkupSafe-2.1.1-cp310-cp310-win32.whl", hash = "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6"},
{file = "MarkupSafe-2.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-win32.whl", hash = "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff"},
{file = "MarkupSafe-2.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a"},
{file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452"},
{file = "MarkupSafe-2.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003"},
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1"},
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601"},
{file = "MarkupSafe-2.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925"},
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f"},
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88"},
{file = "MarkupSafe-2.1.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63"},
{file = "MarkupSafe-2.1.1-cp38-cp38-win32.whl", hash = "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1"},
{file = "MarkupSafe-2.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7"},
{file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a"},
{file = "MarkupSafe-2.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f"},
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6"},
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77"},
{file = "MarkupSafe-2.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603"},
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7"},
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135"},
{file = "MarkupSafe-2.1.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96"},
{file = "MarkupSafe-2.1.1-cp39-cp39-win32.whl", hash = "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c"},
{file = "MarkupSafe-2.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247"},
{file = "MarkupSafe-2.1.1.tar.gz", hash = "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b"},
]
uwsgi = [
{file = "uwsgi-2.0.20.tar.gz", hash = "sha256:88ab9867d8973d8ae84719cf233b7dafc54326fcaec89683c3f9f77c002cdff9"},
]
werkzeug = [
{file = "Werkzeug-2.1.2-py3-none-any.whl", hash = "sha256:72a4b735692dd3135217911cbeaa1be5fa3f62bffb8745c5215420a03dc55255"},
{file = "Werkzeug-2.1.2.tar.gz", hash = "sha256:1ce08e8093ed67d638d63879fd1ba3735817f7a80de3674d293f5984f25fb6e6"},
]
zipp = [
{file = "zipp-3.8.0-py3-none-any.whl", hash = "sha256:c4f6e5bbf48e74f7a38e7cc5b0480ff42b0ae5178957d564d18932525d5cf099"},
{file = "zipp-3.8.0.tar.gz", hash = "sha256:56bf8aadb83c24db6c4b577e13de374ccfb67da2078beba1d037c17980bf43ad"},
]

View File

@ -1,23 +0,0 @@
[tool.poetry]
name = "france-rsvp"
version = "1.0.0"
description = ""
authors = ["Remi Rampin <remi@rampin.org>"]
[tool.poetry.dependencies]
python = "^3.8"
Flask = "^2.1.2"
uWSGI = {version = "*", optional = true}
[tool.poetry.extras]
uwsgi = ["uWSGI"]
[tool.poetry.dev-dependencies]
[tool.poetry.scripts]
generate-codes = "france_rsvp.codes:main"
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"

View File

@ -1,12 +0,0 @@
CREATE TABLE families(
code VARCHAR(8) PRIMARY KEY,
name TEXT
);
CREATE TABLE replies(
family_code VARCHAR(8) NOT NULL,
date DATETIME NOT NULL,
adults INTEGER NOT NULL,
children INTEGER NOT NULL,
FOREIGN KEY(family_code) REFERENCES families(code)
);

View File

@ -1,9 +0,0 @@
INSERT INTO families(code, name) VALUES
('bbbb', 'one'),
('cccc', 'two'),
('dddd', 'three');
INSERT INTO replies(family_code, date, adults, children) VALUES
('bbbb', '2022-05-10 20:37:39', 2, 0),
('bbbb', '2022-05-10 23:55:55', 0, 0),
('cccc', '2022-05-10 20:22:11', 2, 1);