def test_compute_single_clause_diff(): from decimal import Decimal ctx = RequirementContext(areas=(AreaPointer.with_code('711'),)) assert compute_single_clause_diff({'has-area-code(711)': '+ 0.50'}, ctx=ctx) == Decimal(0.5) assert compute_single_clause_diff({'has-area-code(711)': '+ .50'}, ctx=ctx) == Decimal(0.5) with pytest.raises(TypeError, match=r'unknown \$ifs key unknown-key'): assert compute_single_clause_diff({'unknown-key(711)': '+ .50'}, ctx=ctx) == Decimal(0) ctx = RequirementContext( areas=(AreaPointer.with_code('711'),), music_proficiencies=MusicProficiencies(keyboard_3=True, keyboard_4=False), ) assert compute_single_clause_diff({'has-area-code(711) + passed-proficiency-exam(Keyboard Level III)': '+ 0.50'}, ctx=ctx) == Decimal(0.5) assert compute_single_clause_diff({'has-area-code(711) + passed-proficiency-exam(Keyboard Level IV)': '+ .50'}, ctx=ctx) == Decimal(0) assert compute_single_clause_diff({ 'has-area-code(711)': '+ 0.50', 'has-area-code(711) + passed-proficiency-exam(Keyboard Level III)': '+ 0.50', }, ctx=ctx) == Decimal(1.0) assert compute_single_clause_diff({ 'has-area-code(711)': '+ 0.50', 'has-area-code(711) + passed-proficiency-exam(Keyboard Level IV)': '+ 0.50', }, ctx=ctx) == Decimal(0.5)
def test_count_courses_optimization(): ctx = RequirementContext() courses = [ course_from_str('A 101'), course_from_str('B 101'), course_from_str('C 101'), ] rule = QueryRule.load(path=[], c=c, ctx=ctx, data={ 'from': 'courses', 'assert': { 'count(courses)': { '$gte': 2 } }, }) results = list(iterate_item_set(courses, rule=rule)) assert results == [ tuple([courses[0], courses[1]]), tuple([courses[0], courses[2]]), tuple([courses[1], courses[2]]), tuple([courses[0], courses[1], courses[2]]), ]
def test_pred_and_expr(): ctx = RequirementContext( areas=(AreaPointer.with_code('711'), ), music_proficiencies=MusicProficiencies( keyboard_3=MusicProficiencyStatus.Exam, keyboard_4=MusicProficiencyStatus.No), ) both_true = { '$and': [ { 'has-declared-area-code': '711' }, { 'passed-proficiency-exam': 'Keyboard Level III' }, ] } actual = load_predicate_expression(both_true, ctx=ctx) assert actual.result is True assert isinstance(actual, PredicateExpressionCompoundAnd) area_but_not_exam = { '$and': [ { 'has-declared-area-code': '711' }, { 'passed-proficiency-exam': 'Keyboard Level IV' }, ] } assert load_predicate_expression(area_but_not_exam, ctx=ctx).result is False
def init_kwargs(*, course='AMCON 101', path): return { 'context': RequirementContext(), 'course': course_from_str(course), 'allow_claimed': False, 'path': tuple(path), }
def test_pred_expr_passed_proficiency_exam(): ctx = RequirementContext(music_proficiencies=MusicProficiencies( keyboard_3=MusicProficiencyStatus.Exam)) assert load_predicate_expression( { 'passed-proficiency-exam': 'Keyboard Level III' }, ctx=ctx).result is True
def test_load_predicate_expression(): ctx = RequirementContext(areas=(AreaPointer.with_code('711'), )) with pytest.raises( TypeError, match=r"unknown predicate expression \{'unknown-key': '711'\}"): assert load_predicate_expression({'unknown-key': '711'}, ctx=ctx)
def test_load_predicate_constant_expands_to_several_nested(): ppm = tuple(['saxophone', 'jazz saxophone']) constants = Constants(primary_performing_medium=ppm) ctx = RequirementContext() input_data = {'name': {'$in': ['piano', '$primary-performing-medium']}} c = load_predicate(input_data, c=constants, mode=DataType.Course, ctx=ctx) assert isinstance(c, Predicate) assert list(c.expected) == ['piano', 'saxophone', 'jazz saxophone']
def test_pred_expr_has_area_code(): ctx = RequirementContext(areas=(AreaPointer.with_code('711'), )) assert load_predicate_expression({ 'has-declared-area-code': '711' }, ctx=ctx).result is True assert load_predicate_expression({ 'has-declared-area-code': '000' }, ctx=ctx).result is False
def test_pred_or_expr(): ctx = RequirementContext( areas=(AreaPointer.with_code('711'), ), music_proficiencies=MusicProficiencies( keyboard_3=MusicProficiencyStatus.Exam, keyboard_4=MusicProficiencyStatus.No), ) both_true = { '$or': [ { 'has-declared-area-code': '711' }, { 'passed-proficiency-exam': 'Keyboard Level III' }, ] } assert load_predicate_expression(both_true, ctx=ctx).result is True exam_but_not_area = { '$or': [ { 'has-declared-area-code': '000' }, { 'passed-proficiency-exam': 'Keyboard Level III' }, ] } assert load_predicate_expression(exam_but_not_area, ctx=ctx).result is True area_but_not_exam = { '$or': [ { 'has-declared-area-code': '711' }, { 'passed-proficiency-exam': 'Keyboard Level IV' }, ] } assert load_predicate_expression(area_but_not_exam, ctx=ctx).result is True both_false = { '$or': [ { 'has-declared-area-code': '000' }, { 'passed-proficiency-exam': 'Keyboard Level IV' }, ] } assert load_predicate_expression(both_false, ctx=ctx).result is False
def test_pred_expr_has_ip_course(): ctx = RequirementContext().with_transcript([ course_from_str('AMCON 101', in_progress=True), course_from_str('AMCON 102', in_progress=False), ]) assert load_predicate_expression({ 'has-ip-course': 'AMCON 101' }, ctx=ctx).result is True assert load_predicate_expression({ 'has-ip-course': 'AMCON 102' }, ctx=ctx).result is False
def test_claims__claimed(benchmark): course = course_from_str('AMCON 101') context = RequirementContext() kwargs = { 'course': course, 'allow_claimed': False, 'path': tuple(["$", "%Common Requirements", ".count", "[2]", "%Credits outside the major", ".query", ".assertions", "[0]", ".assert", '*AMCON 101']), } context.make_claim(**kwargs) benchmark(do_claim_2, context=context, **kwargs)
def test_su_during_covid_different_clause() -> None: ctx = RequirementContext() clause = load_predicate({"grade": {"$gte": "B"}}, c=c, mode=mode, ctx=ctx) assert isinstance(clause, Predicate) course = course_from_str( 'CSCI 251', grade_code='S', grade_option=GradeOption.SU, su_grade_code='C', year=2019, term='3', ) assert apply_predicate__grade(course, clause) is False
def test_ranges_eq(caplog): caplog.set_level(logging.DEBUG) c = Constants(matriculation_year=2000) ctx = RequirementContext() x = Assertion.load({"assert": { "count(courses)": { "$eq": 1 } }}, c=c, ctx=ctx, data_type=DataType.Course, path=['$']) result = x.input_size_range(maximum=5) assert list(result) == [1]
def test_overlaps(caplog: Any) -> None: # caplog.set_level(logging.DEBUG) global c area = AreaOfStudy.load(c=c, specification={ "result": {"all": [ {"requirement": "Core"}, {"requirement": "Electives"}, ]}, "requirements": { "Core": { "result": {"all": [ {"course": "MUSIC 212"}, {"course": "MUSIC 214"}, ]}, }, "Electives": { "result": { "from": "courses", "where": { "$and": [ {"subject": {"$eq": "MUSIC"}}, {"level": {"$eq": [300]}}, ], }, "all": [ {"assert": {"count(courses)": {"$gte": 2}}}, ], }, }, }, }) transcript = [course_from_str(c) for c in ["MUSIC 212", "MUSIC 214", "MUSIC 301", "MUSIC 302"]] ctx = RequirementContext().with_transcript(transcript) area.result.find_independent_children(items=area.result.items, ctx=ctx) solutions = list(area.solutions(student=Student.load(dict(courses=transcript)), exceptions=[])) assert len(solutions) == 1 result = solutions[0].audit() assert result.ok() is True
def test_graded_during_covid() -> None: ctx = RequirementContext() clause = load_predicate({"grade": { "$gte": "C", "$during_covid": "C-" }}, c=c, mode=mode, ctx=ctx) assert isinstance(clause, Predicate) course = course_from_str( 'CSCI 251', grade_code='C', grade_option=GradeOption.Grade, year=2019, term='3', ) assert apply_predicate__grade(course, clause) is True
def test_clauses_in(caplog): caplog.set_level(logging.DEBUG) c = Constants(matriculation_year=2000) ctx = RequirementContext() course = course_from_str(s="CSCI 296") values = tuple([296, 298, 396, 398]) x = load_predicate({"number": { "$in": values }}, c=c, ctx=ctx, mode=DataType.Course) expected_single = Predicate.from_args(key="number", expected=values, original=values, operator=Operator.In) assert x == expected_single assert x.apply(course) is True
def test_clauses(caplog): caplog.set_level(logging.DEBUG) c = Constants(matriculation_year=2000) ctx = RequirementContext() x = load_predicate({"attributes": { "$eq": "csci_elective" }}, c=c, ctx=ctx, mode=DataType.Course) expected_single = Predicate.from_args(key="attributes", expected="csci_elective", original="csci_elective", operator=Operator.EqualTo) assert x == expected_single crs = course_from_str(s="CSCI 121", attributes=["csci_elective"]) assert x.apply(crs) is True
def test_resolution(caplog): caplog.set_level(logging.DEBUG) c = Constants(matriculation_year=2000) ctx = RequirementContext() x = Assertion.load({"assert": { "count(items)": { "$eq": 1 } }}, c=c, ctx=ctx, data_type=DataType.Recital, path=['$']) result = x.audit_and_resolve(tuple([IntThing()]), ctx=ctx) assert result.ok() is True result = x.audit_and_resolve(tuple([IntThing(), IntThing()]), ctx=ctx) assert result.ok() is False
def test_pred_expr_has_course(): ctx = RequirementContext().with_transcript([course_from_str('AMCON 101')]) assert load_predicate_expression({ 'has-course': 'AMCON 101' }, ctx=ctx).result is True
def test_ranges_eq_2(caplog): """ensure that a solution with fewer matching courses than requested is still proposed""" caplog.set_level(logging.DEBUG) c = Constants(matriculation_year=2000) ctx = RequirementContext() result = Assertion.load({ "assert": { "count(courses)": { "$eq": 3 } } }, c=c, ctx=ctx, data_type=DataType.Course, path=['$']).input_size_range(maximum=2) assert list(result) == [2] result = Assertion.load({ "assert": { "count(courses)": { "$neq": 3 } } }, c=c, ctx=ctx, data_type=DataType.Course, path=['$']).input_size_range(maximum=2) assert list(result) == [0, 1, 2] result = Assertion.load({ "assert": { "count(courses)": { "$lt": 3 } } }, c=c, ctx=ctx, data_type=DataType.Course, path=['$']).input_size_range(maximum=2) assert list(result) == [0, 1, 2] result = Assertion.load({ "assert": { "count(courses)": { "$lte": 3 } } }, c=c, ctx=ctx, data_type=DataType.Course, path=['$']).input_size_range(maximum=2) assert list(result) == [0, 1, 2, 3] result = Assertion.load({ "assert": { "count(courses)": { "$gt": 3 } } }, c=c, ctx=ctx, data_type=DataType.Course, path=['$']).input_size_range(maximum=2) assert list(result) == [2] result = Assertion.load({ "assert": { "count(courses)": { "$gte": 3 } } }, c=c, ctx=ctx, data_type=DataType.Course, path=['$']).input_size_range(maximum=2) assert list(result) == [2]