This commit is contained in:
Dustin J. Mitchell 2021-01-21 20:15:05 +00:00 коммит произвёл Dustin J. Mitchell
Родитель b74fbe4d0c
Коммит 26457f8b31
14 изменённых файлов: 50 добавлений и 26 удалений

Просмотреть файл

@ -31,6 +31,11 @@ tasks:
command: >-
pip install -r requirements.txt &&
python3 manage.py test
- name: Python code style
image: python:3.9
command: >-
pip install pycodestyle &&
pycodestyle ./mentoring
each(opts):
provisionerId: 'proj-misc'
workerType: 'ci'

Просмотреть файл

@ -8,6 +8,7 @@ from django.test import Client
from ..participants.models import Participant
from .views import time_availability
class TimeAvailabilityTest(TestCase):
def test_no_avail(self):
@ -73,7 +74,7 @@ class PostTest(TestCase):
assert(p.full_name == 'Alex Doe')
assert(p.manager == 'Mana Jerr')
assert(p.manager_email == 'mjerr@mozilla.com')
assert(p.approved == None)
assert(p.approved is None)
assert(p.time_availability == 'YYYYYYNNNYYYNNNNNNNNNNNN')
assert(p.org == 'Firefox')
assert(p.org_level == 'P3')
@ -121,7 +122,7 @@ class PostTest(TestCase):
assert(p.full_name == 'Alex Doe')
assert(p.manager == 'Mana Jerr')
assert(p.manager_email == 'mjerr@mozilla.com')
assert(p.approved == None)
assert(p.approved is None)
assert(p.time_availability == 'NNNNNNNNNYYYNNNNNNNNNNNN')
assert(p.org == 'Firefox')
assert(p.org_level == 'P3')
@ -130,7 +131,7 @@ class PostTest(TestCase):
'Increasing Impact on Mozilla Mission',
'Public Speaking',
])
assert(p.track_change == None)
assert(p.track_change is None)
assert(p.org_chart_distance == 'Prefer distant')
assert(p.comments == 'asdf')

Просмотреть файл

@ -14,6 +14,7 @@ from ..participants.models import Participant
logger = logging.getLogger(__name__)
def time_availability(time_availability):
'''Parse a list of 'xx:00 - xx:00 UTC' strings into the 24-hour format in the model'''
rv = ['N'] * 24
@ -61,7 +62,6 @@ def parse_form(form):
)
@require_http_methods(["POST"])
@csrf_exempt
def webhook(request):

Просмотреть файл

@ -1,6 +1,7 @@
from django.shortcuts import render
from django.contrib.auth.decorators import user_passes_test
# Check that a user is authenticated; this automatically redirects un-authenticated
# users to the SSO login page (and right back if auto-login is enabled)
@user_passes_test(lambda user: user.is_authenticated)

Просмотреть файл

@ -2,12 +2,16 @@ from django.contrib import admin
from .models import Pair, HistoricalPair
class PairAdmin(admin.ModelAdmin):
list_display = ('mentor', 'learner', 'pair_id')
list_display = ('mentor', 'learner', 'pair_id')
admin.site.register(Pair, PairAdmin)
class HistoricalPairAdmin(admin.ModelAdmin):
list_display = ('pair_id',)
list_display = ('pair_id',)
admin.site.register(HistoricalPair, HistoricalPairAdmin)

Просмотреть файл

