Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Running the black code formatter on the codebase #241

Open
wants to merge 2 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 32 additions & 16 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@ SHELL = /bin/bash
.SHELLFLAGS = -e -u -o pipefail -c


# Allow overriding the python binary used (e.g. in creation of virtualenv)
PYTHON ?= python

# Allow overriding the virtualenv path
# NOTE: One big caveat here is that if this is overridden, then make will
# not be able to cache the `.venv` target.
# This just means that it'll try and install packages for many/most of the
# targets here. Not a problem, but can be a bit annoying.
VENV ?= .venv


default: help


Expand All @@ -32,22 +43,22 @@ help:
@exit 1


.venv: .env ## Creates a virtualenv at `./.venv`
@python -m venv .venv
.venv: .env ## Creates a virtualenv at `./$(VENV)`
@$(PYTHON) -m venv $(VENV)


.PHONY: setup
setup: .env .venv requirements.txt.log requirements-mysql.txt.log requirements-postgresql.txt.log ## Sets up the project (installs dependencies etc.)


requirements.txt.log: .venv requirements.txt.freeze
@. .venv/bin/activate && pip install -r requirements.txt.freeze | tee .requirements.txt.tmp.log
@. $(VENV)/bin/activate && pip install -r requirements.txt.freeze | tee .requirements.txt.tmp.log
@mv .requirements.txt.tmp.log requirements.txt.log


requirements-mysql.txt.log: .env .venv requirements-mysql.txt.freeze
ifeq ($(shell grep '^W2_DATABASE_ENGINE' .env 2>/dev/null | grep 'mysql' > /dev/null && echo yes || echo no), yes)
@. .venv/bin/activate && pip install -r requirements-mysql.txt.freeze | tee .requirements-mysql.txt.tmp.log
@. $(VENV)/bin/activate && pip install -r requirements-mysql.txt.freeze | tee .requirements-mysql.txt.tmp.log
else
@echo "Not using MySQL" | tee .requirements-mysql.txt.tmp.log
endif
Expand All @@ -56,7 +67,7 @@ endif

requirements-postgresql.txt.log: .env .venv requirements-postgresql.txt.freeze
ifeq ($(shell grep '^W2_DATABASE_ENGINE' .env 2>/dev/null | grep 'psyco' > /dev/null && echo yes || echo no), yes)
@. .venv/bin/activate && pip install -r requirements-postgresql.txt.freeze | tee .requirements-postgresql.txt.tmp.log
@. $(VENV)/bin/activate && pip install -r requirements-postgresql.txt.freeze | tee .requirements-postgresql.txt.tmp.log
else
@echo "Not using PostgreSQL" | tee .requirements-postgresql.txt.tmp.log
endif
Expand All @@ -65,40 +76,45 @@ endif

.PHONY: freeze-dependencies
freeze-dependencies:
@. .venv/bin/activate && pip freeze | grep -v 'mysqlclient' > requirements.txt.freeze
@. $(VENV)/bin/activate && pip freeze | grep -v 'pkg-resources' | grep -v 'mysqlclient' > requirements.txt.freeze
ifeq ($(shell grep '^W2_DATABASE_ENGINE' .env 2>/dev/null | grep 'mysql' > /dev/null && echo yes || echo no), yes)
@. .venv/bin/activate && pip freeze | grep 'mysqlclient' > requirements-mysql.txt.freeze
@. $(VENV)/bin/activate && pip freeze | grep -v 'pkg-resources' | grep 'mysqlclient' > requirements-mysql.txt.freeze
endif
ifeq ($(shell grep '^W2_DATABASE_ENGINE' .env 2>/dev/null | grep 'psyco' > /dev/null && echo yes || echo no), yes)
@ .venv/bin/activate && pip freeze | grep 'psycopg' > requirements-postgresql.txt.freeze
@ $(VENV)/bin/activate && pip freeze | grep -v 'pkg-resources' | grep 'psycopg' > requirements-postgresql.txt.freeze
endif


.PHONY: update-dependencies
update-dependencies:
@rm -rf .venv/
@rm -rf $(VENV)/
@make .venv
@. .venv/bin/activate && pip install -r requirements.txt
@. $(VENV)/bin/activate && pip install -r requirements.txt
@make freeze-dependencies


.PHONY: format
format: setup
@. $(VENV)/bin/activate && black .


.PHONY: test
test: setup ## Runs the unit tests
@. .venv/bin/activate && ./manage.py test
@. $(VENV)/bin/activate && ./manage.py test


.PHONY: migrate
migrate: setup ## Runs the migrate Django management command
@. .venv/bin/activate && ./manage.py migrate
@. $(VENV)/bin/activate && ./manage.py migrate


.PHONY: load_fake_data
load_fake_data: setup ## Loads up fake data using custom Django management command
@. .venv/bin/activate && ./manage.py load_fake_data --full --reset
@. $(VENV)/bin/activate && ./manage.py load_fake_data --full --reset

