tests with ubuntu 22.04, django-bootstrap-datepicker-plus is a standalone package and fix encoding in tests

This commit is contained in:
bleizi 2024-02-12 21:25:07 +01:00
parent fb3337966e
commit 2ee7f41dfe
8 changed files with 34 additions and 291 deletions

View File

@ -7,25 +7,8 @@ stages:
variables: variables:
GIT_SUBMODULE_STRATEGY: recursive GIT_SUBMODULE_STRATEGY: recursive
# Ubuntu 20.04
py38-django22:
stage: test
image: ubuntu:20.04
before_script:
# Fix tzdata prompt
- ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime && echo Europe/Paris > /etc/timezone
- >
apt-get update &&
apt-get install --no-install-recommends -y
python3-django python3-django-crispy-forms
python3-django-extensions python3-django-filters python3-django-polymorphic
python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil
python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache
python3-bs4 python3-setuptools tox texlive-xetex
script: tox -e py38-django22
# Debian Bullseye # Debian Bullseye
py39-django22: py39-django42:
stage: test stage: test
image: debian:bullseye image: debian:bullseye
before_script: before_script:
@ -37,7 +20,24 @@ py39-django22:
python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil
python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache
python3-bs4 python3-setuptools tox texlive-xetex python3-bs4 python3-setuptools tox texlive-xetex
script: tox -e py39-django22 script: tox -e py39-django42
# Ubuntu 22.04
py310-django42:
stage: test
image: ubuntu:22.04
before_script:
# Fix tzdata prompt
- ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime && echo Europe/Paris > /etc/timezone
- >
apt-get update &&
apt-get install --no-install-recommends -y
python3-django python3-django-crispy-forms
python3-django-extensions python3-django-filters python3-django-polymorphic
python3-djangorestframework python3-django-oauth-toolkit python3-psycopg2 python3-pil
python3-babel python3-lockfile python3-pip python3-phonenumbers python3-memcache
python3-bs4 python3-setuptools tox texlive-xetex
script: tox -e py38-django42
# Debian Bookworm # Debian Bookworm
py311-django42: py311-django42:

View File

@ -4,13 +4,14 @@
from datetime import timedelta from datetime import timedelta
from random import shuffle from random import shuffle
from bootstrap_datepicker_plus.widgets import DateTimePickerInput
from django import forms from django import forms
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from member.models import Club from member.models import Club
from note.models import Note, NoteUser from note.models import Note, NoteUser
from note_kfet.inputs import Autocomplete, DateTimePickerInput from note_kfet.inputs import Autocomplete
from note_kfet.middlewares import get_current_request from note_kfet.middlewares import get_current_request
from permission.backends import PermissionBackend from permission.backends import PermissionBackend

View File

@ -3,7 +3,7 @@
import io import io
from PIL import Image, ImageSequence from bootstrap_datepicker_plus.widgets import DatePickerInput
from django import forms from django import forms
from django.conf import settings from django.conf import settings
from django.contrib.auth.forms import AuthenticationForm from django.contrib.auth.forms import AuthenticationForm
@ -13,8 +13,9 @@ from django.forms import CheckboxSelectMultiple
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from note.models import NoteSpecial, Alias from note.models import NoteSpecial, Alias
from note_kfet.inputs import Autocomplete, AmountInput, DatePickerInput from note_kfet.inputs import Autocomplete, AmountInput
from permission.models import PermissionMask, Role from permission.models import PermissionMask, Role
from PIL import Image, ImageSequence
from .models import Profile, Club, Membership from .models import Profile, Club, Membership

View File

@ -2,12 +2,13 @@
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from datetime import datetime from datetime import datetime
from bootstrap_datepicker_plus.widgets import DateTimePickerInput
from django import forms from django import forms
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.forms import CheckboxSelectMultiple from django.forms import CheckboxSelectMultiple
from django.utils.timezone import make_aware from django.utils.timezone import make_aware
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from note_kfet.inputs import Autocomplete, AmountInput, DateTimePickerInput from note_kfet.inputs import Autocomplete, AmountInput
from .models import TransactionTemplate, NoteClub, Alias from .models import TransactionTemplate, NoteClub, Alias

View File

@ -1,13 +1,14 @@
# Copyright (C) 2018-2023 by BDE ENS Paris-Saclay # Copyright (C) 2018-2023 by BDE ENS Paris-Saclay
# SPDX-License-Identifier: GPL-3.0-or-later # SPDX-License-Identifier: GPL-3.0-or-later
from bootstrap_datepicker_plus.widgets import DatePickerInput
from django import forms from django import forms
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.db.models import Q from django.db.models import Q
from django.forms import CheckboxSelectMultiple from django.forms import CheckboxSelectMultiple
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from note.models import NoteSpecial, NoteUser from note.models import NoteSpecial, NoteUser
from note_kfet.inputs import AmountInput, DatePickerInput, Autocomplete, ColorWidget from note_kfet.inputs import AmountInput, Autocomplete, ColorWidget
from ..models import WEIClub, WEIRegistration, Bus, BusTeam, WEIMembership, WEIRole from ..models import WEIClub, WEIRegistration, Bus, BusTeam, WEIMembership, WEIRole

