Compare commits

..

39 commits

Author SHA1 Message Date
2e5ecdf636 dev: update requirements and directly read the files 2023-05-19 15:23:25 +02:00
8c3914694c kfet/open: Add comment to test 2023-05-19 15:23:02 +02:00
533d4fdb2c dev: set explicitely DJANGO_SETTINGS_MODULE 2023-05-19 15:23:00 +02:00
50e59167ae kfet: remove redundant static tag 2023-05-19 15:22:36 +02:00
0568daca8d dev: update requirements 2023-05-19 15:22:35 +02:00
1fea8ed462 Remove useless migrations 2023-05-19 15:21:47 +02:00
59683ec59c Update django-hCaptcha 2023-05-19 15:21:46 +02:00
b37c9daecb assertDictContainsSubset is deprecated 2023-05-19 15:21:19 +02:00
68065c94ef Explicitely set transform=repr in assertQuerysetEquals 2023-05-19 15:21:19 +02:00
42bd1cde39 assertEquals is deprecated 2023-05-19 15:21:19 +02:00
e8143856f5 Use AutoField instead of BigAutoField 2023-05-19 15:21:19 +02:00
ce2182d99e url -> re_path 2023-05-19 15:21:19 +02:00
373aa32e43 Replace unique_together by UniqueConstraint 2023-05-19 15:21:19 +02:00
e6ea8f5675 Update changelog 2023-05-19 15:21:19 +02:00
031717b28b cof has been renamed to gestioasso 2023-05-19 15:21:19 +02:00
0aaa41a8f9 Fix typo 2023-05-19 15:21:19 +02:00
745360ec76 Only run kf tests in sequential mode (to fix issues with channels) 2023-05-19 15:21:19 +02:00
112332ea42 Try not running tests in parallel 2023-05-19 15:21:19 +02:00
260a819eb3 Try to flush old messages in tests 2023-05-19 15:21:19 +02:00
0e2a0fbc95 Update kfet.open tests 2023-05-19 15:21:19 +02:00
8c0f2a43bf Remove default_app_config 2023-05-19 15:21:19 +02:00
224eccc6f0 Update django-djconfig 2023-05-19 15:21:15 +02:00
8f223f6e83 Change backend name as the old one is deprecated 2023-05-19 15:20:44 +02:00
b8aa30a2e9 ugettext -> gettext 2023-05-19 15:20:44 +02:00
9dc049d04f Update redis, and implement a custom channel layer to send datetime/decimal objects 2023-05-19 15:20:44 +02:00
461ab6c7a1 Fix kfet.ope tests 2023-05-19 15:20:44 +02:00
8318af1fd3 Fix kpsul tests 2023-05-19 15:20:44 +02:00
279a3c1828 Simplify group_send for kpsul 2023-05-19 15:20:44 +02:00
9c06d46d58 Channels 3 2023-05-19 15:20:43 +02:00
a334241c4f Add default django asgi handler 2023-05-19 15:18:58 +02:00
9ab5d95c30 Fix app import 2023-05-19 15:18:58 +02:00
c927085a7e keyOrder is deprecated, using a list in Meta gives the correct order 2023-05-19 15:18:58 +02:00
40475a47c4 Update django-redis-cache and fix vagrant setup 2023-05-19 15:18:58 +02:00
a2ef251252 Update django version 2023-05-19 15:18:57 +02:00
89b01884d0 Update base consumers 2023-05-19 15:17:08 +02:00
9cc32f642a Add default http router 2023-05-19 15:17:08 +02:00
6a6d14fe6f Update daphne version 2023-05-19 15:17:08 +02:00
0cc035d903 Update to django channels 2 2023-05-19 15:17:05 +02:00
0065269af5 Fix vagrant setup w/ daphne 2023-05-19 15:15:19 +02:00
25 changed files with 43 additions and 336 deletions

View file

@ -30,29 +30,6 @@ adhérents ni des cotisations.
## Version ??? - ??/??/????
## Version 0.15.1 - 15/06/2023
### K-Fêt
- Rattrape les erreurs d'envoi de mail de négatif
- Utilise l'adresse chefs pour les envois de négatifs
## Version 0.15 - 22/05/2023
### K-Fêt
- Rajoute un formulaire de contact
- Rajoute un formulaire de demande de soirée
- Désactive les mails d'envoi de négatifs sur les comptes gelés
## Version 0.14 - 19/05/2023
- Répare les dépendances en spécifiant toutes les versions
### K-Fêt
- Répare la gestion des changement d'heure via moment.js
## Version 0.13 - 19/02/2023
### K-Fêt

