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

Control registration #156

Merged
merged 8 commits into from
Dec 31, 2021
Merged
Show file tree
Hide file tree
Changes from 7 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
59 changes: 37 additions & 22 deletions rudaux/flows.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import sys, os
import sys
import os
import prefect
from prefect import Flow, unmapped, task, flatten
from prefect import Flow, unmapped, task
from prefect.engine import signals
from prefect.schedules import IntervalSchedule
from prefect.executors import LocalExecutor, DaskExecutor, LocalDaskExecutor
from prefect.executors import LocalExecutor
from prefect.backend import FlowView, FlowRunView
from prefect.tasks.control_flow.filter import FilterTask
from traitlets.config import Config
from traitlets.config.loader import PyFileConfigLoader
import pendulum as plm
from requests.exceptions import ConnectionError
import logging
from subprocess import check_output, STDOUT, CalledProcessError
from subprocess import check_output, CalledProcessError

import threading

Expand All @@ -28,16 +28,17 @@

__PROJECT_NAME = "rudaux"


def _build_flows(args):
print("Loading the rudaux_config.py file...")
if not os.path.exists(os.path.join(args.directory, 'rudaux_config.py')):
sys.exit(
f"""
There is no rudaux_config.py in the directory {args.directory},
and no course directory was specified on the command line. Please
specify a directory with a valid rudaux_config.py file.
"""
)
sys.exit(
f"""
There is no rudaux_config.py in the directory {args.directory},
and no course directory was specified on the command line. Please
specify a directory with a valid rudaux_config.py file.
"""
)
config = Config()
config.merge(PyFileConfigLoader('rudaux_config.py', path=args.directory).load_config())

Expand Down Expand Up @@ -100,14 +101,13 @@ def register(args):
except ConnectionError as e:
print(e)
sys.exit(
f"""
Could not connect to the prefect server. Is the server running?
Make sure to start the server before trying to register flows.
To start the prefect server, run the command:
"""
Could not connect to the prefect server. Is the server running?
Make sure to start the server before trying to register flows.
To start the prefect server, run the command:

prefect server start

"""
prefect server start
"""
)
flows = _build_flows(args)
for flow in flows:
Expand Down Expand Up @@ -155,16 +155,31 @@ def build_snapshot_flows(config, args):
flows.append(flow)
return flows


@task(checkpoint=False)
def combine_dictionaries(dicts):
return {k : v for d in dicts for k, v in d.items()}
return {k: v for d in dicts for k, v in d.items()}


def build_autoext_flows(config, args):
trevorcampbell marked this conversation as resolved.
Show resolved Hide resolved
"""
Build the flow for the auto-extension of assignments for students
who register late.

Params
------
config: traitlets.config.loader.Config
a dictionary-like object containing the configurations
from rudaux_config.py
"""
flows = []
for group in config.course_groups:
for course_id in config.course_groups[group]:
with Flow(config.course_names[course_id]+"-autoext", terminal_state_handler = fail_handler_gen(config)) as flow:
with Flow(config.course_names[course_id] + "-autoext",
terminal_state_handler=fail_handler_gen(config)) as flow:

assignment_names = list(config.assignments[group].keys())

# Obtain course/student/assignment/etc info from the course API
course_info = api.get_course_info(config, course_id)
assignments = api.get_assignments(config, course_id, assignment_names)
Expand All @@ -178,7 +193,7 @@ def build_autoext_flows(config, args):
submission_sets = subm.build_submission_set.map(unmapped(config), submission_sets)

# Compute override updates
overrides = subm.get_latereg_overrides.map(unmapped(config.latereg_extension_days[group]), submission_sets)
overrides = subm.get_latereg_overrides.map(unmapped(config.latereg_extension_days[group]), submission_sets, unmapped(config))

# TODO: we would ideally do flatten(overrides) and then
# api.update_override.map(unmapped(config), unmapped(course_id), flatten(overrides))
Expand Down
4 changes: 2 additions & 2 deletions rudaux/submission.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ def generate_latereg_overrides_name(extension_days, subm_set, **kwargs):
return 'lateregs-'+subm_set['__name__']

@task(checkpoint=False,task_run_name=generate_latereg_overrides_name)
def get_latereg_overrides(extension_days, subm_set):
def get_latereg_overrides(extension_days, subm_set, config):
logger = get_logger()
fmt = 'ddd YYYY-MM-DD HH:mm:ss'
overrides = []
Expand All @@ -234,7 +234,7 @@ def get_latereg_overrides(extension_days, subm_set):

to_remove = None
to_create = None
if regdate > assignment['unlock_at']:
if regdate > assignment['unlock_at'] and assignment['unlock_at'] <= plm.from_format(config.registration_deadline, f'YYYY-MM-DD', tz=config.notify_timezone):
#the late registration due date
latereg_date = regdate.add(days=extension_days).in_timezone(tz).end_of('day').set(microsecond=0)
if latereg_date > subm['due_at']:
Expand Down
24 changes: 14 additions & 10 deletions scripts/rudaux_config_template.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,34 @@
import rudaux


# the base domain for canvas at your institution
# e.g. at UBC, this is https://canvas.ubc.ca
c.canvas_domain = 'https://canvas.your-domain.com'

# tells rudaux which courses are part of which groups
#group_name is a simple name for the group of canvas courses.
#e.g.
# group_name is a simple name for the group of canvas courses.
# e.g.
# "dsci100" : ["12345", "678910"]
# "stat201" : ["54323"]
c.course_groups = {
'group_name' : ['canvas_id_1', 'canvas_id_2']
'group_name': ['canvas_id_1', 'canvas_id_2']
}

# tells rudaux what to call each course when printing to logs
# canvas_id_1/2/etc are the same as above
# human_readable_name_1/2/etc is just a human-readable name for each section,
# human_readable_name_1/2/etc is just a human-readable name for each section
# (e.g., human_readable_name_1 and 2 would be dsci100-001 and dsci100-004 for
# the two dsci100 sections)
# make sure you include names for every canvas ID above
# e.g.
# e.g.
# {"12345" : "dsci100-001", "678910" : "dsci100-004"}
c.course_names = {
'canvas_id_1' : 'human_readable_name_1', #e.g. human_readable_name_1 and 2 would be dsci100-001 and dsci100-004 (for the two dsci100 sections)
'canvas_id_2' : 'human_readable_name_2',
'canvas_id_1': 'human_readable_name_1',
'canvas_id_2': 'human_readable_name_2',
}

# tells rudaux the last day students have to add a course.
# at UBC we can check it here:
# https://students.ubc.ca/enrolment/registration/course-change-dates
c.registration_deadline = '2022-01-21'

# gives rudaux the ability to read/write to canvas page
# canvas_id_1/2/etc are same as above
# instructor_token_1/2/etc are the Canvas API tokens for the instructor of each section
Expand Down