.PHONY: run
run: setup ## Runs the Django development server
@. .venv/bin/activate && ./manage.py runserver
@. $(VENV)/bin/activate && ./manage.py runserver


.PHONY: clean
Expand All @@ -107,8 +123,8 @@ clean: ## Removes cached python files and virtualenv
@find . -name "__pycache__" -exec rm -rf {} \+
@echo "Deleting requirement log files"
@rm requirements*.log 2>/dev/null || true
@echo "Deleting the virtualenv ('./.venv/')"
@rm -rf .venv 2>/dev/null || true
@echo "Deleting the virtualenv ('./$(VENV)/')"
@rm -rf $(VENV) 2>/dev/null || true


.PHONY: docker/build
Expand Down
3 changes: 2 additions & 1 deletion core/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
def getDerivedAdmin(base_admin, **kwargs):
class DerivedAdmin(base_admin):
pass

derived = DerivedAdmin
for k, v in kwargs.iteritems():
setattr(derived, k, getattr(base_admin, k, []) + v)
Expand All @@ -26,7 +27,7 @@ class UserProfileInline(admin.StackedInline):


class UserAdmin(auth.admin.UserAdmin):
inlines = (UserProfileInline, )
inlines = (UserProfileInline,)


# Register the admins
Expand Down
1 change: 0 additions & 1 deletion core/ajax/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

from django.http import HttpResponse
import json

Expand Down
1 change: 1 addition & 0 deletions core/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from core.django_mdmail import convert_md_templates


class CoreConfig(AppConfig):
name = 'core'
verbose_name = 'Wasa2il Core'
Expand Down
2 changes: 2 additions & 0 deletions core/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def authenticate(self, request, username=None, password=None):

class EmailAuthenticationBackend(CustomAuthenticationBackend):
"""Allow users to log in using their e-mail address"""

def custom_get_user(self, email):
try:
return User.objects.get(email=email)
Expand All @@ -30,6 +31,7 @@ def custom_get_user(self, email):

class SSNAuthenticationBackend(CustomAuthenticationBackend):
"""Allow users to log in using their SSN"""

def custom_get_user(self, ssn):
# FIXME: This may be Iceland specific; we ignore dashes.
ssn = ssn.replace('-', '').strip()
Expand Down
6 changes: 4 additions & 2 deletions core/contextprocessors.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def globals(request):
'INSTANCE_VERSION': settings.WASA2IL_VERSION,
'FEATURES': settings.FEATURES,
'GCM_APP_ID': settings.GCM_APP_ID,
'settings': settings
'settings': settings,
}

# Get global variables from GlobalsMiddleWare.
Expand All @@ -25,7 +25,9 @@ def globals(request):
def auto_logged_out(request):
if hasattr(request, 'auto_logged_out') and request.auto_logged_out:
return {
'splash_message': _('For security reasons, you have been automatically logged out due to inactivity.')
'splash_message': _(
'For security reasons, you have been automatically logged out due to inactivity.'
)
}

return {}
141 changes: 71 additions & 70 deletions core/dataviews.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,90 +3,91 @@
from election.models import Election
from issue.models import Issue


@jsonize
def recent_activity(request):

# Names prefixed with "q_" to distinguish them as queries. We will be
# returning the same data in JSON format, which we will call "issues" and
# "elections".
q_issues = Issue.objects.select_related('polity').recent().order_by('polity__id', '-deadline_votes')
q_elections = Election.objects.prefetch_related(
'electionvote_set',
'candidate_set'
).select_related(
'result'
).recent()
q_issues = (
Issue.objects.select_related('polity')
.recent()
.order_by('polity__id', '-deadline_votes')
)
q_elections = (
Election.objects.prefetch_related('electionvote_set', 'candidate_set')
.select_related('result')
.recent()
)