View file

@ -205,9 +205,8 @@ MAIL_DATA = {
"REPLYTO": "cof@ens.fr",
},
"rappels": {"FROM": "Le BdA <bda@ens.fr>", "REPLYTO": "Le BdA <bda@ens.fr>"},
"kfet": {
"FROM": "La K-Fêt <chefs-k-fet@ens.fr>",
"REPLYTO": "La K-Fêt <chefs-k-fet@ens.fr>",
"rappel_negatif": {
"FROM": "La K-Fêt <k-fet@ens.fr>",
},
"revente": {
"FROM": "BdA-Revente <bda-revente@ens.fr>",

View file

@ -1,19 +0,0 @@
# Generated by Django 2.2.28 on 2023-05-22 09:01
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("gestioncof", "0018_petitscours_email"),
]
operations = [
migrations.AddField(
model_name="cofprofile",
name="date_adhesion",
field=models.DateField(
blank=True, null=True, verbose_name="Date d'adhésion"
),
),
]

View file

@ -50,7 +50,6 @@ class CofProfile(models.Model):
"Login clipper", max_length=32, blank=True, unique=True, null=True
)
is_cof = models.BooleanField("Membre du COF", default=False)
date_adhesion = models.DateField("Date d'adhésion", blank=True, null=True)
phone = models.CharField("Téléphone", max_length=20, blank=True)
occupation = models.CharField(
_("Occupation"),

View file

@ -1,5 +1,5 @@
import uuid
from datetime import date, timedelta
from datetime import timedelta
from django.contrib import messages
from django.contrib.auth import get_user_model
@ -486,7 +486,6 @@ class ExportMembersViewTests(CSVResponseMixin, ViewTestCaseMixin, TestCase):
u1.last_name = "last"
u1.email = "user@mail.net"
u1.save()
u1.profile.date_adhesion = date(2023, 5, 22)
u1.profile.phone = "0123456789"
u1.profile.departement = "Dept"
u1.profile.save()
@ -508,9 +507,8 @@ class ExportMembersViewTests(CSVResponseMixin, ViewTestCaseMixin, TestCase):
"1A",
"Dept",
"normalien",
"2023-05-22",
],
[str(u2.pk), "staff", "", "", "", "", "1A", "", "normalien", "None"],
[str(u2.pk), "staff", "", "", "", "", "1A", "", "normalien"],
],
)

View file

@ -1,6 +1,6 @@
import csv
import uuid
from datetime import date, timedelta
from datetime import timedelta
from smtplib import SMTPRecipientsRefused
from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
@ -86,7 +86,6 @@ class ResetComptes(BuroRequiredMixin, TemplateView):
nb_adherents = CofProfile.objects.filter(is_cof=True).count()
CofProfile.objects.update(
is_cof=False,
date_adhesion=None,
mailing_cof=False,
mailing_bda=False,
mailing_bda_revente=False,
@ -576,9 +575,6 @@ def registration(request):
profile = profile_form.save()
if profile.is_cof and not was_cof:
notify_new_member(request, member)
profile.date_adhesion = date.today()
profile.save()
# Enregistrement des inscriptions aux événements
for form in event_formset:
if "status" not in form.cleaned_data:
@ -719,7 +715,6 @@ def export_members(request):
profile.occupation,
profile.departement,
profile.type_cotiz,
profile.date_adhesion,
]
writer.writerow([str(bit) for bit in bits])

View file