@ -8,6 +8,7 @@ from django.db import models
from ..participants.models import Participant
class Pair(models.Model):
"""
An active pairing in the program.
@ -31,7 +32,7 @@ class Pair(models.Model):
start_date = models.DateTimeField(
null=False,
default=lambda: datetime.datetime.now(pytz.UTC),
default=lambda: datetime.datetime.now(pytz.UTC),
help_text=dedent('''Date this pairing began''')
)

Просмотреть файл

@ -3,6 +3,7 @@ from rest_framework import serializers, viewsets, permissions, mixins
from .models import Pair
from ..participants.models import Participant
class PairSerializer(serializers.HyperlinkedModelSerializer):
mentor = serializers.PrimaryKeyRelatedField(
queryset=Participant.objects.all().filter(role=Participant.MENTOR))

Просмотреть файл

@ -8,10 +8,11 @@ from rest_framework.test import APIClient
from .models import Pair, HistoricalPair
from ..participants.models import Participant
class PairTest(TestCase):
def make_particips(self):
l = Participant(
learner = Participant(
expires=datetime.datetime.now(pytz.UTC),
email='llearner@mozilla.com',
role=Participant.LEARNER,
@ -20,9 +21,9 @@ class PairTest(TestCase):
manager_email='mshur@mozilla.com',
time_availability='N' * 24,
)
l.save()
learner.save()
m = Participant(
mentor = Participant(
expires=datetime.datetime.now(pytz.UTC),
email='mmentor@mozilla.com',
role=Participant.MENTOR,
@ -31,13 +32,13 @@ class PairTest(TestCase):
manager_email='mshur@mozilla.com',
time_availability='N' * 24,
)
m.save()
mentor.save()
return l, m
return learner, mentor
def test_model_make_pair(self):
l, m = self.make_particips()
p = Pair(learner=l, mentor=m)
learner, mentor = self.make_particips()
p = Pair(learner=learner, mentor=mentor)
p.save()
self.assertEqual(p.learner.email, 'llearner@mozilla.com')
@ -53,7 +54,7 @@ class PairTest(TestCase):
self.assertTrue(HistoricalPair.already_paired(p))
def test_make_pair_rest_mentor_as_learner(self):
l, m = self.make_particips()
learner, mentor = self.make_particips()
client = APIClient()
user = User.objects.create_superuser('test')
@ -62,6 +63,6 @@ class PairTest(TestCase):
res = client.post(
'/api/pairs',
# note that these are reversed
{'mentor': l.id, 'learner': m.id},
{'mentor': learner.id, 'learner': mentor.id},
format='json')
self.assertEqual(res.status_code, 400)

Просмотреть файл

@ -14,7 +14,7 @@ def validate_time_availability(time_availability):
def validate_interests(interests):
if type(interests) != list:
raise ValidationError('interests must be a list')
if any(type(i) != type('') for i in interests):
if any(not isinstance(i, str) for i in interests):
raise ValidationError('interests must contain strings')
@ -45,7 +45,7 @@ class Participant(models.Model):
help_text=dedent('''\
The participant's role in the program. Note that the same email may appear
at most once in each role.'''),
)
)
full_name = models.CharField(null=False, max_length=512, help_text=dedent('''\
The participant's full name (as they would prefer to be called).'''))
@ -67,7 +67,7 @@ class Participant(models.Model):
help_text=dedent('''\
The participant's time availability, as a sequence of Y and N for each UTC hour,
so `NNNYYYYYYYYYNNNNNNNNNNNN` indicates availability from 03:00-12:00 UTC.'''),
)
)
org = models.CharField(max_length=100, null=True, help_text=dedent('''\
Participant's organization (roughly, executive to whom they report)'''))
@ -78,11 +78,14 @@ class Participant(models.Model):
time_at_org_level = models.CharField(max_length=10, null=True, help_text=dedent('''\
Participant's time at current organizational level, e.g., `2-3 y`'''))
interests = models.JSONField(null=True, blank=False, help_text=dedent('''\
A learner's areas of interest, or a mentor's areas in which they can offer mentorship;
format is an array of open-text strings.'''),
interests = models.JSONField(
null=True,
blank=False,
help_text=dedent('''\
A learner's areas of interest, or a mentor's areas in which they can offer mentorship;
format is an array of open-text strings.'''),
validators=[validate_interests],
)
)
track_change = models.CharField(null=True, max_length=64, help_text=dedent('''\
Whether the participant is interested in changing tracks (between IC and Manager)'''))
@ -92,13 +95,13 @@ class Participant(models.Model):
null=True,
blank=False,
help_text=dedent('''Preference for a pairing nearby or distant in the org chart (open text)''')
)
)
comments = models.TextField(
null=False,
blank=True,
help_text=dedent('''Open comments from the participant's enrollment'''),
)
)
class Meta:
db_table = "participants"

Просмотреть файл

@ -2,6 +2,7 @@ from rest_framework import serializers, viewsets, permissions
from .models import Participant
class ParticipantSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Participant

Просмотреть файл

@ -5,6 +5,7 @@ from configurations import Configuration, values
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
class Base(Configuration):
# Application definition
@ -98,6 +99,7 @@ class Base(Configuration):
STATIC_URL = '/static/'
STATICFILES_DIRS = [BASE_DIR / "static"]
class Production(Base):
DEBUG = False

Просмотреть файл

@ -4,6 +4,7 @@ from django.test import TestCase
from .auth import MentoringAuthBackend
class Auth(TestCase):
def get_username(self):

Просмотреть файл

@ -16,7 +16,7 @@ urlpatterns = [
# if (and only if) we are in DEBUG mode (meaning Development), we allow
# users to sign in using simple Django auth
] + ([path('accounts/', include('django.contrib.auth.urls'))] if settings.DEBUG else []) + [
] + ([path('accounts/', include('django.contrib.auth.urls'))] if settings.DEBUG else []) + [
# ..and anything else renders the frontend
path('', include('mentoring.frontend.urls')),

3
setup.cfg Normal file
Просмотреть файл

@ -0,0 +1,3 @@
[pycodestyle]
# E501 = line length
ignore = E501