Commit 489bcfb2 authored by Luko van der Maas's avatar Luko van der Maas Committed by Sébastiaan Versteeg

Black all code

parent 79e50f30
......@@ -22,7 +22,7 @@ codestyle:
before_script:
- poetry install --no-interaction
script:
- poetry run flake8 website
- black --check .
# Check for obsolete translations in .po files (starting with `#~`).
- cd website
- grep --include="*.po" --files-with-matches --recursive "^#~" && exit 1 || echo "No obsolete translations found."
......
......@@ -28,9 +28,8 @@ Testing and linting
You can use [`pyenv`](https://github.com/pyenv/pyenv) (on Unix systems) to test in different python
environments.
The linter can be run in the `poetry shell` or by running
poetry run flake8 website
All code has to be run through [`black`](https://github.com/psf/black) before being committed. To black the code before committing make run `black` one the base directory of this project.
If you want to integrate `black` with your editor look in the [`black` docs](https://black.readthedocs.io/en/stable/editor_integration.html). On linux you can find the black executable in `~/.cache/poety/virtualenvs/<your env>/bin/black`.
There are a range of tests that can be run:
......
......@@ -20,7 +20,7 @@
import os
import sys
sys.path.insert(0, os.path.abspath('../website'))
sys.path.insert(0, os.path.abspath("../website"))
import django
from django.conf import settings # noqa
......@@ -43,23 +43,23 @@ django.setup()
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.doctest',
'sphinx.ext.mathjax',
'sphinx.ext.viewcode',
'sphinx.ext.intersphinx',
'sphinx.ext.graphviz',
'recommonmark',
"sphinx.ext.autodoc",
"sphinx.ext.doctest",
"sphinx.ext.mathjax",
"sphinx.ext.viewcode",
"sphinx.ext.intersphinx",
"sphinx.ext.graphviz",
"recommonmark",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]
# The master toctree document.
master_doc = 'index'
master_doc = "index"
# General information about the project.
project = 'Concrexit'
project = "Concrexit"
copyright = "2017--2019, Technicie, Studievereniging Thalia"
author = "Technicie, Studievereniging Thalia"
......@@ -68,9 +68,9 @@ author = "Technicie, Studievereniging Thalia"
# built documents.
#
# The short X.Y version.
version = ''
version = ""
# The full version, including alpha/beta/rc tags.
release = ''
release = ""
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
......@@ -82,23 +82,23 @@ language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
pygments_style = "sphinx"
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# default domain:
primary_domain = 'py'
primary_domain = "py"
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'alabaster'
html_theme = "alabaster"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
......@@ -109,31 +109,28 @@ html_theme = 'alabaster'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
#html_static_path = ['_static']
# html_static_path = ['_static']
# -- Options for HTMLHelp output ------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'Concrexitdoc'
htmlhelp_basename = "Concrexitdoc"
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
'maxlistdepth': '10'
"maxlistdepth": "10"
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
......@@ -143,8 +140,13 @@ latex_elements = {
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'Concrexit.tex', 'Concrexit Documentation',
'Thalia Technicie', 'manual'),
(
master_doc,
"Concrexit.tex",
"Concrexit Documentation",
"Thalia Technicie",
"manual",
),
]
......@@ -152,10 +154,7 @@ latex_documents = [
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'concrexit', 'Concrexit Documentation',
[author], 1)
]
man_pages = [(master_doc, "concrexit", "Concrexit Documentation", [author], 1)]
# -- Options for Texinfo output -------------------------------------------
......@@ -164,35 +163,43 @@ man_pages = [
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'Concrexit', 'Concrexit Documentation',
author, 'Concrexit', "Thalia's website",
'Django Applications'),
(
master_doc,
"Concrexit",
"Concrexit Documentation",
author,
"Concrexit",
"Thalia's website",
"Django Applications",
),
]
# -- Options for autodoc --------------------------------------------------
# Default options for autodoc
autodoc_default_options = {
'members': True,
'undoc-members': True,
"members": True,
"undoc-members": True,
}
# We need to mock the modules for the sphinx build in the docker.
autodoc_mock_imports = ['factory', 'pydenticon', 'faker']
autodoc_mock_imports = ["factory", "pydenticon", "faker"]
# -- Options for doctest --------------------------------------------------
# Disable doctests in normal strings
doctest_test_doctest_blocks = ''
doctest_test_doctest_blocks = ""
# -- intersphinx ---
intersphinx_mapping = {
'python': ('https://docs.python.org/3.7', None),
'django': ('https://docs.djangoproject.com/en/2.2/',
'https://docs.djangoproject.com/en/2.2/_objects/'),
"python": ("https://docs.python.org/3.7", None),
"django": (
"https://docs.djangoproject.com/en/2.2/",
"https://docs.djangoproject.com/en/2.2/_objects/",
),
}
# -- Supress warnings ---
suppress_warnings = [
'image.nonlocal_uri',
"image.nonlocal_uri",
]
This diff is collapsed.
......@@ -39,12 +39,15 @@ docs = ["recommonmark", "sphinx"]
[tool.poetry.dev-dependencies]
django-template-check = "~0.3.1"
factory_boy = "~2.12"
flake8 = "~3.7"
pydenticon = "~0.3.1"
pylint = "~2.4"
pylint-django = "~2.0"
Faker = "~3.0"
coverage = "~4.5"
black = "~19.10b0"
[tool.black]
exclude = '(/(\.eggs|\.git|\.tox)/|migrations)'
[build-system]
requires = ["poetry>=0.12"]
......
......@@ -26,95 +26,133 @@ class MemberGroupMembershipInlineFormSet(forms.BaseInlineFormSet):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.queryset = self.queryset.select_related(
'member', 'group').filter(until=None)
self.queryset = self.queryset.select_related("member", "group").filter(
until=None
)
class MemberGroupMembershipInline(admin.StackedInline):
"""Inline for group memberships"""
model = models.MemberGroupMembership
formset = MemberGroupMembershipInlineFormSet
can_delete = False
ordering = ('since',)
ordering = ("since",)
extra = 0
autocomplete_fields = ('member',)
autocomplete_fields = ("member",)
@admin.register(models.Committee)
class CommitteeAdmin(TranslatedModelAdmin):
"""Manage the committees"""
inlines = (MemberGroupMembershipInline,)
form = MemberGroupForm
list_display = ('name', 'since', 'until', 'active', 'email')
list_filter = ('until', 'active',)
search_fields = ('name', 'description')
filter_horizontal = ('permissions',)
fields = ('name', 'description', 'photo', 'permissions', 'since',
'until', 'contact_mailinglist', 'contact_email', 'active',
'display_members')
list_display = ("name", "since", "until", "active", "email")
list_filter = (
"until",
"active",
)
search_fields = ("name", "description")
filter_horizontal = ("permissions",)
fields = (
"name",
"description",
"photo",
"permissions",
"since",
"until",
"contact_mailinglist",
"contact_email",
"active",
"display_members",
)
def email(self, instance):
if instance.contact_email:
return instance.contact_email
elif instance.contact_mailinglist:
return instance.contact_mailinglist.name + '@thalia.nu'
return instance.contact_mailinglist.name + "@thalia.nu"
return None
@admin.register(models.Society)
class SocietyAdmin(TranslatedModelAdmin):
"""Manage the societies"""
inlines = (MemberGroupMembershipInline,)
form = MemberGroupForm
list_display = ('name', 'since', 'until', 'active', 'email')
list_filter = ('until', 'active',)
search_fields = ('name', 'description')
filter_horizontal = ('permissions',)
fields = ('name', 'description', 'photo', 'permissions', 'since',
'until', 'contact_mailinglist', 'contact_email', 'active',
'display_members')
list_display = ("name", "since", "until", "active", "email")
list_filter = (
"until",
"active",
)
search_fields = ("name", "description")
filter_horizontal = ("permissions",)
fields = (
"name",
"description",
"photo",
"permissions",
"since",
"until",
"contact_mailinglist",
"contact_email",
"active",
"display_members",
)
def email(self, instance):
if instance.contact_email:
return instance.contact_email
elif instance.contact_mailinglist:
return instance.contact_mailinglist.name + '@thalia.nu'
return instance.contact_mailinglist.name + "@thalia.nu"
return None
@admin.register(models.Board)
class BoardAdmin(TranslatedModelAdmin):
"""Manage the board"""
inlines = (MemberGroupMembershipInline,)
form = MemberGroupForm
exclude = ('is_board',)
filter_horizontal = ('permissions',)
fields = ('name', 'description', 'photo', 'permissions',
'contact_mailinglist', 'contact_email', 'since', 'until',
'display_members')
exclude = ("is_board",)
filter_horizontal = ("permissions",)
fields = (
"name",
"description",
"photo",
"permissions",
"contact_mailinglist",
"contact_email",
"since",
"until",
"display_members",
)
class TypeFilter(admin.SimpleListFilter):
"""Filter memberships on board-only"""
title = _('group memberships')
parameter_name = 'group_type'
title = _("group memberships")
parameter_name = "group_type"
def lookups(self, request, model_admin):
return [
('boards', _('Only boards')),
('committees', _('Only committees')),
('societies', _('Only societies')),
("boards", _("Only boards")),
("committees", _("Only committees")),
("societies", _("Only societies")),
]
def queryset(self, request, queryset):
if self.value() == 'boards':
if self.value() == "boards":
return queryset.exclude(group__board=None)
elif self.value() == 'committees':
elif self.value() == "committees":
return queryset.exclude(group__committee=None)
elif self.value() == 'societies':
elif self.value() == "societies":
return queryset.exclude(group__society=None)
return queryset
......@@ -122,17 +160,20 @@ class TypeFilter(admin.SimpleListFilter):
class LectureYearFilter(admin.SimpleListFilter):
"""Filter the memberships on those started or ended in a lecture year"""
title = _('lecture year')
parameter_name = 'lecture_year'
title = _("lecture year")
parameter_name = "lecture_year"
def lookups(self, request, model_admin):
current_year = datetime_to_lectureyear(timezone.now())
first_year = datetime_to_lectureyear(
models.MemberGroupMembership.objects.earliest('since').since
models.MemberGroupMembership.objects.earliest("since").since
)
return [(year, '{}-{}'.format(year, year+1))
for year in range(first_year, current_year+1)]
return [
(year, "{}-{}".format(year, year + 1))
for year in range(first_year, current_year + 1)
]
def queryset(self, request, queryset):
if not self.value():
......@@ -146,82 +187,95 @@ class LectureYearFilter(admin.SimpleListFilter):
class ActiveMembershipsFilter(admin.SimpleListFilter):
"""Filter the memberships by whether they are active or not"""
title = _('active memberships')
parameter_name = 'active'
title = _("active memberships")
parameter_name = "active"
def lookups(self, request, model_name):
return (
('active', _('Active')),
('inactive', _('Inactive')),
("active", _("Active")),
("inactive", _("Inactive")),
)
def queryset(self, request, queryset):
now = timezone.now()
if self.value() == 'active':
return queryset.filter(Q(until__isnull=True) |
Q(until__gte=now))
if self.value() == "active":
return queryset.filter(Q(until__isnull=True) | Q(until__gte=now))
if self.value() == 'inactive':
if self.value() == "inactive":
return queryset.filter(until__lt=now)
@admin.register(models.MemberGroupMembership)
class MemberGroupMembershipAdmin(TranslatedModelAdmin):
"""Manage the group memberships"""
form = MemberGroupMembershipForm
list_display = ('member', 'group', 'since', 'until', 'chair', 'role')
list_filter = ('group', TypeFilter, LectureYearFilter,
ActiveMembershipsFilter)
list_select_related = ('member', 'group',)
search_fields = ('member__first_name', 'member__last_name',
'member__email')
date_hierarchy = 'since'
actions = ('export',)
list_display = ("member", "group", "since", "until", "chair", "role")
list_filter = ("group", TypeFilter, LectureYearFilter, ActiveMembershipsFilter)
list_select_related = (
"member",
"group",
)
search_fields = ("member__first_name", "member__last_name", "member__email")
date_hierarchy = "since"
actions = ("export",)
def changelist_view(self, request, extra_context=None):
self.message_user(request, _('Do not edit existing memberships if the '
'chair of a group has changed, add a '
'new membership instead.'),
messages.WARNING)
self.message_user(
request,
_(
"Do not edit existing memberships if the "
"chair of a group has changed, add a "
"new membership instead."
),
messages.WARNING,
)
return super().changelist_view(request, extra_context)
def export(self, request, queryset):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = ('attachment;'
'filename='
'"group_memberships.csv"')
response = HttpResponse(content_type="text/csv")
response["Content-Disposition"] = (
"attachment;" "filename=" '"group_memberships.csv"'
)
writer = csv.writer(response)
writer.writerow([