@ -45,47 +45,6 @@ class DateTimeWidget(forms.DateTimeInput):
js = ("kfet/vendor/bootstrap/bootstrap-datetimepicker.min.js",)
class ContactForm(forms.Form):
from_email = forms.EmailField(
label="Adresse mail",
help_text="Si aucune adresse mail n'est renseignée, la soumission sera anonyme.",
required=False,
)
subject = forms.CharField(label="Objet", required=True)
message = forms.CharField(widget=forms.Textarea, required=True)
def clean_from_email(self):
return self.cleaned_data["from_email"] or "Anonyme <k-fet@ens.psl.eu>"
class DemandeSoireeForm(forms.Form):
HORAIRE_CHOICES = map(lambda s: (s, s), ("22h", "23h", "00h", "01h", "02h", "03h"))
SERVICE_CHOICES = (
("K-Fêt", "K-Fêt standard (L'équipe K-Fêt fait le service normal au bar)"),
("Kalô", "Type Kalô (Vous ramenez vos propres boissons et servez vous-mêmes)"),
)
nom = forms.CharField()
from_email = forms.EmailField(label="Adresse mail de contact")
contact_boum = forms.BooleanField(label="Contacter le Boum", required=False)
contact_pls = forms.BooleanField(label="Contacter PLS", required=False)
theme = forms.CharField(label="Thème de la soirée")
horaire_fin = forms.ChoiceField(label="Horaire de fin", choices=HORAIRE_CHOICES)
service = forms.ChoiceField(label="Mode de service", choices=SERVICE_CHOICES)
date = forms.CharField(label="Date souhaitée")
respo1 = forms.CharField(label="Nom de la personne respo n°1")
respo2 = forms.CharField(label="Nom de la personne respo n°2")
respo3 = forms.CharField(label="Nom de la personne respo n°3")
respo4 = forms.CharField(label="Nom de la personne respo n°4")
remarques = forms.CharField(
label="Remarques supplémentaires", widget=forms.Textarea
)
# -----
# Account forms
# -----

View file

