Merge branch 'develop' into 'master'

Merge 'Develop' into master

See merge request sahkoinsinoorikilta/vtmk/web2.0-backend!64
This commit is contained in:
Ilari Ojakorpi
2022-07-06 19:50:50 +00:00
28 changed files with 280 additions and 111 deletions
+10
View File
@@ -0,0 +1,10 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
- id: trailing-whitespace
- repo: https://github.com/psf/black
rev: 22.3.0
hooks:
- id: black
language_version: python3.9
+1 -1
View File
@@ -3,7 +3,7 @@ body {
} }
#header:after { #header:after {
content: " "; content: " ";
display: block; display: block;
clear: both; clear: both;
} }
+2 -2
View File
@@ -12,7 +12,7 @@ body {
.event { .event {
font-size: 100px; font-size: 100px;
font-weight: bold; font-weight: bold;
margin-left: 20px; margin-left: 20px;
} }
.event-col{ .event-col{
padding-top:1vh; padding-top:1vh;
@@ -21,7 +21,7 @@ body {
.header-row{ .header-row{
margin: 30px; margin: 30px;
margin-left: 20px; margin-left: 20px;
font-size: 130px; font-size: 130px;
padding-bottom:20px; padding-bottom:20px;
color:#24a05f; color:#24a05f;
@@ -1,8 +1,8 @@
#infocontent { #infocontent {
width: 100%; width: 100%;
height: 100%; height: 100%;
position: fixed; position: fixed;
left: 0px; left: 0px;
top: 0px; top: 0px;
z-index: -1; /* Ensure div tag stays behind content; -999 might work, too. */ z-index: -1; /* Ensure div tag stays behind content; -999 might work, too. */
} }
+3 -3
View File
@@ -31,10 +31,10 @@
max-height 200px; max-height 200px;
} }
#sossoimage { #sossoimage {
height:300px; height:300px;
position: relative; position: relative;
left: 0px; left: 0px;
top: 0px; top: 0px;
} }
@@ -1,5 +1,5 @@
<link rel="stylesheet" href="/static/infoscreen/css/events.css"> <link rel="stylesheet" href="/static/infoscreen/css/events.css">
<link href="https://fonts.googleapis.com/css?family=Droid+Sans+Mono" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Droid+Sans+Mono" rel="stylesheet">
<div class="container" ng-app="myApp" ng-controller="EventController"> <div class="container" ng-app="myApp" ng-controller="EventController">
<div class="header-row row"> <div class="header-row row">
<div class="col-sm-6">Tapahtuma</div> <div class="col-sm-6">Tapahtuma</div>
+1 -1
View File
@@ -26,7 +26,7 @@
<div class="col"> <div class="col">
<div class="rotation-title-row"> <div class="rotation-title-row">
<h2>{% trans "Rotation" %}: {$ selected_rot.name $}</h2> <h2>{% trans "Rotation" %}: {$ selected_rot.name $}</h2>
<a class="btn btn-primary" href="/infoscreen/{$ selected_rot.id $}">{% trans "Preview" %}</a> <a class="btn btn-primary" href="/infoscreen/{$ selected_rot.id $}">{% trans "Preview" %}</a>
</div> </div>
<div>{% trans "Instances in currently selected rotation" %}:</div> <div>{% trans "Instances in currently selected rotation" %}:</div>
<table class="table table-striped"> <table class="table table-striped">
+1 -1
View File
@@ -18,7 +18,7 @@
<h4>{% trans "Non-board applications" %}</h4> <h4>{% trans "Non-board applications" %}</h4>
{{ non_board_table|safe }} {{ non_board_table|safe }}
</div> </div>
<div> <div>
<a href="/kaehmy" class="btn btn-primary">{% trans "Front page" %}</a> <a href="/kaehmy" class="btn btn-primary">{% trans "Front page" %}</a>
</div> </div>
+10 -10
View File
@@ -11,11 +11,11 @@
<script> <script>
function commentOn(id, op) { function commentOn(id, op) {
setTimeout(function() { setTimeout(function() {
document.getElementById("commentNameField").focus(); document.getElementById("commentNameField").focus();
}, 50); }, 50);
document.getElementById("collapse_add_comment").scrollIntoView(); document.getElementById("collapse_add_comment").scrollIntoView();
document.getElementById("commentOP").innerHTML = op; document.getElementById("commentOP").innerHTML = op;
document.getElementById("commentId").value = id; document.getElementById("commentId").value = id;
} }
</script> </script>
@@ -24,7 +24,7 @@
<h2 style="padding-top: 1rem">{% trans "All kaehmys" %}</h2> <h2 style="padding-top: 1rem">{% trans "All kaehmys" %}</h2>
</div> </div>
<div class="collapse" id="collapse_add_comment"> <div class="collapse" id="collapse_add_comment">
<div class="card"> <div class="card">
<div class="card-block"> <div class="card-block">
<form method="POST" action="/kaehmy/add_comment" class="form">{% csrf_token %} <form method="POST" action="/kaehmy/add_comment" class="form">{% csrf_token %}
@@ -69,18 +69,18 @@
<div> <div>
<h6 style="padding-bottom: 1rem">{% trans "Total kaehmys:" %} {{ application_count }}</h6> <h6 style="padding-bottom: 1rem">{% trans "Total kaehmys:" %} {{ application_count }}</h6>
</div> </div>
{% for application in applications %} {% for application in applications %}
<div class="card"> <div class="card">
<h4 class="card-header">{{ application.name }}</h4> <h4 class="card-header">{{ application.name }}</h4>
<div class="card-block"> <div class="card-block">
{% if application.board_roles|length > 0 %} {% if application.board_roles|length > 0 %}
<h5 style="padding-bottom: 1rem" class="card-subtitle mb-2 text-muted">{{ application.board_roles }}</h5> <h5 style="padding-bottom: 1rem" class="card-subtitle mb-2 text-muted">{{ application.board_roles }}</h5>
{% endif %} {% endif %}
{% if application.official_roles|length > 0 %} {% if application.official_roles|length > 0 %}
<h5 style="padding-bottom: 1rem" class="card-subtitle mb-2 text-muted">{{ application.official_roles }}</h5> <h5 style="padding-bottom: 1rem" class="card-subtitle mb-2 text-muted">{{ application.official_roles }}</h5>
{% endif %} {% endif %}
<p class="card-text">{{ application.text|linebreaks|urlize }}</p> <p class="card-text">{{ application.text|linebreaks|urlize }}</p>
{% if application.comment_count > 0 %} {% if application.comment_count > 0 %}
@@ -95,7 +95,7 @@
</a> </a>
</div> </div>
<div class="collapse" id="collapse_{{ application.id }}"> <div class="collapse" id="collapse_{{ application.id }}">
{% for message in application.messages.all %} {% for message in application.messages.all %}
{% include "kaehmy:message.html" with messages=message.messages.all %} {% include "kaehmy:message.html" with messages=message.messages.all %}
{% endfor %} {% endfor %}
+1 -1
View File
@@ -16,6 +16,6 @@
{% include "message.html" with messages=message.messages.all %} {% include "message.html" with messages=message.messages.all %}
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
</div> </div>
+3 -3
View File
@@ -10,12 +10,12 @@
{% block content %} {% block content %}
<div> <div>
<div> <div>
<h2 style="padding-top: 1rem">{% trans "Statistics" %}</h2> <h2 style="padding-top: 1rem">{% trans "Statistics" %}</h2>
</div> </div>
<div style="margin-top: 1rem" class="card"> <div style="margin-top: 1rem" class="card">
<div class="card-header"> <div class="card-header">
<h5>{% trans "Total kaehmys:" %} {{ application_count }}</h5> <h5>{% trans "Total kaehmys:" %} {{ application_count }}</h5>
</div> </div>
<div class="card-block"> <div class="card-block">
{% for role in role_list %} {% for role in role_list %}
@@ -25,6 +25,6 @@
{% endfor %} {% endfor %}
</div> </div>
</div> </div>
</div> </div>
{% endblock content %} {% endblock content %}
+1 -1
View File
@@ -11,7 +11,7 @@
<div id="input_form"> <div id="input_form">
<form name="applicationForm" action="/members/accept_application" method="post" class="form">{% csrf_token %} <form name="applicationForm" action="/members/accept_application" method="post" class="form">{% csrf_token %}
<input type="hidden" name="id" value="{{ application_id }}"> <input type="hidden" name="id" value="{{ application_id }}">
{% bootstrap_form form %} {% bootstrap_form form %}
{% buttons %} {% buttons %}
<button type="submit" class="btn btn-primary"> <button type="submit" class="btn btn-primary">
+1 -1
View File
@@ -17,7 +17,7 @@
{{ table|safe }} {{ table|safe }}
<div> <div>
<a href="/members/export_applications" class="btn btn-info">{% trans "Download Excel" %}</a> <a href="/members/export_applications" class="btn btn-info">{% trans "Download Excel" %}</a>
</div> </div>
</div> </div>
@@ -1,11 +1,15 @@
{% load i18n %} {% load i18n %}
{% trans "Moi" %} {{ first_name }}!
{% trans "Onnittelut! Sinut on hyväksytty Sähköinsinöörikillan jäseneksi." %} <p>Moi {{first_name}}!</p>
{% trans "Käy kurkkaamassa killan nettisivuilta" %} (https://sahkoinsinoorikilta.fi) {% trans "tulevia tapahtumia ja piipahda kiltahuoneella tutustumassa uusiin kiltatovereihisi!" %} <p>Onnittelut! Sinut on hyväksytty Sähköinsinöörikillan jäseneksi.</p>
<p>
Käy kurkkaamassa killan
<a href="https://sahkoinsinoorikilta.fi">nettisivuilta</a>
tulevia tapahtumia ja piipahda kiltahuoneella tutustumassa uusiin kiltatovereihisi!
</p>
{% trans "Liity myös killan TG-kanaville" %}: <p>Liity myös killan TG-kanaville:</p>
{% trans "SIK" %}: https://t.me/+ubTeGSYKTvg3NmVk <p><a href="https://t.me/+ubTeGSYKTvg3NmVk">Killan yleinen telegram</a></p>
{% trans "SIK-fuksit 2022" %}: https://t.me/+1PqQHRVMjiAxMTU0 <p><a href="https://t.me/+1PqQHRVMjiAxMTU0">SIK-fuksit 2022</a></p>
{% trans "SIK-fuksit 2022 -tiedotuskanava" %}: https://t.me/+Ln8TvQ-_id9kZTU0 <p><a href="https://t.me/+Ln8TvQ-_id9kZTU0">SIK-fuksit 2022 -tiedotuskanava</a></p>
+5 -5
View File
@@ -11,7 +11,7 @@
<div> <div>
<p> <p>
{% blocktrans %} {% blocktrans %}
Enter member information in CSV format, separate members on separate lines. Enter member information in CSV format, separate members on separate lines.
If a new member already exists in the database, a new payment event will be created for that member instead. If a new member already exists in the database, a new payment event will be created for that member instead.
{% endblocktrans %} {% endblocktrans %}
</p> </p>
@@ -20,7 +20,7 @@
<div> <div>
<label>{% trans "Format the member table like this:" %}</label> <label>{% trans "Format the member table like this:" %}</label>
<div> <div>
<img src="{% static "members/img/excel_csv_save_example.png" %}"> <img src="{% static "members/img/excel_csv_save_example.png" %}">
</div> </div>
<p>{% blocktrans %}Columns: First name, last name, email address, place of origin, AYY member, JAS recipient{% endblocktrans %}</p> <p>{% blocktrans %}Columns: First name, last name, email address, place of origin, AYY member, JAS recipient{% endblocktrans %}</p>
</div> </div>
@@ -28,10 +28,10 @@
<label>{% trans "Save the file as CSV" %}</label> <label>{% trans "Save the file as CSV" %}</label>
<div><img src="{% static "members/img/excel_csv_save_tutorial.png" %}"></div> <div><img src="{% static "members/img/excel_csv_save_tutorial.png" %}"></div>
</div> </div>
<form name="memberTextForm" action="/members/import_csv" enctype="multipart/form-data" method="POST">{% csrf_token %} <form name="memberTextForm" action="/members/import_csv" enctype="multipart/form-data" method="POST">{% csrf_token %}
<h3>{% trans "Upload file" %}</h3> <h3>{% trans "Upload file" %}</h3>
<input class="form-control-file" type="file" accept=".csv" name="csvFile" /> <input class="form-control-file" type="file" accept=".csv" name="csvFile" />
<div class="form-group"> <div class="form-group">
<label>{% trans "Payment source" %}</label> <label>{% trans "Payment source" %}</label>
@@ -42,7 +42,7 @@
</select> </select>
<small class="form-text text-muted"> <small class="form-text text-muted">
{% trans "This payment source will be used to create any payments for new members that already exist in the database." %} {% trans "This payment source will be used to create any payments for new members that already exist in the database." %}
</small> </small>
</div> </div>
<div class="form-group"> <div class="form-group">
<label>{% trans "CSV delimiter" %}</label> <label>{% trans "CSV delimiter" %}</label>
+1 -1
View File
@@ -41,7 +41,7 @@
{{ table|safe }} {{ table|safe }}
<div> <div>
<a href="/members/export_members" class="btn btn-info">{% trans "Download Excel" %}</a> <a href="/members/export_members" class="btn btn-info">{% trans "Download Excel" %}</a>
</div> </div>
</div> </div>
{% endblock content %} {% endblock content %}
+1 -1
View File
@@ -38,7 +38,7 @@
{{ table|safe }} {{ table|safe }}
<div> <div>
<a href="/members/export_payments" class="btn btn-info">{% trans "Download Excel" %}</a> <a href="/members/export_payments" class="btn btn-info">{% trans "Download Excel" %}</a>
</div> </div>
</div> </div>
{% endblock content %} {% endblock content %}
+1 -1
View File
@@ -5,6 +5,6 @@
<h3>{{ header }}</h3> <h3>{{ header }}</h3>
<form method="POST" action="/members/import_excel" enctype="multipart/form-data">{% csrf_token %} <form method="POST" action="/members/import_excel" enctype="multipart/form-data">{% csrf_token %}
{{ form }} {{ form }}
<input type="submit" class="btn btn-primary"> <input type="submit" class="btn btn-primary">
</form> </form>
{% endblock %} {% endblock %}
+1 -1
View File
@@ -104,7 +104,7 @@ def application_accept(request, *args, **kwargs):
"members:email_application_accept.html", "members:email_application_accept.html",
{"first_name": application.first_name}, {"first_name": application.first_name},
) )
send_email(member.email, subject, message) send_email(member.email, subject, message, True)
return HttpResponseRedirect( return HttpResponseRedirect(
"/members/list?notification={}".format(html.escape(notification)) "/members/list?notification={}".format(html.escape(notification))
+1 -1
View File
@@ -14,7 +14,7 @@
{% for challenge in challenges %} {% for challenge in challenges %}
<div class="card"> <div class="card">
<h4 class="card-header">{{ challenge.challenger }} vs. {{ challenge.victim }}</h4> <h4 class="card-header">{{ challenge.challenger }} vs. {{ challenge.victim }}</h4>
<div class="card-block"> <div class="card-block">
<h5 class="card-subtitle mb-2">{{ challenge.get_series_display }}</h5> <h5 class="card-subtitle mb-2">{{ challenge.get_series_display }}</h5>
<p class="card-text">{{ challenge.message|linebreaks|urlize }}</p> <p class="card-text">{{ challenge.message|linebreaks|urlize }}</p>
Generated
+155 -35
View File
@@ -14,7 +14,7 @@ tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>
[[package]] [[package]]
name = "babel" name = "babel"
version = "2.10.1" version = "2.10.3"
description = "Internationalization utilities" description = "Internationalization utilities"
category = "main" category = "main"
optional = false optional = false
@@ -47,11 +47,19 @@ uvloop = ["uvloop (>=0.15.2)"]
[[package]] [[package]]
name = "certifi" name = "certifi"
version = "2022.5.18" version = "2022.6.15"
description = "Python package for providing Mozilla's CA Bundle." description = "Python package for providing Mozilla's CA Bundle."
category = "main" category = "main"
optional = false optional = false
python-versions = ">=3.5" python-versions = ">=3.6"
[[package]]
name = "cfgv"
version = "3.3.1"
description = "Validate configuration and produce human readable error messages."
category = "main"
optional = false
python-versions = ">=3.6.1"
[[package]] [[package]]
name = "charset-normalizer" name = "charset-normalizer"
@@ -77,7 +85,7 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""}
[[package]] [[package]]
name = "colorama" name = "colorama"
version = "0.4.4" version = "0.4.5"
description = "Cross-platform colored terminal text." description = "Cross-platform colored terminal text."
category = "dev" category = "dev"
optional = false optional = false
@@ -110,6 +118,14 @@ category = "main"
optional = false optional = false
python-versions = ">=2.7" python-versions = ">=2.7"
[[package]]
name = "distlib"
version = "0.3.4"
description = "Distribution utilities"
category = "main"
optional = false
python-versions = "*"
[[package]] [[package]]
name = "django" name = "django"
version = "2.2.28" version = "2.2.28"
@@ -303,15 +319,24 @@ django = ">=2.2"
pytz = "*" pytz = "*"
[[package]] [[package]]
name = "djangorestframework-jwt" name = "djangorestframework-simplejwt"
version = "1.11.0" version = "5.2.0"
description = "JSON Web Token based authentication for Django REST framework" description = "A minimal JSON Web Token authentication plugin for Django REST Framework"
category = "main" category = "main"
optional = false optional = false
python-versions = "*" python-versions = ">=3.7"
[package.dependencies] [package.dependencies]
PyJWT = ">=1.5.2,<2.0.0" django = "*"
djangorestframework = "*"
pyjwt = ">=1.7.1,<3"
[package.extras]
dev = ["pytest-watch", "wheel", "twine", "ipython", "cryptography", "pytest-cov", "pytest-django", "pytest-xdist", "pytest", "tox", "flake8", "pep8", "isort", "Sphinx (>=1.6.5,<2)", "sphinx-rtd-theme (>=0.1.9)", "python-jose (==3.3.0)"]
doc = ["Sphinx (>=1.6.5,<2)", "sphinx-rtd-theme (>=0.1.9)"]
lint = ["flake8", "pep8", "isort"]
python-jose = ["python-jose (==3.3.0)"]
test = ["cryptography", "pytest-cov", "pytest-django", "pytest-xdist", "pytest", "tox"]
[[package]] [[package]]
name = "dparse" name = "dparse"
@@ -337,6 +362,18 @@ category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
[[package]]
name = "filelock"
version = "3.7.1"
description = "A platform independent file lock."
category = "main"
optional = false
python-versions = ">=3.7"
[package.extras]
docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"]
testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"]
[[package]] [[package]]
name = "gunicorn" name = "gunicorn"
version = "20.1.0" version = "20.1.0"
@@ -351,6 +388,17 @@ gevent = ["gevent (>=1.4.0)"]
setproctitle = ["setproctitle"] setproctitle = ["setproctitle"]
tornado = ["tornado (>=0.2)"] tornado = ["tornado (>=0.2)"]
[[package]]
name = "identify"
version = "2.5.1"
description = "File identification library for Python"
category = "main"
optional = false
python-versions = ">=3.7"
[package.extras]
license = ["ukkonen"]
[[package]] [[package]]
name = "idna" name = "idna"
version = "3.3" version = "3.3"
@@ -361,7 +409,7 @@ python-versions = ">=3.5"
[[package]] [[package]]
name = "importlib-metadata" name = "importlib-metadata"
version = "4.11.3" version = "4.11.4"
description = "Read metadata from Python packages" description = "Read metadata from Python packages"
category = "main" category = "main"
optional = false optional = false
@@ -430,6 +478,14 @@ category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
[[package]]
name = "nodeenv"
version = "1.7.0"
description = "Node.js virtual environment builder"
category = "main"
optional = false
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
[[package]] [[package]]
name = "nose" name = "nose"
version = "1.3.7" version = "1.3.7"
@@ -482,7 +538,7 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
[[package]] [[package]]
name = "phonenumbers" name = "phonenumbers"
version = "8.12.48" version = "8.12.50"
description = "Python version of Google's common library for parsing, formatting, storing and validating international phone numbers." description = "Python version of Google's common library for parsing, formatting, storing and validating international phone numbers."
category = "main" category = "main"
optional = false optional = false
@@ -504,7 +560,7 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa
name = "platformdirs" name = "platformdirs"
version = "2.5.2" version = "2.5.2"
description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
category = "dev" category = "main"
optional = false optional = false
python-versions = ">=3.7" python-versions = ">=3.7"
@@ -512,6 +568,22 @@ python-versions = ">=3.7"
docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"] docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)", "sphinx (>=4)"]
test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"] test = ["appdirs (==1.4.4)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)", "pytest (>=6)"]
[[package]]
name = "pre-commit"
version = "2.19.0"
description = "A framework for managing and maintaining multi-language pre-commit hooks."
category = "main"
optional = false
python-versions = ">=3.7"
[package.dependencies]
cfgv = ">=2.0.0"
identify = ">=1.0.0"
nodeenv = ">=0.11.1"
pyyaml = ">=5.1"
toml = "*"
virtualenv = ">=20.0.8"
[[package]] [[package]]
name = "psycopg2-binary" name = "psycopg2-binary"
version = "2.8.6" version = "2.8.6"
@@ -568,16 +640,17 @@ pyexcel-io = ">=0.5.3"
[[package]] [[package]]
name = "pyjwt" name = "pyjwt"
version = "1.7.1" version = "2.4.0"
description = "JSON Web Token implementation in Python" description = "JSON Web Token implementation in Python"
category = "main" category = "main"
optional = false optional = false
python-versions = "*" python-versions = ">=3.6"
[package.extras] [package.extras]
crypto = ["cryptography (>=1.4)"] crypto = ["cryptography (>=3.3.1)"]
flake8 = ["flake8", "flake8-import-order", "pep8-naming"] dev = ["sphinx", "sphinx-rtd-theme", "zope.interface", "cryptography (>=3.3.1)", "pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)", "mypy", "pre-commit"]
test = ["pytest (>=4.0.1,<5.0.0)", "pytest-cov (>=2.6.0,<3.0.0)", "pytest-runner (>=4.2,<5.0.0)"] docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"]
tests = ["pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)"]
[[package]] [[package]]
name = "pyparsing" name = "pyparsing"
@@ -640,7 +713,7 @@ python-versions = "*"
name = "pyyaml" name = "pyyaml"
version = "6.0" version = "6.0"
description = "YAML parser and emitter for Python" description = "YAML parser and emitter for Python"
category = "dev" category = "main"
optional = false optional = false
python-versions = ">=3.6" python-versions = ">=3.6"
@@ -772,7 +845,7 @@ python-versions = "*"
name = "toml" name = "toml"
version = "0.10.2" version = "0.10.2"
description = "Python Library for Tom's Obvious, Minimal Language" description = "Python Library for Tom's Obvious, Minimal Language"
category = "dev" category = "main"
optional = false optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
@@ -813,6 +886,24 @@ category = "main"
optional = false optional = false
python-versions = "*" python-versions = "*"
[[package]]
name = "virtualenv"
version = "20.15.1"
description = "Virtual Python Environment builder"
category = "main"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
[package.dependencies]
distlib = ">=0.3.1,<1"
filelock = ">=3.2,<4"
platformdirs = ">=2,<3"
six = ">=1.9.0,<2"
[package.extras]
docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"]
testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"]
[[package]] [[package]]
name = "whitenoise" name = "whitenoise"
version = "4.1.4" version = "4.1.4"
@@ -839,7 +930,7 @@ testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.9" python-versions = "^3.9"
content-hash = "737b7278d4803532c7b5aee8fa95cabba24a20c70467d58fde5ab6d63c796ecf" content-hash = "6ec0f461a5cc62edfc77f1b4e4f1b79647a86d9193d6492574ef6a44e15cc89b"
[metadata.files] [metadata.files]
attrs = [ attrs = [
@@ -847,8 +938,8 @@ attrs = [
{file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"},
] ]
babel = [ babel = [
{file = "Babel-2.10.1-py3-none-any.whl", hash = "sha256:3f349e85ad3154559ac4930c3918247d319f21910d5ce4b25d439ed8693b98d2"}, {file = "Babel-2.10.3-py3-none-any.whl", hash = "sha256:ff56f4892c1c4bf0d814575ea23471c230d544203c7748e8c68f0089478d48eb"},
{file = "Babel-2.10.1.tar.gz", hash = "sha256:98aeaca086133efb3e1e2aad0396987490c8425929ddbcfe0550184fdc54cd13"}, {file = "Babel-2.10.3.tar.gz", hash = "sha256:7614553711ee97490f732126dc077f8d0ae084ebc6a96e23db1482afabdb2c51"},
] ]
black = [ black = [
{file = "black-22.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09"}, {file = "black-22.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2497f9c2386572e28921fa8bec7be3e51de6801f7459dffd6e62492531c47e09"},
@@ -876,8 +967,12 @@ black = [
{file = "black-22.3.0.tar.gz", hash = "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79"}, {file = "black-22.3.0.tar.gz", hash = "sha256:35020b8886c022ced9282b51b5a875b6d1ab0c387b31a065b84db7c33085ca79"},
] ]
certifi = [ certifi = [
{file = "certifi-2022.5.18-py3-none-any.whl", hash = "sha256:8d15a5a7fde18536a249c49e07e8e462b8fc13de21b3c80e8a68315dfa227c99"}, {file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"},
{file = "certifi-2022.5.18.tar.gz", hash = "sha256:6ae10321df3e464305a46e997da41ea56c1d311fb9ff1dd4e04d6f14653ec63a"}, {file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"},
]
cfgv = [
{file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"},
{file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"},
] ]
charset-normalizer = [ charset-normalizer = [
{file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"}, {file = "charset-normalizer-2.0.12.tar.gz", hash = "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597"},
@@ -888,8 +983,8 @@ click = [
{file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"},
] ]
colorama = [ colorama = [
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"},
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"},
] ]
coverage = [ coverage = [
{file = "coverage-5.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf"}, {file = "coverage-5.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:b6d534e4b2ab35c9f93f46229363e17f63c53ad01330df9f2d6bd1187e5eaacf"},
@@ -953,6 +1048,10 @@ diff-match-patch = [
{file = "diff-match-patch-20200713.tar.gz", hash = "sha256:da6f5a01aa586df23dfc89f3827e1cafbb5420be9d87769eeb079ddfd9477a18"}, {file = "diff-match-patch-20200713.tar.gz", hash = "sha256:da6f5a01aa586df23dfc89f3827e1cafbb5420be9d87769eeb079ddfd9477a18"},
{file = "diff_match_patch-20200713-py3-none-any.whl", hash = "sha256:8bf9d9c4e059d917b5c6312bac0c137971a32815ddbda9c682b949f2986b4d34"}, {file = "diff_match_patch-20200713-py3-none-any.whl", hash = "sha256:8bf9d9c4e059d917b5c6312bac0c137971a32815ddbda9c682b949f2986b4d34"},
] ]
distlib = [
{file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"},
{file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"},
]
django = [ django = [
{file = "Django-2.2.28-py3-none-any.whl", hash = "sha256:365429d07c1336eb42ba15aa79f45e1c13a0b04d5c21569e7d596696418a6a45"}, {file = "Django-2.2.28-py3-none-any.whl", hash = "sha256:365429d07c1336eb42ba15aa79f45e1c13a0b04d5c21569e7d596696418a6a45"},
{file = "Django-2.2.28.tar.gz", hash = "sha256:0200b657afbf1bc08003845ddda053c7641b9b24951e52acd51f6abda33a7413"}, {file = "Django-2.2.28.tar.gz", hash = "sha256:0200b657afbf1bc08003845ddda053c7641b9b24951e52acd51f6abda33a7413"},
@@ -1012,9 +1111,9 @@ djangorestframework = [
{file = "djangorestframework-3.13.1-py3-none-any.whl", hash = "sha256:24c4bf58ed7e85d1fe4ba250ab2da926d263cd57d64b03e8dcef0ac683f8b1aa"}, {file = "djangorestframework-3.13.1-py3-none-any.whl", hash = "sha256:24c4bf58ed7e85d1fe4ba250ab2da926d263cd57d64b03e8dcef0ac683f8b1aa"},
{file = "djangorestframework-3.13.1.tar.gz", hash = "sha256:0c33407ce23acc68eca2a6e46424b008c9c02eceb8cf18581921d0092bc1f2ee"}, {file = "djangorestframework-3.13.1.tar.gz", hash = "sha256:0c33407ce23acc68eca2a6e46424b008c9c02eceb8cf18581921d0092bc1f2ee"},
] ]
djangorestframework-jwt = [ djangorestframework-simplejwt = [
{file = "djangorestframework-jwt-1.11.0.tar.gz", hash = "sha256:5efe33032f3a4518a300dc51a51c92145ad95fb6f4b272e5aa24701db67936a7"}, {file = "djangorestframework_simplejwt-5.2.0-py3-none-any.whl", hash = "sha256:bcc4cb74dcb637ca1e17eed35276bd618ab19491f8c53e65dee6271177c355e8"},
{file = "djangorestframework_jwt-1.11.0-py2.py3-none-any.whl", hash = "sha256:ab15dfbbe535eede8e2e53adaf52ef0cf018ee27dbfad10cbc4cbec2ab63d38c"}, {file = "djangorestframework_simplejwt-5.2.0.tar.gz", hash = "sha256:a60b09afb27d91ad1d7ac904cc632bd52cecead8f389f0fa1532ceb0fb757a74"},
] ]
dparse = [ dparse = [
{file = "dparse-0.5.1-py3-none-any.whl", hash = "sha256:e953a25e44ebb60a5c6efc2add4420c177f1d8404509da88da9729202f306994"}, {file = "dparse-0.5.1-py3-none-any.whl", hash = "sha256:e953a25e44ebb60a5c6efc2add4420c177f1d8404509da88da9729202f306994"},
@@ -1024,16 +1123,25 @@ et-xmlfile = [
{file = "et_xmlfile-1.1.0-py3-none-any.whl", hash = "sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada"}, {file = "et_xmlfile-1.1.0-py3-none-any.whl", hash = "sha256:a2ba85d1d6a74ef63837eed693bcb89c3f752169b0e3e7ae5b16ca5e1b3deada"},
{file = "et_xmlfile-1.1.0.tar.gz", hash = "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c"}, {file = "et_xmlfile-1.1.0.tar.gz", hash = "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c"},
] ]
filelock = [
{file = "filelock-3.7.1-py3-none-any.whl", hash = "sha256:37def7b658813cda163b56fc564cdc75e86d338246458c4c28ae84cabefa2404"},
{file = "filelock-3.7.1.tar.gz", hash = "sha256:3a0fd85166ad9dbab54c9aec96737b744106dc5f15c0b09a6744a445299fcf04"},
]
gunicorn = [ gunicorn = [
{file = "gunicorn-20.1.0-py3-none-any.whl", hash = "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e"},
{file = "gunicorn-20.1.0.tar.gz", hash = "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"}, {file = "gunicorn-20.1.0.tar.gz", hash = "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"},
] ]
identify = [
{file = "identify-2.5.1-py2.py3-none-any.whl", hash = "sha256:0dca2ea3e4381c435ef9c33ba100a78a9b40c0bab11189c7cf121f75815efeaa"},
{file = "identify-2.5.1.tar.gz", hash = "sha256:3d11b16f3fe19f52039fb7e39c9c884b21cb1b586988114fbe42671f03de3e82"},
]
idna = [ idna = [
{file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
{file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
] ]
importlib-metadata = [ importlib-metadata = [
{file = "importlib_metadata-4.11.3-py3-none-any.whl", hash = "sha256:1208431ca90a8cca1a6b8af391bb53c1a2db74e5d1cef6ddced95d4b2062edc6"}, {file = "importlib_metadata-4.11.4-py3-none-any.whl", hash = "sha256:c58c8eb8a762858f49e18436ff552e83914778e50e9d2f1660535ffb364552ec"},
{file = "importlib_metadata-4.11.3.tar.gz", hash = "sha256:ea4c597ebf37142f827b8f39299579e31685c31d3a438b59f469406afd0f2539"}, {file = "importlib_metadata-4.11.4.tar.gz", hash = "sha256:5d26852efe48c0a32b0509ffbc583fda1a2266545a78d104a6f4aff3db17d700"},
] ]
jdcal = [ jdcal = [
{file = "jdcal-1.4.1-py2.py3-none-any.whl", hash = "sha256:1abf1305fce18b4e8aa248cf8fe0c56ce2032392bc64bbd61b5dff2a19ec8bba"}, {file = "jdcal-1.4.1-py2.py3-none-any.whl", hash = "sha256:1abf1305fce18b4e8aa248cf8fe0c56ce2032392bc64bbd61b5dff2a19ec8bba"},
@@ -1055,6 +1163,10 @@ mypy-extensions = [
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
] ]
nodeenv = [
{file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"},
{file = "nodeenv-1.7.0.tar.gz", hash = "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b"},
]
nose = [ nose = [
{file = "nose-1.3.7-py2-none-any.whl", hash = "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a"}, {file = "nose-1.3.7-py2-none-any.whl", hash = "sha256:dadcddc0aefbf99eea214e0f1232b94f2fa9bd98fa8353711dacb112bfcbbb2a"},
{file = "nose-1.3.7-py3-none-any.whl", hash = "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac"}, {file = "nose-1.3.7-py3-none-any.whl", hash = "sha256:9ff7c6cc443f8c51994b34a667bbcf45afd6d945be7477b52e97516fd17c53ac"},
@@ -1075,8 +1187,8 @@ pathspec = [
{file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
] ]
phonenumbers = [ phonenumbers = [
{file = "phonenumbers-8.12.48-py2.py3-none-any.whl", hash = "sha256:429273b98966475d0c18ee293096eaf81c6b5727d0d55c7ba5ce9c60ec8c59ef"}, {file = "phonenumbers-8.12.50-py2.py3-none-any.whl", hash = "sha256:56713403b4160b59ea1fef4e842ddeb70931055146d794d371b60cd4b5f05fb8"},
{file = "phonenumbers-8.12.48.tar.gz", hash = "sha256:af0681fbfe9fa0721376ad9b729e772e5d20bf2cf50d9dd8ca2f0bdd78e9f0ce"}, {file = "phonenumbers-8.12.50.tar.gz", hash = "sha256:f00d67f20875804f4fade4803a9438294029982ac929c6ba303e1f0290cf5d45"},
] ]
pillow = [ pillow = [
{file = "Pillow-9.1.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:42dfefbef90eb67c10c45a73a9bc1599d4dac920f7dfcbf4ec6b80cb620757fe"}, {file = "Pillow-9.1.1-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:42dfefbef90eb67c10c45a73a9bc1599d4dac920f7dfcbf4ec6b80cb620757fe"},
@@ -1122,6 +1234,10 @@ platformdirs = [
{file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"},
{file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"},
] ]
pre-commit = [
{file = "pre_commit-2.19.0-py2.py3-none-any.whl", hash = "sha256:10c62741aa5704faea2ad69cb550ca78082efe5697d6f04e5710c3c229afdd10"},
{file = "pre_commit-2.19.0.tar.gz", hash = "sha256:4233a1e38621c87d9dda9808c6606d7e7ba0e087cd56d3fe03202a01d2919615"},
]
psycopg2-binary = [ psycopg2-binary = [
{file = "psycopg2-binary-2.8.6.tar.gz", hash = "sha256:11b9c0ebce097180129e422379b824ae21c8f2a6596b159c7659e2e5a00e1aa0"}, {file = "psycopg2-binary-2.8.6.tar.gz", hash = "sha256:11b9c0ebce097180129e422379b824ae21c8f2a6596b159c7659e2e5a00e1aa0"},
{file = "psycopg2_binary-2.8.6-cp27-cp27m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:d14b140a4439d816e3b1229a4a525df917d6ea22a0771a2a78332273fd9528a4"}, {file = "psycopg2_binary-2.8.6-cp27-cp27m-macosx_10_6_intel.macosx_10_9_intel.macosx_10_9_x86_64.macosx_10_10_intel.macosx_10_10_x86_64.whl", hash = "sha256:d14b140a4439d816e3b1229a4a525df917d6ea22a0771a2a78332273fd9528a4"},
@@ -1172,8 +1288,8 @@ pyexcel-xlsx = [
{file = "pyexcel_xlsx-0.5.8-py2.py3-none-any.whl", hash = "sha256:9bae2820c5767440d8a387695e0f8e8f73c97bcde0a5680c200ae82a2f6d5cc6"}, {file = "pyexcel_xlsx-0.5.8-py2.py3-none-any.whl", hash = "sha256:9bae2820c5767440d8a387695e0f8e8f73c97bcde0a5680c200ae82a2f6d5cc6"},
] ]
pyjwt = [ pyjwt = [
{file = "PyJWT-1.7.1-py2.py3-none-any.whl", hash = "sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e"}, {file = "PyJWT-2.4.0-py3-none-any.whl", hash = "sha256:72d1d253f32dbd4f5c88eaf1fdc62f3a19f676ccbadb9dbc5d07e951b2b26daf"},
{file = "PyJWT-1.7.1.tar.gz", hash = "sha256:8d59a976fb773f3e6a39c85636357c4f0e242707394cadadd9814f5cbaa20e96"}, {file = "PyJWT-2.4.0.tar.gz", hash = "sha256:d42908208c699b3b973cbeb01a969ba6a96c821eefb1c5bfe4c390c01d67abba"},
] ]
pyparsing = [ pyparsing = [
{file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"},
@@ -1308,6 +1424,10 @@ urllib3 = [
uwsgi = [ uwsgi = [
{file = "uwsgi-2.0.20.tar.gz", hash = "sha256:88ab9867d8973d8ae84719cf233b7dafc54326fcaec89683c3f9f77c002cdff9"}, {file = "uwsgi-2.0.20.tar.gz", hash = "sha256:88ab9867d8973d8ae84719cf233b7dafc54326fcaec89683c3f9f77c002cdff9"},
] ]
virtualenv = [
{file = "virtualenv-20.15.1-py2.py3-none-any.whl", hash = "sha256:b30aefac647e86af6d82bfc944c556f8f1a9c90427b2fb4e3bfbf338cb82becf"},
{file = "virtualenv-20.15.1.tar.gz", hash = "sha256:288171134a2ff3bfb1a2f54f119e77cd1b81c29fc1265a2356f3e8d14c7d58c4"},
]
whitenoise = [ whitenoise = [
{file = "whitenoise-4.1.4-py2.py3-none-any.whl", hash = "sha256:6dfea214b7c12efd689007abf9afa87a426586e9dbc051873ad2c8e535e2a1ac"}, {file = "whitenoise-4.1.4-py2.py3-none-any.whl", hash = "sha256:6dfea214b7c12efd689007abf9afa87a426586e9dbc051873ad2c8e535e2a1ac"},
{file = "whitenoise-4.1.4.tar.gz", hash = "sha256:22f79cf8f1f509639330f93886acaece8ec5ac5e9600c3b981d33c34e8a42dfd"}, {file = "whitenoise-4.1.4.tar.gz", hash = "sha256:22f79cf8f1f509639330f93886acaece8ec5ac5e9600c3b981d33c34e8a42dfd"},
+3 -2
View File
@@ -8,10 +8,9 @@ authors = ["Aarni Halinen aarni.halinen@sahkoinsinoorikilta.fi"]
python = "^3.9" python = "^3.9"
decorator = "^4.0.9" decorator = "^4.0.9"
Django = "^2.2.19" Django = "^2.2.19"
requests = "^2.11.1" requests = "2.27.1"
django-cors-headers = "^3.7.0" django-cors-headers = "^3.7.0"
djangorestframework = "^3.12.4" djangorestframework = "^3.12.4"
djangorestframework-jwt = "^1.11.0"
django-nose = "^1.4.5" django-nose = "^1.4.5"
psycopg2-binary = "2.8.6" psycopg2-binary = "2.8.6"
django-bootstrap3 = "^11.1.0" django-bootstrap3 = "^11.1.0"
@@ -38,6 +37,8 @@ sendgrid = "^6.7.0"
sentry-sdk = "^1.4.3" sentry-sdk = "^1.4.3"
django-polymorphic = "^3.1.0" django-polymorphic = "^3.1.0"
python-dotenv = "^0.20.0" python-dotenv = "^0.20.0"
djangorestframework-simplejwt = "^5.2.0"
pre-commit = "^2.19.0"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
coverage = "^5.5" coverage = "^5.5"
+2 -2
View File
@@ -3,8 +3,8 @@ CREATE USER sik WITH PASSWORD 'password123';
ALTER ROLE sik SET client_encoding TO 'utf8'; ALTER ROLE sik SET client_encoding TO 'utf8';
ALTER ROLE sik SET default_transaction_isolation TO 'read committed'; ALTER ROLE sik SET default_transaction_isolation TO 'read committed';
ALTER ROLE sik SET timezone TO 'UTC'; ALTER ROLE sik SET timezone TO 'UTC';
CREATE DATABASE sik CREATE DATABASE sik
ENCODING 'UTF8' ENCODING 'UTF8'
OWNER sik; OWNER sik;
GRANT ALL PRIVILEGES ON DATABASE sik TO sik; GRANT ALL PRIVILEGES ON DATABASE sik TO sik;
ALTER USER sik CREATEDB; ALTER USER sik CREATEDB;
+2 -2
View File
@@ -87,7 +87,7 @@ INSTALLED_APPS = [
"kaehmy", "kaehmy",
"ohlhafv", "ohlhafv",
"rest_framework", "rest_framework",
"rest_framework_jwt", "rest_framework_simplejwt",
"django_nose", "django_nose",
"bootstrap3", "bootstrap3",
"django_tables2", "django_tables2",
@@ -178,7 +178,7 @@ REST_FRAMEWORK = {
"rest_framework.permissions.IsAdminUser", "rest_framework.permissions.IsAdminUser",
), ),
"DEFAULT_AUTHENTICATION_CLASSES": ( "DEFAULT_AUTHENTICATION_CLASSES": (
"rest_framework_jwt.authentication.JSONWebTokenAuthentication", "rest_framework_simplejwt.authentication.JWTAuthentication",
), ),
# 'DEFAULT_THROTTLE_CLASSES': ( # 'DEFAULT_THROTTLE_CLASSES': (
# 'members.throttles.BurstRateThrottle', # 'members.throttles.BurstRateThrottle',
+29 -1
View File
@@ -14,6 +14,7 @@ from dotenv import load_dotenv
import sentry_sdk import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration from sentry_sdk.integrations.django import DjangoIntegration
from sikweb.base import * from sikweb.base import *
from datetime import timedelta
load_dotenv() # loads the configs from .env load_dotenv() # loads the configs from .env
@@ -61,7 +62,7 @@ DEFAULT_EMAIL_FROM = "SIK"
DEFAULT_EMAIL_FROM_ADDR = "noreply@sahkoinsinoorikilta.fi" DEFAULT_EMAIL_FROM_ADDR = "noreply@sahkoinsinoorikilta.fi"
ENABLE_AUTOMATIC_EMAILS = True ENABLE_AUTOMATIC_EMAILS = True
# Database settings # Database settingsfrom datetime import timedelta
# Only uncomment if default settings in base.py are not ok # Only uncomment if default settings in base.py are not ok
DB_OPTIONS = {"sslmode": "require"} if os.getenv("DB_SSL", False) == "True" else {} DB_OPTIONS = {"sslmode": "require"} if os.getenv("DB_SSL", False) == "True" else {}
@@ -77,3 +78,30 @@ DATABASES = {
"OPTIONS": DB_OPTIONS, "OPTIONS": DB_OPTIONS,
} }
} }
SIMPLE_JWT = {
"ACCESS_TOKEN_LIFETIME": timedelta(minutes=5),
"REFRESH_TOKEN_LIFETIME": timedelta(days=1),
"ROTATE_REFRESH_TOKENS": False,
"BLACKLIST_AFTER_ROTATION": False,
"UPDATE_LAST_LOGIN": False,
"ALGORITHM": "HS256",
"SIGNING_KEY": SECRET_KEY,
"VERIFYING_KEY": None,
"AUDIENCE": None,
"ISSUER": None,
"JWK_URL": None,
"LEEWAY": 0,
"AUTH_HEADER_TYPES": ("Bearer",),
"AUTH_HEADER_NAME": "HTTP_AUTHORIZATION",
"USER_ID_FIELD": "id",
"USER_ID_CLAIM": "user_id",
"USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule",
"AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",),
"TOKEN_TYPE_CLAIM": "token_type",
"TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser",
"JTI_CLAIM": "jti",
"SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp",
"SLIDING_TOKEN_LIFETIME": timedelta(minutes=5),
"SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1),
}
@@ -3475,19 +3475,19 @@
} }
while( (node = node.parentNode) && (node !== document.body) ); while( (node = node.parentNode) && (node !== document.body) );
}, },
disableMouseover: false, disableMouseover: false,
mouseover: function (evt){ mouseover: function (evt){
if (!flash.disableMouseover) { if (!flash.disableMouseover) {
var target = api.event.fix(evt).target; var target = api.event.fix(evt).target;
if( /input/i.test(target.nodeName) && target.type == 'file' && !target.disabled ){ if( /input/i.test(target.nodeName) && target.type == 'file' && !target.disabled ){
var var
state = target.getAttribute(_attr) state = target.getAttribute(_attr)
, wrapper = flash.getWrapper(target) , wrapper = flash.getWrapper(target)
; ;
if( api.multiFlash ){ if( api.multiFlash ){
// check state: // check state:
// i — published // i — published
@@ -3500,14 +3500,14 @@
else if( state != 'p' ){ else if( state != 'p' ){
// set "init" state // set "init" state
target.setAttribute(_attr, 'i'); target.setAttribute(_attr, 'i');
var dummy = document.createElement('div'); var dummy = document.createElement('div');
if( !wrapper ){ if( !wrapper ){
api.log('[err] FlashAPI.mouseover: js-fileapi-wrapper not found'); api.log('[err] FlashAPI.mouseover: js-fileapi-wrapper not found');
return; return;
} }
_css(dummy, { _css(dummy, {
top: 0 top: 0
, left: 0 , left: 0
@@ -3516,21 +3516,21 @@
, zIndex: 1e6+'' // set max zIndex , zIndex: 1e6+'' // set max zIndex
, position: 'absolute' , position: 'absolute'
}); });
wrapper.appendChild(dummy); wrapper.appendChild(dummy);
flash.publish(dummy, api.uid()); flash.publish(dummy, api.uid());
// set "publish" state // set "publish" state
target.setAttribute(_attr, 'p'); target.setAttribute(_attr, 'p');
} }
return true; return true;
} }
else if( wrapper ){ else if( wrapper ){
// Use one flash element // Use one flash element
var box = _getDimensions(wrapper); var box = _getDimensions(wrapper);
_css(flash.getEl(), box); _css(flash.getEl(), box);
// Set current input // Set current input
flash.curInp = target; flash.curInp = target;
} }
@@ -3543,7 +3543,7 @@
onEvent: function (evt){ onEvent: function (evt){
var type = evt.type; var type = evt.type;
if( type == 'ready' ){ if( type == 'ready' ){
try { try {
// set "ready" state // set "ready" state
@@ -3632,9 +3632,9 @@
_each(files, function (file){ _each(files, function (file){
api.checkFileObj(file); api.checkFileObj(file);
}); });
_files[uid] = files; _files[uid] = files;
if( document.createEvent ){ if( document.createEvent ){
event = document.createEvent('Event'); event = document.createEvent('Event');
event.files = files; event.files = files;
@@ -3664,7 +3664,7 @@
this.cmdFn(id, name, data, last); this.cmdFn(id, name, data, last);
} }
}, },
cmdFn: function(id, name, data, last) { cmdFn: function(id, name, data, last) {
try { try {
api.log('(js -> flash).'+name+':', data); api.log('(js -> flash).'+name+':', data);
@@ -3727,7 +3727,7 @@
callback(evt); callback(evt);
}); });
}, },
getFiles: function (input, filter, callback){ getFiles: function (input, filter, callback){
if( callback ){ if( callback ){
api.filterFiles(api.getFiles(input), filter, callback); api.filterFiles(api.getFiles(input), filter, callback);
@@ -4039,7 +4039,7 @@
} }
try { el.style[key] = val; } catch (e) {} try { el.style[key] = val; } catch (e) {}
} }
} }
} }
@@ -4161,7 +4161,7 @@
, body = document.body , body = document.body
, docEl = (el && el.ownerDocument).documentElement , docEl = (el && el.ownerDocument).documentElement
; ;
function getOffset(obj) { function getOffset(obj) {
var left, top; var left, top;
left = top = 0; left = top = 0;
@@ -4176,7 +4176,7 @@
top : top top : top
}; };
}; };
return { return {
top: getOffset(el).top top: getOffset(el).top
, left: getOffset(el).left , left: getOffset(el).left
+2 -2
View File
@@ -7,7 +7,7 @@
{% load static %} {% load static %}
<link rel="stylesheet" href="{% static "css/contact.css" %}"> <link rel="stylesheet" href="{% static "css/contact.css" %}">
<h2>{% trans "Contact" %}</h2> <h2>{% trans "Contact" %}</h2>
{% if committees %} {% if committees %}
{% for committee in committees %} {% for committee in committees %}
<!--Committee title--> <!--Committee title-->
@@ -23,7 +23,7 @@
<div class="row"> <div class="row">
<div class="col"> <div class="col">
<h5>{{role.name}}</h5> <h5>{{role.name}}</h5>
<p>{{official.first_name}} <p>{{official.first_name}}
{{official.last_name}} {{official.last_name}}
{{official.email}}</p> {{official.email}}</p>
</div> </div>
+9 -3
View File
@@ -1,8 +1,13 @@
"""Webapp urls.""" """Webapp urls."""
from django.conf.urls import url, include from django.conf.urls import url, include
from django.urls import path
from rest_framework import routers from rest_framework import routers
from rest_framework_jwt.views import obtain_jwt_token, verify_jwt_token from rest_framework_simplejwt.views import (
TokenObtainPairView,
TokenRefreshView,
TokenVerifyView,
)
from webapp.views import * from webapp.views import *
@@ -21,7 +26,8 @@ router.register(r"jobads", JobAdViewSet)
urlpatterns = [ urlpatterns = [
url(r"^api/", include(router.urls)), url(r"^api/", include(router.urls)),
url(r"^api/api-token-auth/", obtain_jwt_token), path(r"api/token/", TokenObtainPairView.as_view(), name="token_obtain_pair"),
url(r"^api/api-token-verify/", verify_jwt_token), path(r"api/token/verify/", TokenVerifyView.as_view(), name="token_verify"),
path(r"api/token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
url(r"^jwt_nginx", nginx_jwt_resp), url(r"^jwt_nginx", nginx_jwt_resp),
] ]