issues = []
for q_issue in q_issues:
issues.append({
# Web location for further info on the issue.
'url': request.build_absolute_uri(
reverse('issue', args=(q_issue.polity_id, q_issue.id))
),

# The polity to which this issue belongs.
'polity': q_issue.polity.name,

# The polity's short name, if available.
'polity_shortname': q_issue.polity.name_short,

# A unique identifier for formal reference. Example: 6/2019
'log_number': '%d/%d' % (q_issue.issue_num, q_issue.issue_year),

# The issue's name or title.
'name': q_issue.name,

# Options are: concluded/voting/accepting_proposals/discussion
# Note that the state does not give the *result*, i.e. whether the
# proposal was accepted or rejected, but rather where the issue is
# currently in the decision-making process. Therefore "concluded"
# only means that the issue has concluded, but does not tell us
# *how* it concluded.
'state': q_issue.issue_state(),

# Translated, human-readable version of the issue state.
'state_human_readable': q_issue.get_issue_state_display(),

# A boolean indicating whether the issue has been approved or not.
'majority_reached': q_issue.majority_reached(),

# Translated, human-readable version of the result.
'majority_reached_human_readable': q_issue.get_majority_reached_display(),

# When the issue's fate is not determined by vote from within
# Wasa2il, for example when a vote is made outside of Wasa2il but
# still placed here for reference or historical reasons, or when
# an issue is retracted without ever coming to a vote.
#
# Consider displaying only this value if it is non-null, and the
# `majority_reached` value only if this is null.
'special_process': q_issue.special_process,

# Translated, human-readable version of the result.
'special_process_human_readable': q_issue.get_special_process_display(),

# Comment count.
'comment_count': q_issue.comment_count,

# Vote count.
'vote_count': q_issue.votecount,
})
issues.append(
{
# Web location for further info on the issue.
'url': request.build_absolute_uri(
reverse('issue', args=(q_issue.polity_id, q_issue.id))
),
# The polity to which this issue belongs.
'polity': q_issue.polity.name,
# The polity's short name, if available.
'polity_shortname': q_issue.polity.name_short,
# A unique identifier for formal reference. Example: 6/2019
'log_number': '%d/%d'
% (q_issue.issue_num, q_issue.issue_year),
# The issue's name or title.
'name': q_issue.name,
# Options are: concluded/voting/accepting_proposals/discussion
# Note that the state does not give the *result*, i.e. whether the
# proposal was accepted or rejected, but rather where the issue is
# currently in the decision-making process. Therefore "concluded"
# only means that the issue has concluded, but does not tell us
# *how* it concluded.
'state': q_issue.issue_state(),
# Translated, human-readable version of the issue state.
'state_human_readable': q_issue.get_issue_state_display(),
# A boolean indicating whether the issue has been approved or not.
'majority_reached': q_issue.majority_reached(),
# Translated, human-readable version of the result.
'majority_reached_human_readable': q_issue.get_majority_reached_display(),
# When the issue's fate is not determined by vote from within
# Wasa2il, for example when a vote is made outside of Wasa2il but
# still placed here for reference or historical reasons, or when
# an issue is retracted without ever coming to a vote.
#
# Consider displaying only this value if it is non-null, and the
# `majority_reached` value only if this is null.
'special_process': q_issue.special_process,
# Translated, human-readable version of the result.
'special_process_human_readable': q_issue.get_special_process_display(),
# Comment count.
'comment_count': q_issue.comment_count,
# Vote count.
'vote_count': q_issue.votecount,
}
)

elections = []
for q_election in q_elections:
# See comments for issue above, which are more detailed but are mostly
# applicable to this section as well.
elections.append({
'url': request.build_absolute_uri(reverse('election', args=(q_election.polity_id, q_election.id))),
'polity': q_election.polity.name,
'polity_shortname': q_election.polity.name_short,
'name': q_election.name,
'state': q_election.election_state(),
'state_human_readable': q_election.get_election_state_display(),
'candidate_count': q_election.candidate_set.count(),
'vote_count': q_election.get_vote_count(),
})
elections.append(
{
'url': request.build_absolute_uri(
reverse(
'election', args=(q_election.polity_id, q_election.id)
)
),
'polity': q_election.polity.name,
'polity_shortname': q_election.polity.name_short,
'name': q_election.name,
'state': q_election.election_state(),
'state_human_readable': q_election.get_election_state_display(),
'candidate_count': q_election.candidate_set.count(),
'vote_count': q_election.get_vote_count(),
}
)

return {
'elections': elections,
Expand Down
22 changes: 16 additions & 6 deletions core/django_mdmail.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@

from django.conf import settings
from django.core.mail import EmailMultiAlternatives

if sys.version_info[0] == 3:
from email.mime.image import MIMEImage
else:
Expand All @@ -57,17 +58,24 @@
OVERRIDE_WARNING = 'WARNING! THIS FILE IS AUTO-GENERATED by django_mdmail upon Django startup. Changes to this file WILL be overwritten. In the same directory, there should be a file with the same name, except an ".md" ending (for Markdown). Edit that instead and restart Django.'


def send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None, connection=None, html_message=None):
def send_mail(
subject,
message,
from_email,
recipient_list,
fail_silently=False,
auth_user=None,
auth_password=None,
connection=None,
html_message=None,
):

# Have `mdmail` do its Markdown magic.
content = EmailContent(message)

# Create the email message and fill it with the relevant data.
email = EmailMultiAlternatives(
subject,
content.text,
from_email,
recipient_list
subject, content.text, from_email, recipient_list
)
email.attach_alternative(html_message or content.html, 'text/html')
email.mixed_subtype = 'related'
Expand Down Expand Up @@ -115,7 +123,9 @@ def ready(self):
convert_md_templates()
'''

override_comment = '{%% comment %%}%s{%% endcomment %%}\n' % OVERRIDE_WARNING
override_comment = (
'{%% comment %%}%s{%% endcomment %%}\n' % OVERRIDE_WARNING
)

# Find all the template directories we'll need to process and put them
# in a flat list.
Expand Down
Loading