@ -2,7 +2,6 @@
Gestion en ligne de commande des mails de rappel K-Fet.
"""
import smtplib
from datetime import timedelta
from django.core.management.base import BaseCommand
@ -11,14 +10,6 @@ from django.utils import timezone
from kfet.models import AccountNegative
def send_mail(neg: AccountNegative, stdout) -> None:
try:
neg.send_rappel()
stdout.write(f"Mail de rappel pour {neg.account} envoyé avec succès.")
except smtplib.SMTPException:
stdout.write(f"Erreur lors de l'envoi du mail de rappel pour {neg.account}.")
class Command(BaseCommand):
help = (
"Envoie un mail de rappel aux personnes en négatif.\n"
@ -35,9 +26,8 @@ class Command(BaseCommand):
# On n'envoie des mails qu'aux comptes qui ont un négatif vraiment actif
# et dont la balance est négative
# On ignore les comptes gelés qui signinfient une adresse mail plus valide
account_negatives = AccountNegative.objects.filter(
account__balance__lt=0, account__is_frozen=False
account__balance__lt=0
).exclude(end__lte=now)
accounts_first_mail = account_negatives.filter(
@ -48,10 +38,12 @@ class Command(BaseCommand):
)
for neg in accounts_first_mail:
send_mail(neg, self.stdout)
neg.send_rappel()
self.stdout.write(f"Mail de rappel pour {neg.account} envoyé avec succès.")
for neg in accounts_periodic_mail:
send_mail(neg, self.stdout)
neg.send_rappel()
self.stdout.write("Mail de rappel pour {neg.account} envoyé avec succès.")
if not (accounts_first_mail.exists() or accounts_periodic_mail.exists()):
self.stdout.write("Aucun mail à envoyer.")

View file

@ -2,8 +2,7 @@ import re
from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from django.core.mail import EmailMessage
from django.core.mail import send_mail
from django.core.validators import RegexValidator
from django.db import models, transaction
from django.db.models import F
@ -270,32 +269,6 @@ class Account(models.Model):
def __init__(self, trigramme):
self.trigramme = trigramme
def send_creation_email(self):
"""
Envoie un mail à la création du trigramme.
"""
mail_data = settings.MAIL_DATA["kfet"]
email = EmailMessage(
subject="Création d'un trigramme",
body=loader.render_to_string(
"kfet/mails/creation_trigramme.txt",
context={
"account": self,
"site": Site.objects.get_current(),
"url_read": reverse("kfet.account.read", args=(self.trigramme)),
"url_update": reverse("kfet.account.update", args=(self.trigramme)),
"url_delete": reverse("kfet.account.delete", args=(self.trigramme))
},
),
from_email=mail_data["FROM"],
to=[self.email],
reply_to=[mail_data["REPLYTO"]],
)
# On envoie le mail
email.send()
def get_deleted_account():
return Account.objects.get(trigramme=KFET_DELETED_TRIGRAMME)
@ -325,11 +298,10 @@ class AccountNegative(models.Model):
"""
Envoie un mail de rappel signalant que la personne est en négatif.
"""
mail_data = settings.MAIL_DATA["kfet"]
email = EmailMessage(
subject="Compte K-Psul négatif",
body=loader.render_to_string(
# On envoie le mail
send_mail(
"Compte K-Psul négatif",
loader.render_to_string(
"kfet/mails/rappel.txt",
context={
"account": self.account,
@ -337,17 +309,13 @@ class AccountNegative(models.Model):
"start_date": self.start,
},
),
from_email=mail_data["FROM"],
to=[self.account.email],
reply_to=[mail_data["REPLYTO"]],
settings.MAIL_DATA["rappel_negatif"]["FROM"],
[self.account.email],
)
# On envoie le mail
email.send()
# On enregistre le fait que l'envoi a bien eu lieu
self.last_rappel = timezone.now()
self.save()
return
class CheckoutQuerySet(models.QuerySet):

View file

@ -78,7 +78,7 @@ class KfetWebsocket {
listen() {
var that = this;
this.socket = new ReconnectingWebSocket(this.url, [], { minReconnectionDelay: 100 });
this.socket = new ReconnectingWebSocket(this.url);
this.socket.onmessage = function (e) {
var data = $.extend({}, that.default_msg, JSON.parse(e.data));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -8,7 +8,7 @@
<script type="text/javascript" src="{% url 'js_reverse' %}" ></script>
<script type="text/javascript" src="{% static 'kfet/vendor/moment/moment.min.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/vendor/moment/fr.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/vendor/moment/moment-timezone-with-data.min.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/vendor/moment/moment-timezone-with-data-2012-2022.min.js' %}"></script>
{% if account.user == request.user %}
<script type="text/javascript" src="{% static 'kfet/vendor/Chart.min.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/js/statistic.js' %}"></script>

View file

@ -1,13 +1,17 @@
{% load wagtailcore_tags %}
{% with "k-fet@ens.fr" as kfet_mail %}
<footer class="row">
<div class="footer">
<span>
<b><a href="{% url "kfet.contact" %}">Formulaire de contact</a></b>
<a href="{% slugurl "mentions-legales" %}">Mentions légales</a>
</span>
|
<span>
<a href="{% slugurl "mentions-legales" %}">Mentions légales</a>
En cas de pépin : <a href="mailto:{{ kfet_mail }}"><tt>{{ kfet_mail }}</tt></a>
</span>
</div>
</footer>
</div>
{% endwith %}

View file

@ -1,36 +0,0 @@
{% extends "kfet/base_form.html" %}
{% block extra_head %}
{{ negative_form.media }}
{% endblock %}
{% block title %}
Contacter la K-Fêt
{% endblock %}
{% block header-title %}
Contacter la K-Fêt
{% endblock %}
{% block footer %}
{% include "kfet/base_footer.html" %}
{% endblock %}
{% block main %}
<div class="messages">
<div class="alert alert-info">
<b>Votre message sera envoyé aux Chef·fe·s et aux Wo·men K-Fêt.</b>
</div>
</div>
<br>
<form action="" method="post" class="form-horizontal" autocomplete="off">
{% csrf_token %}
{% include 'kfet/form_snippet.html' %}
{% include 'kfet/form_submit_snippet.html' with value="Envoyer" %}
</form>
{% endblock %}

View file

@ -1,28 +0,0 @@
{% extends "kfet/base_form.html" %}
{% block extra_head %}
{{ negative_form.media }}
{% endblock %}
{% block title %}
Effectuer une demande de soirée
{% endblock %}
{% block header-title %}
Effectuer une demande de soirée
{% endblock %}
{% block footer %}
{% include "kfet/base_footer.html" %}
{% endblock %}
{% block main %}
<form action="" method="post" class="form-horizontal" autocomplete="off">
{% csrf_token %}
{% include 'kfet/form_snippet.html' %}
{% include 'kfet/form_submit_snippet.html' with value="Envoyer" %}
</form>
{% endblock %}

View file

@ -7,7 +7,7 @@
{{ filter_form.media }}
<script type="text/javascript" src="{% url 'js_reverse' %}" ></script>
<script type="text/javascript" src="{% static 'kfet/js/history.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/vendor/moment/moment-timezone-with-data.min.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/vendor/moment/moment-timezone-with-data-2012-2022.min.js' %}"></script>
{% endblock %}
{% block title %}Historique{% endblock %}

View file

@ -4,7 +4,7 @@
{% block extra_head %}
<link rel="stylesheet" style="text/css" href="{% static 'kfet/css/kpsul_grid.css' %}">
<script type="text/javascript" src="{% static 'vendor/jquery/jquery.autocomplete-light.min.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/vendor/moment/moment-timezone-with-data.min.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/vendor/moment/moment-timezone-with-data-2012-2022.min.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/js/history.js' %}"></script>
<script type="text/javascript" src="{% url 'js_reverse' %}" ></script>
<script type="text/javascript" src="{% static 'kfet/vendor/underscore-min.js' %}"></script>

View file

@ -1,12 +0,0 @@
Salut {{ account.name }},
Ton compte K-Fêt a bien été créé le {{ account.created_at }} avec le trigramme {{ account.trigramme }}.
Tu peux désormais :
- Accéder à ton historique personnel des consommations : https://{{ site }}{{ url_read }}
- Modifier tes informations : https://{{ site }}{{ url_update }}
- Supprimer ton compte : https://{{ site }}{{ url_delete }}
En espérant te revoir bientôt,
--
L'équipe K-Fêt

View file

@ -1,16 +0,0 @@
Bonjour,
J'aimerais organiser une soirée le {{ date }}, au thème « {{ theme|safe }} », en K-Fêt.
Elle se terminerait à {{ horaire_fin }}, et le service serait en mode {{ service }}.
Les 4 responsables de la soirée seraient :
- {{ respo1 }}
- {{ respo2 }}
- {{ respo3 }}
- {{ respo4 }}
Quelques remarques supplémentaires :
{{ remarques|safe }}
Bien cordialement,
{{ nom|safe }}

View file

@ -7,7 +7,7 @@
{% block extra_head %}
<script type="text/javascript" src="{% url 'js_reverse' %}" ></script>
<script type="text/javascript" src="{% static 'kfet/js/history.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/vendor/moment/moment-timezone-with-data.min.js' %}"></script>
<script type="text/javascript" src="{% static 'kfet/vendor/moment/moment-timezone-with-data-2012-2022.min.js' %}"></script>
{% endblock %}
{% block fixed %}

View file

@ -9,10 +9,6 @@ register_converter(converters.TrigrammeConverter, "trigramme")
urlpatterns = [
path("login/generic", views.login_generic, name="kfet.login.generic"),
path("history", views.history, name="kfet.history"),
path("contact", views.ContactView.as_view(), name="kfet.contact"),
path(
"demande-soiree", views.DemandeSoireeView.as_view(), name="kfet.demande-soiree"
),
# -----
# Account urls
# -----

View file

@ -13,7 +13,6 @@ from django.contrib.auth.mixins import PermissionRequiredMixin
from django.contrib.auth.models import Permission, User
from django.contrib.messages.views import SuccessMessageMixin
from django.core.exceptions import SuspiciousOperation
from django.core.mail import EmailMessage
from django.db import transaction
from django.db.models import (
Count,
@ -35,7 +34,6 @@ from django.http import (
JsonResponse,
)
from django.shortcuts import get_object_or_404, redirect, render
from django.template import loader
from django.urls import reverse, reverse_lazy
from django.utils import timezone
from django.utils.decorators import method_decorator
@ -66,8 +64,6 @@ from kfet.forms import (
CheckoutStatementCreateForm,
CheckoutStatementUpdateForm,
CofForm,
ContactForm,
DemandeSoireeForm,
FilterHistoryForm,
InventoryArticleForm,
KFetConfigForm,
@ -118,61 +114,6 @@ def put_cleaned_data_in_dict(dict, form):
dict[field] = form.cleaned_data[field]
class ContactView(FormView):
template_name = "kfet/contact.html"
form_class = ContactForm
success_url = reverse_lazy("kfet.contact")
def form_valid(self, form):
# Envoie un mail lorsque le formulaire est valide
EmailMessage(
form.cleaned_data["subject"],
form.cleaned_data["message"],
from_email=form.cleaned_data["from_email"],
to=("chefs-k-fet@ens.psl.eu",),
).send()
messages.success(
self.request,
"Votre message a bien été envoyé aux Wo·men K-Fêt.",
)
return super().form_valid(form)
class DemandeSoireeView(FormView):
template_name = "kfet/demande_soiree.html"
form_class = DemandeSoireeForm
success_url = reverse_lazy("kfet.demande-soiree")
def form_valid(self, form):
destinataires = ["chefs-k-fet@ens.psl.eu"]
if form.cleaned_data["contact_boum"]:
destinataires.append("boum@ens.psl.eu")
if form.cleaned_data["contact_pls"]:
destinataires.append("pls@ens.psl.eu")
# Envoie un mail lorsque le formulaire est valide
EmailMessage(
f"Demande de soirée le {form.cleaned_data['date']}",
loader.render_to_string(
"kfet/mails/demande_soiree.txt", context=form.cleaned_data
),
from_email=form.cleaned_data["from_email"],
to=destinataires,
cc=[form.cleaned_data["from_email"]],
).send()
messages.success(
self.request,
"Votre demande de soirée a bien été envoyée.",
)
return super().form_valid(form)
# -----
# Account views
# -----
@ -244,7 +185,6 @@ def account_create(request):
account_form = AccountNoTriForm(request.POST, instance=account)
account_form.save()
messages.success(request, "Compte créé : %s" % account.trigramme)
account.send_creation_email()
return redirect("kfet.account.create")
except Account.UserHasAccount as e:
messages.error(
@ -422,7 +362,7 @@ def account_update(request, trigramme):
user_info_form = UserInfoForm(instance=account.user)
account_form = AccountForm(instance=account)
group_form = UserGroupForm(instance=account.user)
frozen_form = AccountFrozenForm(instance=account)
frozen_form = AccountFrozenForm(request.POST, instance=account)
pwd_form = AccountPwdForm()
if request.method == "POST":

View file

@ -10,14 +10,14 @@ Le COF a reçu une demande de petit cours qui te correspond. Tu es en haut de la
¤ Lieu (si préféré) : {{ demande.lieu }}
{% if matieres|length > 1 %}¤ Matières :
{% for matiere in matieres %} ¤ {{ matiere }}
{% endfor %}{% else %}¤ Matière : {% for matiere in matieres %}{{ matiere }}
{% endfor %}{% endif %}
¤ Niveau : {{ demande.get_niveau_display }}
¤ Remarques diverses (désolé pour les balises HTML) : {{ demande.remarques }}
{% if matieres|length > 1 %}¤ Matières :
{% for matiere in matieres %} ¤ {{ matiere }}
{% endfor %}{% else %}¤ Matière : {% for matiere in matieres %}{{ matiere }}
{% endfor %}{% endif %}
Voilà, cette personne te contactera peut-être sous peu, tu pourras voir les détails directement avec elle (prix, modalités, ...). Pour indication, 30 Euro/h semble être la moyenne.
Si tu te rends compte qu'en fait tu ne peux pas/plus donner de cours en ce moment, ça serait cool que tu décoches la case "Recevoir des propositions de petits cours" sur GestioCOF. Ensuite dès que tu voudras réapparaître tu pourras recocher la case et tu seras à nouveau sur la liste.

View file

@ -1,11 +1,4 @@
{
pkgs ? import <nixpkgs> { },
...
}:
let
python = pkgs.python39;
in
{ pkgs ? import <nixpkgs> { }, ... }:
pkgs.mkShell {
shellHook = ''
@ -17,14 +10,12 @@ pkgs.mkShell {
pip install -r requirements-devel.txt | grep -v 'Requirement already satisfied:'
'';
packages =
[ python ]
++ (with python.pkgs; [
django-types
pip
virtualenv
python-ldap
]);
packages = with pkgs; [
python38
python38Packages.pip
python38Packages.virtualenv
python38Packages.python-ldap
];
allowSubstitutes = false;
}