View File

@ -439,7 +439,7 @@ class TestWEIRegistration(TestCase):
emergency_contact_phone='+33123456789', emergency_contact_phone='+33123456789',
)) ))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertTrue("This user can't be in her/his first year since he/she has already participated to a WEI." self.assertTrue("This user can't be in her/his first year since he/she has already participated to a WEI."
in str(response.context["form"].errors)) in str(response.context["form"].errors))
# Check that if the WEI is started, we can't register anyone # Check that if the WEI is started, we can't register anyone
@ -635,7 +635,7 @@ class TestWEIRegistration(TestCase):
)) ))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertFalse(response.context["form"].is_valid()) self.assertFalse(response.context["form"].is_valid())
self.assertTrue("This team doesn't belong to the given bus." in str(response.context["form"].errors)) self.assertTrue("This team doesn't belong to the given bus." in str(response.context["form"].errors))
response = self.client.post(reverse("wei:validate_registration", kwargs=dict(pk=self.registration.pk)), dict( response = self.client.post(reverse("wei:validate_registration", kwargs=dict(pk=self.registration.pk)), dict(
roles=[WEIRole.objects.get(name="GC WEI").id], roles=[WEIRole.objects.get(name="GC WEI").id],

View File

@ -68,264 +68,3 @@ class ColorWidget(Widget):
def value_from_datadict(self, data, files, name): def value_from_datadict(self, data, files, name):
val = super().value_from_datadict(data, files, name) val = super().value_from_datadict(data, files, name)
return int(val[1:], 16) return int(val[1:], 16)
"""
The remaining of this file comes from the project `django-bootstrap-datepicker-plus` available on Github:
https://github.com/monim67/django-bootstrap-datepicker-plus
This is distributed under Apache License 2.0.
This adds datetime pickers with bootstrap.
"""
"""Contains Base Date-Picker input class for widgets of this package."""
class DatePickerDictionary:
"""Keeps track of all date-picker input classes."""
_i = 0
items = dict()
@classmethod
def generate_id(cls):
"""Return a unique ID for each date-picker input class."""
cls._i += 1
return 'dp_%s' % cls._i
class BasePickerInput(DateTimeBaseInput):
"""Base Date-Picker input class for widgets of this package."""
template_name = 'bootstrap_datepicker_plus/date-picker.html'
picker_type = 'DATE'
format = '%Y-%m-%d'
config = {}
_default_config = {
'id': None,
'picker_type': None,
'linked_to': None,
'options': {} # final merged options
}
options = {} # options extended by user
options_param = {} # options passed as parameter
_default_options = {
'showClose': True,
'showClear': True,
'showTodayButton': True,
"locale": "fr",
}
# source: https://github.com/tutorcruncher/django-bootstrap3-datetimepicker
# file: /blob/31fbb09/bootstrap3_datetime/widgets.py#L33
format_map = (
('DDD', r'%j'),
('DD', r'%d'),
('MMMM', r'%B'),
('MMM', r'%b'),
('MM', r'%m'),
('YYYY', r'%Y'),
('YY', r'%y'),
('HH', r'%H'),
('hh', r'%I'),
('mm', r'%M'),
('ss', r'%S'),
('a', r'%p'),
('ZZ', r'%z'),
)
class Media:
"""JS/CSS resources needed to render the date-picker calendar."""
js = (
'https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/'
'moment-with-locales.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/'
'4.17.47/js/bootstrap-datetimepicker.min.js',
'bootstrap_datepicker_plus/js/datepicker-widget.js'
)
css = {'all': (
'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/'
'4.17.47/css/bootstrap-datetimepicker.css',
'bootstrap_datepicker_plus/css/datepicker-widget.css'
), }
@classmethod
def format_py2js(cls, datetime_format):
"""Convert python datetime format to moment datetime format."""
for js_format, py_format in cls.format_map:
datetime_format = datetime_format.replace(py_format, js_format)
return datetime_format
@classmethod
def format_js2py(cls, datetime_format):
"""Convert moment datetime format to python datetime format."""
for js_format, py_format in cls.format_map:
datetime_format = datetime_format.replace(js_format, py_format)
return datetime_format
def __init__(self, attrs=None, format=None, options=None):
"""Initialize the Date-picker widget."""
self.format_param = format
self.options_param = options if options else {}
self.config = self._default_config.copy()
self.config['id'] = DatePickerDictionary.generate_id()
self.config['picker_type'] = self.picker_type
self.config['options'] = self._calculate_options()
attrs = attrs if attrs else {}
if 'class' not in attrs:
attrs['class'] = 'form-control'
super().__init__(attrs, self._calculate_format())
def _calculate_options(self):
"""Calculate and Return the options."""
_options = self._default_options.copy()
_options.update(self.options)
if self.options_param:
_options.update(self.options_param)
return _options
def _calculate_format(self):
"""Calculate and Return the datetime format."""
_format = self.format_param if self.format_param else self.format
if self.config['options'].get('format'):
_format = self.format_js2py(self.config['options'].get('format'))
else:
self.config['options']['format'] = self.format_py2js(_format)
return _format
def get_context(self, name, value, attrs):
"""Return widget context dictionary."""
context = super().get_context(
name, value, attrs)
context['widget']['attrs']['dp_config'] = json_dumps(self.config)
return context
def start_of(self, event_id):
"""
Set Date-Picker as the start-date of a date-range.
Args:
- event_id (string): User-defined unique id for linking two fields
"""
DatePickerDictionary.items[str(event_id)] = self
return self
def end_of(self, event_id, import_options=True):
"""
Set Date-Picker as the end-date of a date-range.
Args:
- event_id (string): User-defined unique id for linking two fields
- import_options (bool): inherit options from start-date input,
default: TRUE
"""
event_id = str(event_id)
if event_id in DatePickerDictionary.items:
linked_picker = DatePickerDictionary.items[event_id]
self.config['linked_to'] = linked_picker.config['id']
if import_options:
backup_moment_format = self.config['options']['format']
self.config['options'].update(linked_picker.config['options'])
self.config['options'].update(self.options_param)
if self.format_param or 'format' in self.options_param:
self.config['options']['format'] = backup_moment_format
else:
self.format = linked_picker.format
# Setting useCurrent is necessary, see following issue
# https://github.com/Eonasdan/bootstrap-datetimepicker/issues/1075
self.config['options']['useCurrent'] = False
self._link_to(linked_picker)
else:
raise KeyError(
'start-date not specified for event_id "%s"' % event_id)
return self
def _link_to(self, linked_picker):
"""
Executed when two date-inputs are linked together.
This method for sub-classes to override to customize the linking.
"""
pass
class DatePickerInput(BasePickerInput):
"""
Widget to display a Date-Picker Calendar on a DateField property.
Args:
- attrs (dict): HTML attributes of rendered HTML input
- format (string): Python DateTime format eg. "%Y-%m-%d"
- options (dict): Options to customize the widget, see README
"""
picker_type = 'DATE'
format = '%Y-%m-%d'
format_key = 'DATE_INPUT_FORMATS'
class TimePickerInput(BasePickerInput):
"""
Widget to display a Time-Picker Calendar on a TimeField property.
Args:
- attrs (dict): HTML attributes of rendered HTML input
- format (string): Python DateTime format eg. "%Y-%m-%d"
- options (dict): Options to customize the widget, see README
"""
picker_type = 'TIME'
format = '%H:%M'
format_key = 'TIME_INPUT_FORMATS'
template_name = 'bootstrap_datepicker_plus/time_picker.html'
class DateTimePickerInput(BasePickerInput):
"""
Widget to display a DateTime-Picker Calendar on a DateTimeField property.
Args:
- attrs (dict): HTML attributes of rendered HTML input
- format (string): Python DateTime format eg. "%Y-%m-%d"
- options (dict): Options to customize the widget, see README
"""
picker_type = 'DATETIME'
format = '%Y-%m-%d %H:%M'
format_key = 'DATETIME_INPUT_FORMATS'
class MonthPickerInput(BasePickerInput):
"""
Widget to display a Month-Picker Calendar on a DateField property.
Args:
- attrs (dict): HTML attributes of rendered HTML input
- format (string): Python DateTime format eg. "%Y-%m-%d"
- options (dict): Options to customize the widget, see README
"""
picker_type = 'MONTH'
format = '01/%m/%Y'
format_key = 'DATE_INPUT_FORMATS'
class YearPickerInput(BasePickerInput):
"""
Widget to display a Year-Picker Calendar on a DateField property.
Args:
- attrs (dict): HTML attributes of rendered HTML input
- format (string): Python DateTime format eg. "%Y-%m-%d"
- options (dict): Options to customize the widget, see README
"""
picker_type = 'YEAR'
format = '01/01/%Y'
format_key = 'DATE_INPUT_FORMATS'
def _link_to(self, linked_picker):
"""Customize the options when linked with other date-time input"""
yformat = self.config['options']['format'].replace('-01-01', '-12-31')
self.config['options']['format'] = yformat

View File

@ -1,10 +1,10 @@
[tox] [tox]
envlist = envlist =
# Ubuntu 20.04 Python
py38-django22
# Debian Bullseye Python # Debian Bullseye Python
py39-django22 py39-django42
# Ubuntu 22.04 Python
py310-django42
# Debian Bookworm Python # Debian Bookworm Python
py311-django42 py311-django42