diff --git a/.basedpyright/baseline.json b/.basedpyright/baseline.json index 28c002000..a322913fe 100644 --- a/.basedpyright/baseline.json +++ b/.basedpyright/baseline.json @@ -13049,7 +13049,7 @@ "code": "reportUnknownVariableType", "range": { "startColumn": 4, - "endColumn": 9, + "endColumn": 27, "lineCount": 1 } }, @@ -13093,12 +13093,76 @@ "lineCount": 5 } }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 4, + "endColumn": 25, + "lineCount": 1 + } + }, { "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 17, - "lineCount": 6 + "endColumn": 29, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 13, + "lineCount": 2 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 13, + "lineCount": 3 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 15, + "lineCount": 4 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 22, + "lineCount": 5 + } + }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 4, + "endColumn": 9, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 19, + "endColumn": 48, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 19, + "endColumn": 80, + "lineCount": 1 } }, { @@ -13129,7 +13193,7 @@ "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 13, + "endColumn": 15, "lineCount": 2 } }, @@ -13137,16 +13201,16 @@ "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 18, - "lineCount": 3 + "endColumn": 15, + "lineCount": 8 } }, { "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 15, - "lineCount": 4 + "endColumn": 17, + "lineCount": 9 } }, { @@ -13154,23 +13218,63 @@ "range": { "startColumn": 8, "endColumn": 17, - "lineCount": 5 + "lineCount": 10 } }, { "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 17, - "lineCount": 6 + "endColumn": 15, + "lineCount": 11 } }, { "code": "reportUnknownMemberType", "range": { - "startColumn": 8, - "endColumn": 15, - "lineCount": 7 + "startColumn": 16, + "endColumn": 27, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 16, + "endColumn": 31, + "lineCount": 1 + } + }, + { + "code": "reportUnknownArgumentType", + "range": { + "startColumn": 16, + "endColumn": 70, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 16, + "endColumn": 33, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 16, + "endColumn": 37, + "lineCount": 1 + } + }, + { + "code": "reportUnknownArgumentType", + "range": { + "startColumn": 16, + "endColumn": 74, + "lineCount": 1 } }, { @@ -13425,7 +13529,7 @@ "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 13, + "endColumn": 15, "lineCount": 2 } }, @@ -13433,24 +13537,24 @@ "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 18, - "lineCount": 3 + "endColumn": 15, + "lineCount": 8 } }, { "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 15, - "lineCount": 4 + "endColumn": 17, + "lineCount": 9 } }, { "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 17, - "lineCount": 5 + "endColumn": 16, + "lineCount": 10 } }, { @@ -13458,7 +13562,7 @@ "range": { "startColumn": 8, "endColumn": 16, - "lineCount": 6 + "lineCount": 15 } }, { @@ -13466,23 +13570,63 @@ "range": { "startColumn": 8, "endColumn": 16, - "lineCount": 11 + "lineCount": 16 } }, { "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 16, - "lineCount": 12 + "endColumn": 12, + "lineCount": 17 } }, { "code": "reportUnknownMemberType", "range": { - "startColumn": 8, - "endColumn": 12, - "lineCount": 13 + "startColumn": 16, + "endColumn": 27, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 16, + "endColumn": 31, + "lineCount": 1 + } + }, + { + "code": "reportUnknownArgumentType", + "range": { + "startColumn": 16, + "endColumn": 70, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 16, + "endColumn": 33, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 16, + "endColumn": 37, + "lineCount": 1 + } + }, + { + "code": "reportUnknownArgumentType", + "range": { + "startColumn": 16, + "endColumn": 74, + "lineCount": 1 } }, { @@ -14305,7 +14449,7 @@ "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 13, + "endColumn": 15, "lineCount": 2 } }, @@ -14314,39 +14458,79 @@ "range": { "startColumn": 8, "endColumn": 18, - "lineCount": 3 + "lineCount": 8 } }, { "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 18, - "lineCount": 4 + "endColumn": 17, + "lineCount": 9 } }, { "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 17, - "lineCount": 5 + "endColumn": 15, + "lineCount": 10 } }, { "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 15, - "lineCount": 6 + "endColumn": 14, + "lineCount": 11 } }, { "code": "reportUnknownMemberType", "range": { - "startColumn": 8, - "endColumn": 14, - "lineCount": 7 + "startColumn": 16, + "endColumn": 27, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 16, + "endColumn": 31, + "lineCount": 1 + } + }, + { + "code": "reportUnknownArgumentType", + "range": { + "startColumn": 16, + "endColumn": 70, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 16, + "endColumn": 33, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 16, + "endColumn": 37, + "lineCount": 1 + } + }, + { + "code": "reportUnknownArgumentType", + "range": { + "startColumn": 16, + "endColumn": 74, + "lineCount": 1 } }, { @@ -19163,6 +19347,54 @@ "lineCount": 5 } }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 38, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 13, + "lineCount": 2 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 13, + "lineCount": 3 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 22, + "lineCount": 4 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 12, + "lineCount": 5 + } + }, + { + "code": "reportUnknownArgumentType", + "range": { + "startColumn": 8, + "endColumn": 14, + "lineCount": 5 + } + }, { "code": "reportUnknownVariableType", "range": { @@ -23011,6 +23243,150 @@ "lineCount": 1 } }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 4, + "endColumn": 37, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 24, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 15, + "lineCount": 2 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 17, + "lineCount": 3 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 15, + "lineCount": 4 + } + }, + { + "code": "reportUnknownArgumentType", + "range": { + "startColumn": 8, + "endColumn": 60, + "lineCount": 4 + } + }, + { + "code": "reportAny", + "range": { + "startColumn": 39, + "endColumn": 49, + "lineCount": 1 + } + }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 4, + "endColumn": 45, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 24, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 15, + "lineCount": 2 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 13, + "lineCount": 3 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 17, + "lineCount": 4 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 15, + "lineCount": 5 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 15, + "lineCount": 6 + } + }, + { + "code": "reportUnknownArgumentType", + "range": { + "startColumn": 8, + "endColumn": 71, + "lineCount": 6 + } + }, + { + "code": "reportAny", + "range": { + "startColumn": 16, + "endColumn": 26, + "lineCount": 1 + } + }, + { + "code": "reportAny", + "range": { + "startColumn": 39, + "endColumn": 49, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 50, + "endColumn": 67, + "lineCount": 1 + } + }, { "code": "reportUnknownVariableType", "range": { @@ -23055,7 +23431,15 @@ "code": "reportUnknownVariableType", "range": { "startColumn": 15, - "endColumn": 67, + "endColumn": 69, + "lineCount": 3 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 12, + "endColumn": 49, "lineCount": 1 } }, @@ -23071,7 +23455,15 @@ "code": "reportUnknownVariableType", "range": { "startColumn": 15, - "endColumn": 75, + "endColumn": 77, + "lineCount": 3 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 12, + "endColumn": 57, "lineCount": 1 } }, @@ -23087,7 +23479,15 @@ "code": "reportUnknownVariableType", "range": { "startColumn": 15, - "endColumn": 66, + "endColumn": 69, + "lineCount": 3 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 12, + "endColumn": 49, "lineCount": 1 } }, @@ -23103,7 +23503,15 @@ "code": "reportUnknownVariableType", "range": { "startColumn": 15, - "endColumn": 74, + "endColumn": 77, + "lineCount": 3 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 12, + "endColumn": 57, "lineCount": 1 } }, @@ -25881,20 +26289,12 @@ "lineCount": 5 } }, - { - "code": "reportUnknownMemberType", - "range": { - "startColumn": 16, - "endColumn": 23, - "lineCount": 6 - } - }, { "code": "reportUnknownMemberType", "range": { "startColumn": 16, "endColumn": 20, - "lineCount": 7 + "lineCount": 6 } }, { @@ -30199,48 +30599,64 @@ "code": "reportUnknownMemberType", "range": { "startColumn": 16, - "endColumn": 35, + "endColumn": 36, "lineCount": 1 } }, { "code": "reportUnknownMemberType", "range": { - "startColumn": 20, - "endColumn": 52, + "startColumn": 16, + "endColumn": 40, "lineCount": 1 } }, { "code": "reportUnknownMemberType", "range": { - "startColumn": 20, - "endColumn": 25, - "lineCount": 2 + "startColumn": 24, + "endColumn": 35, + "lineCount": 1 } }, { "code": "reportUnknownMemberType", "range": { - "startColumn": 20, - "endColumn": 34, - "lineCount": 3 + "startColumn": 24, + "endColumn": 39, + "lineCount": 1 + } + }, + { + "code": "reportUnknownArgumentType", + "range": { + "startColumn": 24, + "endColumn": 78, + "lineCount": 1 } }, { "code": "reportUnknownMemberType", "range": { - "startColumn": 20, - "endColumn": 29, - "lineCount": 4 + "startColumn": 24, + "endColumn": 41, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 24, + "endColumn": 45, + "lineCount": 1 } }, { "code": "reportUnknownArgumentType", "range": { - "startColumn": 20, - "endColumn": 31, - "lineCount": 4 + "startColumn": 24, + "endColumn": 82, + "lineCount": 1 } }, { @@ -30872,7 +31288,7 @@ "range": { "startColumn": 16, "endColumn": 25, - "lineCount": 12 + "lineCount": 10 } }, { @@ -30880,7 +31296,7 @@ "range": { "startColumn": 16, "endColumn": 23, - "lineCount": 13 + "lineCount": 11 } }, { @@ -30888,7 +31304,7 @@ "range": { "startColumn": 16, "endColumn": 84, - "lineCount": 13 + "lineCount": 11 } }, { @@ -30904,7 +31320,7 @@ "range": { "startColumn": 20, "endColumn": 21, - "lineCount": 9 + "lineCount": 7 } }, { @@ -30923,20 +31339,12 @@ "lineCount": 2 } }, - { - "code": "reportUnknownMemberType", - "range": { - "startColumn": 24, - "endColumn": 31, - "lineCount": 4 - } - }, { "code": "reportUnknownMemberType", "range": { "startColumn": 24, "endColumn": 34, - "lineCount": 5 + "lineCount": 3 } }, { @@ -30944,7 +31352,7 @@ "range": { "startColumn": 24, "endColumn": 38, - "lineCount": 6 + "lineCount": 4 } }, { @@ -30952,7 +31360,7 @@ "range": { "startColumn": 24, "endColumn": 33, - "lineCount": 7 + "lineCount": 5 } }, { @@ -30960,7 +31368,7 @@ "range": { "startColumn": 24, "endColumn": 35, - "lineCount": 7 + "lineCount": 5 } }, { @@ -31787,6 +32195,30 @@ "lineCount": 1 } }, + { + "code": "reportCallIssue", + "range": { + "startColumn": 12, + "endColumn": 20, + "lineCount": 1 + } + }, + { + "code": "reportCallIssue", + "range": { + "startColumn": 12, + "endColumn": 20, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 22, + "lineCount": 1 + } + }, { "code": "reportUnknownVariableType", "range": { @@ -32685,6 +33117,54 @@ "lineCount": 1 } }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 8, + "endColumn": 29, + "lineCount": 1 + } + }, + { + "code": "reportCallIssue", + "range": { + "startColumn": 12, + "endColumn": 34, + "lineCount": 1 + } + }, + { + "code": "reportArgumentType", + "range": { + "startColumn": 12, + "endColumn": 34, + "lineCount": 1 + } + }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 8, + "endColumn": 31, + "lineCount": 1 + } + }, + { + "code": "reportUnknownArgumentType", + "range": { + "startColumn": 39, + "endColumn": 65, + "lineCount": 1 + } + }, + { + "code": "reportUnknownArgumentType", + "range": { + "startColumn": 43, + "endColumn": 64, + "lineCount": 1 + } + }, { "code": "reportUnknownMemberType", "range": { @@ -32829,6 +33309,14 @@ "lineCount": 1 } }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 50, + "endColumn": 58, + "lineCount": 1 + } + }, { "code": "reportUnknownVariableType", "range": { @@ -32845,6 +33333,14 @@ "lineCount": 1 } }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 50, + "endColumn": 58, + "lineCount": 1 + } + }, { "code": "reportUnknownMemberType", "range": { @@ -34484,32 +34980,16 @@ { "code": "reportUnknownMemberType", "range": { - "startColumn": 69, - "endColumn": 84, - "lineCount": 1 - } - }, - { - "code": "reportUnknownMemberType", - "range": { - "startColumn": 11, - "endColumn": 49, + "startColumn": 50, + "endColumn": 65, "lineCount": 1 } }, { "code": "reportUnknownMemberType", "range": { - "startColumn": 16, - "endColumn": 31, - "lineCount": 1 - } - }, - { - "code": "reportUnknownArgumentType", - "range": { - "startColumn": 16, - "endColumn": 31, + "startColumn": 50, + "endColumn": 71, "lineCount": 1 } }, @@ -34733,15 +35213,15 @@ "code": "reportUnknownVariableType", "range": { "startColumn": 4, - "endColumn": 31, + "endColumn": 21, "lineCount": 1 } }, { "code": "reportUnknownMemberType", "range": { - "startColumn": 8, - "endColumn": 26, + "startColumn": 24, + "endColumn": 36, "lineCount": 1 } }, @@ -34749,16 +35229,8 @@ "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 13, - "lineCount": 9 - } - }, - { - "code": "reportUnknownMemberType", - "range": { - "startColumn": 8, - "endColumn": 13, - "lineCount": 10 + "endColumn": 24, + "lineCount": 1 } }, { @@ -34766,7 +35238,7 @@ "range": { "startColumn": 8, "endColumn": 15, - "lineCount": 11 + "lineCount": 2 } }, { @@ -34774,15 +35246,7 @@ "range": { "startColumn": 8, "endColumn": 13, - "lineCount": 12 - } - }, - { - "code": "reportUnknownMemberType", - "range": { - "startColumn": 8, - "endColumn": 18, - "lineCount": 13 + "lineCount": 3 } }, { @@ -34790,31 +35254,23 @@ "range": { "startColumn": 8, "endColumn": 15, - "lineCount": 14 - } - }, - { - "code": "reportUnknownMemberType", - "range": { - "startColumn": 8, - "endColumn": 18, - "lineCount": 15 + "lineCount": 4 } }, { - "code": "reportUnknownMemberType", + "code": "reportUnknownArgumentType", "range": { "startColumn": 8, - "endColumn": 17, - "lineCount": 22 + "endColumn": 25, + "lineCount": 4 } }, { - "code": "reportUnknownMemberType", + "code": "reportUnknownArgumentType", "range": { - "startColumn": 8, - "endColumn": 15, - "lineCount": 23 + "startColumn": 12, + "endColumn": 29, + "lineCount": 1 } }, { @@ -34873,6 +35329,102 @@ "lineCount": 4 } }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 8, + "endColumn": 20, + "lineCount": 1 + } + }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 4, + "endColumn": 31, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 26, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 13, + "lineCount": 2 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 13, + "lineCount": 3 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 15, + "lineCount": 4 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 13, + "lineCount": 5 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 18, + "lineCount": 6 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 15, + "lineCount": 7 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 18, + "lineCount": 8 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 17, + "lineCount": 15 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 15, + "lineCount": 16 + } + }, { "code": "reportUnknownMemberType", "range": { @@ -35121,78 +35673,6 @@ "lineCount": 1 } }, - { - "code": "reportUnknownVariableType", - "range": { - "startColumn": 8, - "endColumn": 24, - "lineCount": 1 - } - }, - { - "code": "reportUnknownMemberType", - "range": { - "startColumn": 12, - "endColumn": 44, - "lineCount": 1 - } - }, - { - "code": "reportUnknownMemberType", - "range": { - "startColumn": 12, - "endColumn": 17, - "lineCount": 4 - } - }, - { - "code": "reportUnknownMemberType", - "range": { - "startColumn": 12, - "endColumn": 17, - "lineCount": 5 - } - }, - { - "code": "reportUnknownMemberType", - "range": { - "startColumn": 12, - "endColumn": 19, - "lineCount": 6 - } - }, - { - "code": "reportUnknownArgumentType", - "range": { - "startColumn": 12, - "endColumn": 50, - "lineCount": 6 - } - }, - { - "code": "reportUnknownVariableType", - "range": { - "startColumn": 8, - "endColumn": 15, - "lineCount": 1 - } - }, - { - "code": "reportUnknownVariableType", - "range": { - "startColumn": 16, - "endColumn": 25, - "lineCount": 1 - } - }, - { - "code": "reportUnknownVariableType", - "range": { - "startColumn": 27, - "endColumn": 33, - "lineCount": 1 - } - }, { "code": "reportUnknownVariableType", "range": { @@ -35238,7 +35718,7 @@ "range": { "startColumn": 8, "endColumn": 15, - "lineCount": 5 + "lineCount": 4 } }, { @@ -35246,7 +35726,7 @@ "range": { "startColumn": 8, "endColumn": 17, - "lineCount": 11 + "lineCount": 5 } }, { @@ -35254,23 +35734,7 @@ "range": { "startColumn": 8, "endColumn": 15, - "lineCount": 12 - } - }, - { - "code": "reportUnknownArgumentType", - "range": { - "startColumn": 16, - "endColumn": 57, - "lineCount": 1 - } - }, - { - "code": "reportUnknownArgumentType", - "range": { - "startColumn": 16, - "endColumn": 69, - "lineCount": 1 + "lineCount": 6 } }, { @@ -36813,104 +37277,88 @@ "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 22, - "lineCount": 3 - } - }, - { - "code": "reportUnknownVariableType", - "range": { - "startColumn": 4, - "endColumn": 19, - "lineCount": 1 - } - }, - { - "code": "reportUnknownVariableType", - "range": { - "startColumn": 12, - "endColumn": 29, - "lineCount": 1 - } - }, - { - "code": "reportUnknownVariableType", - "range": { - "startColumn": 31, - "endColumn": 41, - "lineCount": 1 - } - }, - { - "code": "reportUnknownVariableType", - "range": { - "startColumn": 43, - "endColumn": 51, - "lineCount": 1 - } - }, - { - "code": "reportUnknownMemberType", - "range": { - "startColumn": 8, - "endColumn": 24, - "lineCount": 1 - } - }, - { - "code": "reportUnknownMemberType", - "range": { - "startColumn": 8, - "endColumn": 15, - "lineCount": 2 - } - }, - { - "code": "reportUnknownMemberType", - "range": { - "startColumn": 8, - "endColumn": 13, + "endColumn": 22, "lineCount": 3 } }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 4, + "endColumn": 19, + "lineCount": 1 + } + }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 12, + "endColumn": 29, + "lineCount": 1 + } + }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 31, + "endColumn": 41, + "lineCount": 1 + } + }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 43, + "endColumn": 51, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 24, + "lineCount": 1 + } + }, { "code": "reportUnknownMemberType", "range": { "startColumn": 8, "endColumn": 15, - "lineCount": 5 + "lineCount": 2 } }, { "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 22, - "lineCount": 11 + "endColumn": 13, + "lineCount": 3 } }, { - "code": "reportUnknownArgumentType", + "code": "reportUnknownMemberType", "range": { "startColumn": 8, - "endColumn": 53, - "lineCount": 11 + "endColumn": 18, + "lineCount": 4 } }, { - "code": "reportUnknownArgumentType", + "code": "reportUnknownMemberType", "range": { - "startColumn": 16, - "endColumn": 57, - "lineCount": 1 + "startColumn": 8, + "endColumn": 22, + "lineCount": 7 } }, { "code": "reportUnknownArgumentType", "range": { - "startColumn": 16, - "endColumn": 69, - "lineCount": 1 + "startColumn": 8, + "endColumn": 53, + "lineCount": 7 } }, { @@ -36953,6 +37401,102 @@ "lineCount": 1 } }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 4, + "endColumn": 11, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 24, + "lineCount": 1 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 15, + "lineCount": 2 + } + }, + { + "code": "reportUnknownMemberType", + "range": { + "startColumn": 8, + "endColumn": 22, + "lineCount": 3 + } + }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 4, + "endColumn": 19, + "lineCount": 1 + } + }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 12, + "endColumn": 29, + "lineCount": 1 + } + }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 31, + "endColumn": 41, + "lineCount": 1 + } + }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 43, + "endColumn": 51, + "lineCount": 1 + } + }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 4, + "endColumn": 19, + "lineCount": 1 + } + }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 12, + "endColumn": 29, + "lineCount": 1 + } + }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 31, + "endColumn": 41, + "lineCount": 1 + } + }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 43, + "endColumn": 51, + "lineCount": 1 + } + }, { "code": "reportUnknownVariableType", "range": { @@ -36965,7 +37509,7 @@ "code": "reportUnknownMemberType", "range": { "startColumn": 28, - "endColumn": 49, + "endColumn": 50, "lineCount": 1 } }, @@ -37114,18 +37658,18 @@ } }, { - "code": "reportAny", + "code": "reportUnknownVariableType", "range": { - "startColumn": 20, - "endColumn": 21, + "startColumn": 12, + "endColumn": 30, "lineCount": 1 } }, { "code": "reportUnknownMemberType", "range": { - "startColumn": 35, - "endColumn": 52, + "startColumn": 60, + "endColumn": 77, "lineCount": 1 } }, @@ -37405,23 +37949,31 @@ "code": "reportUnknownMemberType", "range": { "startColumn": 28, - "endColumn": 49, + "endColumn": 50, "lineCount": 1 } }, { - "code": "reportAny", + "code": "reportUnknownVariableType", "range": { - "startColumn": 20, - "endColumn": 21, + "startColumn": 12, + "endColumn": 48, "lineCount": 1 } }, { "code": "reportUnknownMemberType", "range": { - "startColumn": 35, - "endColumn": 52, + "startColumn": 60, + "endColumn": 77, + "lineCount": 1 + } + }, + { + "code": "reportUnknownArgumentType", + "range": { + "startColumn": 19, + "endColumn": 55, "lineCount": 1 } }, @@ -52979,6 +53531,22 @@ "lineCount": 1 } }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 4, + "endColumn": 15, + "lineCount": 1 + } + }, + { + "code": "reportUnannotatedClassAttribute", + "range": { + "startColumn": 4, + "endColumn": 15, + "lineCount": 1 + } + }, { "code": "reportUnknownVariableType", "range": { @@ -54363,6 +54931,46 @@ "lineCount": 1 } }, + { + "code": "reportUnannotatedClassAttribute", + "range": { + "startColumn": 4, + "endColumn": 12, + "lineCount": 1 + } + }, + { + "code": "reportUnknownVariableType", + "range": { + "startColumn": 4, + "endColumn": 9, + "lineCount": 1 + } + }, + { + "code": "reportUnannotatedClassAttribute", + "range": { + "startColumn": 4, + "endColumn": 9, + "lineCount": 1 + } + }, + { + "code": "reportUnannotatedClassAttribute", + "range": { + "startColumn": 4, + "endColumn": 12, + "lineCount": 1 + } + }, + { + "code": "reportUnannotatedClassAttribute", + "range": { + "startColumn": 4, + "endColumn": 18, + "lineCount": 1 + } + }, { "code": "reportUnannotatedClassAttribute", "range": { @@ -118135,6 +118743,14 @@ "lineCount": 5 } }, + { + "code": "reportUndefinedVariable", + "range": { + "startColumn": 50, + "endColumn": 69, + "lineCount": 1 + } + }, { "code": "reportUnknownVariableType", "range": { @@ -118239,6 +118855,14 @@ "lineCount": 5 } }, + { + "code": "reportUndefinedVariable", + "range": { + "startColumn": 50, + "endColumn": 69, + "lineCount": 1 + } + }, { "code": "reportUnknownVariableType", "range": { @@ -118287,6 +118911,14 @@ "lineCount": 5 } }, + { + "code": "reportUndefinedVariable", + "range": { + "startColumn": 50, + "endColumn": 69, + "lineCount": 1 + } + }, { "code": "reportUnknownVariableType", "range": { diff --git a/server/api/batches.py b/server/api/batches.py index 8bf8e5cf8..95d8e031d 100644 --- a/server/api/batches.py +++ b/server/api/batches.py @@ -5,7 +5,7 @@ from flask import jsonify, request, session from werkzeug.exceptions import BadRequest, Conflict from sqlalchemy.orm import Query, joinedload -from sqlalchemy import func +from sqlalchemy import func, or_ from . import api from ..auth import get_loggedin_user, get_support_user, restrict_access, UserType @@ -46,14 +46,21 @@ def replace_combined_batches_with_representative_batches( def already_audited_batches(jurisdiction: Jurisdiction, round: Round) -> Query: - query: Query = ( + sampled_in_prior_rounds = ( Batch.query.filter_by(jurisdiction_id=jurisdiction.id) .join(SampledBatchDraw) .join(Round) .filter(Round.round_num < round.round_num) .with_entities(Batch.id) - .subquery() ) + extra_in_prior_rounds = ( + Batch.query.filter_by(jurisdiction_id=jurisdiction.id) + .join(ExtraBatchDraw) + .join(Round) + .filter(Round.round_num < round.round_num) + .with_entities(Batch.id) + ) + query: Query = sampled_in_prior_rounds.union(extra_in_prior_rounds).subquery() return query @@ -67,8 +74,12 @@ def get_batch_retrieval_list( ): batches = ( Batch.query.filter_by(jurisdiction_id=jurisdiction.id) - .join(SampledBatchDraw) - .filter_by(round_id=round.id) + .filter( + or_( + Batch.draws.any(SampledBatchDraw.round_id == round.id), + Batch.extra_draws.any(ExtraBatchDraw.round_id == round.id), + ) + ) .filter(Batch.id.notin_(already_audited_batches(jurisdiction, round))) .group_by(Batch.id) .order_by(func.human_sort(Batch.name)) @@ -139,8 +150,12 @@ def list_batches_for_jurisdiction( ): batches = ( Batch.query.filter_by(jurisdiction_id=jurisdiction.id) - .join(SampledBatchDraw) - .filter_by(round_id=round.id) + .filter( + or_( + Batch.draws.any(SampledBatchDraw.round_id == round.id), + Batch.extra_draws.any(ExtraBatchDraw.round_id == round.id), + ) + ) .filter(Batch.id.notin_(already_audited_batches(jurisdiction, round))) .order_by(func.human_sort(Batch.name)) .options( @@ -366,8 +381,12 @@ def finalize_batch_results( num_batches_without_results = ( Batch.query.filter_by(jurisdiction_id=jurisdiction.id) - .join(SampledBatchDraw) - .filter_by(round_id=round.id) + .filter( + or_( + Batch.draws.any(SampledBatchDraw.round_id == round.id), + Batch.extra_draws.any(ExtraBatchDraw.round_id == round.id), + ) + ) .outerjoin(BatchResultTallySheet) .group_by(Batch.id) .having(func.count(BatchResultTallySheet.batch_id) == 0) diff --git a/server/api/discrepancies.py b/server/api/discrepancies.py index 37ac15897..2ef84ca43 100644 --- a/server/api/discrepancies.py +++ b/server/api/discrepancies.py @@ -74,6 +74,12 @@ def get_batch_comparison_discrepancies_by_jurisdiction( .join(Jurisdiction) .with_entities(Jurisdiction.name, Batch.name) .all() + ) | set( + ExtraBatchDraw.query.filter_by(round_id=round_id) + .join(Batch) + .join(Jurisdiction) + .with_entities(Jurisdiction.name, Batch.name) + .all() ) jurisdiction_name_to_id = dict( diff --git a/server/api/jurisdictions.py b/server/api/jurisdictions.py index d6bf46cf8..18569f282 100644 --- a/server/api/jurisdictions.py +++ b/server/api/jurisdictions.py @@ -501,6 +501,22 @@ def batch_round_status(election: Election, round: Round) -> dict[str, JSONDict]: .values(Batch.jurisdiction_id, func.count(Batch.id.distinct())) ) + extra_batch_count_by_jurisdiction = dict( + Batch.query.join(ExtraBatchDraw) + .filter(ExtraBatchDraw.round_id == round.id) + .group_by(Batch.jurisdiction_id) + .values(Batch.jurisdiction_id, func.count(Batch.id)) + ) + + audited_extra_batch_count_by_jurisdiction = dict( + Batch.query.join(ExtraBatchDraw) + .filter(ExtraBatchDraw.round_id == round.id) + .join(BatchResultTallySheet) + .group_by(Batch.jurisdiction_id) + .having(func.count(BatchResultTallySheet.id) > 0) + .values(Batch.jurisdiction_id, func.count(Batch.id.distinct())) + ) + finalized_jurisdiction_ids = { jurisdiction_id for (jurisdiction_id,) in BatchResultsFinalized.query.filter_by( @@ -509,16 +525,24 @@ def batch_round_status(election: Election, round: Round) -> dict[str, JSONDict]: } def num_samples(jurisdiction_id: str) -> int: - return sample_count_by_jurisdiction.get(jurisdiction_id, 0) + return sample_count_by_jurisdiction.get( + jurisdiction_id, 0 + ) + extra_batch_count_by_jurisdiction.get(jurisdiction_id, 0) def num_samples_audited(jurisdiction_id: str) -> int: - return audited_sample_count_by_jurisdiction.get(jurisdiction_id, 0) + return audited_sample_count_by_jurisdiction.get( + jurisdiction_id, 0 + ) + audited_extra_batch_count_by_jurisdiction.get(jurisdiction_id, 0) def num_batches(jurisdiction_id: str) -> int: - return batch_count_by_jurisdiction.get(jurisdiction_id, 0) + return batch_count_by_jurisdiction.get( + jurisdiction_id, 0 + ) + extra_batch_count_by_jurisdiction.get(jurisdiction_id, 0) def num_batches_audited(jurisdiction_id: str) -> int: - return audited_batch_count_by_jurisdiction.get(jurisdiction_id, 0) + return audited_batch_count_by_jurisdiction.get( + jurisdiction_id, 0 + ) + audited_extra_batch_count_by_jurisdiction.get(jurisdiction_id, 0) # NOT_STARTED = the jurisdiction hasn’t audited any batches yet # IN_PROGRESS = the jurisdiction is auditing batches diff --git a/server/api/reports.py b/server/api/reports.py index a4102ffdc..591c493f5 100644 --- a/server/api/reports.py +++ b/server/api/reports.py @@ -519,7 +519,6 @@ def round_rows(election: Election): .join(Jurisdiction) .filter_by(election_id=election.id) .filter(SampledBatchDraw.round_id == round.id) - .filter(SampledBatchDraw.ticket_number != EXTRA_TICKET_NUMBER) .all() ) sampled_batch_ids = {batch.id for batch in sampled_batches} diff --git a/server/api/rounds.py b/server/api/rounds.py index 055e60e17..1f755f625 100644 --- a/server/api/rounds.py +++ b/server/api/rounds.py @@ -3,7 +3,7 @@ from flask import jsonify, request from jsonschema import validate from werkzeug.exceptions import BadRequest, Conflict -from sqlalchemy import and_, func, not_ +from sqlalchemy import and_, func, not_, or_ from . import api @@ -64,11 +64,11 @@ def is_round_ready_to_finish(election: Election, round: Round) -> bool: num_jurisdictions_not_finalized: int = ( Jurisdiction.query.filter_by(election_id=election.id) .filter( - Jurisdiction.id.in_( - SampledBatchDraw.query.filter_by(round_id=round.id) - .join(Batch) - .with_entities(Batch.jurisdiction_id) - .subquery() + Jurisdiction.batches.any( + or_( + Batch.draws.any(SampledBatchDraw.round_id == round.id), + Batch.extra_draws.any(ExtraBatchDraw.round_id == round.id), + ) ) ) .filter( @@ -195,8 +195,6 @@ def count_audited_votes(election: Election, round: Round): BatchResult.tally_sheet_id.in_( BatchResultTallySheet.query.join(Batch) .join(SampledBatchDraw) - # Special case: don't include extra sampled batches - .filter(SampledBatchDraw.ticket_number != EXTRA_TICKET_NUMBER) .filter_by(round_id=round.id) .with_entities(BatchResultTallySheet.id) .subquery() @@ -356,8 +354,10 @@ def draw_sample_batches( round: Round, contest_sample_sizes: list[tuple[Contest, SampleSize]], ): - sample = compute_sample_batches(election, round.round_num, contest_sample_sizes) - for batch_draw in sample: + rla_sample_batches, extra_batches = compute_sample_batches( + election, round.round_num, contest_sample_sizes + ) + for batch_draw in rla_sample_batches: sampled_batch_draw = SampledBatchDraw( batch_id=batch_draw["batch_id"], round_id=round.id, @@ -366,6 +366,13 @@ def draw_sample_batches( ) db_session.add(sampled_batch_draw) + for extra_batch in extra_batches: + round_extra_batch = ExtraBatchDraw( + round_id=round.id, + batch_id=extra_batch["batch_id"], + ) + db_session.add(round_extra_batch) + def draw_sample_ballots( election: Election, diff --git a/server/api/shared.py b/server/api/shared.py index 9b9dec62a..c63365933 100644 --- a/server/api/shared.py +++ b/server/api/shared.py @@ -1,7 +1,7 @@ from collections import defaultdict import random from typing import TypedDict -from sqlalchemy import and_, func, literal +from sqlalchemy import and_, func, literal, or_ from sqlalchemy.orm import joinedload, load_only @@ -103,17 +103,18 @@ class CombinedBatch(TypedDict): def combined_batch_representative(sub_batches: list[Batch]) -> Batch: assert len(sub_batches) > 0 - sampled_sub_batches = [sub_batch for sub_batch in sub_batches if sub_batch.draws] # Prioritize RLA sampled sub-batches (if there are any) over extra sampled # batches. That way, the results from this combined batch will be included # in places where we filter out extra sampled batches. - sampled_non_extra_sub_batches = [ - sub_batch - for sub_batch in sampled_sub_batches - if list(sub_batch.draws)[0].ticket_number != EXTRA_TICKET_NUMBER + rla_sampled_sub_batches = [ + sub_batch for sub_batch in sub_batches if sub_batch.draws + ] + extra_sub_batches = [ + sub_batch for sub_batch in sub_batches if sub_batch.extra_draws ] return sorted( - sampled_non_extra_sub_batches or sampled_sub_batches, key=lambda batch: batch.id + rla_sampled_sub_batches or extra_sub_batches, + key=lambda batch: batch.id, )[0] @@ -148,15 +149,30 @@ def combined_batch_keys(election_id: str) -> list[set[sampler.BatchKey]]: def sampled_batch_results( contest: Contest, include_non_rla_batches=False ) -> BatchTallies: - results_by_batch_and_choice = ( - Batch.query.filter( + sampled_batch_ids = Batch.id.in_( + Batch.query.join(Jurisdiction) + .filter(Jurisdiction.election_id == contest.election_id) + .join(SampledBatchDraw) + .values(Batch.id) + ) + # Don't include non-RLA batches (extra batches that don't count toward risk + # measurement) unless explicitly requested, e.g., for discrepancy and audit + # reports + if include_non_rla_batches: + batch_filter = or_( + sampled_batch_ids, Batch.id.in_( Batch.query.join(Jurisdiction) .filter(Jurisdiction.election_id == contest.election_id) - .join(SampledBatchDraw) + .join(ExtraBatchDraw) .values(Batch.id) - ) + ), ) + else: + batch_filter = sampled_batch_ids + + results_by_batch_and_choice = ( + Batch.query.filter(batch_filter) .join(Jurisdiction) .join(Jurisdiction.contests) .filter(Contest.id == contest.id) @@ -213,23 +229,6 @@ def sampled_batch_results( if sub_batch_key in results: results[sub_batch_key] = representative_results - # Don't include non-RLA batches unless explicitly requested, e.g., for discrepancy - # and audit reports - if not include_non_rla_batches: - extra_batch_keys = set( - SampledBatchDraw.query.filter_by( - contest_id=contest.id, ticket_number=EXTRA_TICKET_NUMBER - ) - .join(Batch) - .join(Jurisdiction) - .values(Jurisdiction.name, Batch.name) - ) - results = { - batch_key: result - for batch_key, result in results.items() - if batch_key not in extra_batch_keys - } - return results @@ -238,13 +237,7 @@ def sampled_batches_by_ticket_number(contest: Contest) -> dict[str, sampler.Batc SampledBatchDraw.query.join(Batch) .join(Jurisdiction) .filter(Jurisdiction.election_id == contest.election_id) - # Don't include non-RLA batches - .filter( - and_( - SampledBatchDraw.contest_id == contest.id, - SampledBatchDraw.ticket_number != EXTRA_TICKET_NUMBER, - ) - ) + .filter(SampledBatchDraw.contest_id == contest.id) .order_by(SampledBatchDraw.ticket_number) .values(SampledBatchDraw.ticket_number, Jurisdiction.name, Batch.name) ) @@ -633,9 +626,12 @@ class BatchDraw(TypedDict): ticket_number: str +class ExtraBatch(TypedDict): + batch_id: str + + def compute_sample_batches_for_contest( election: Election, - round_num: int, contest: Contest, contest_sample_size: SampleSize, ) -> list[BatchDraw]: @@ -654,12 +650,8 @@ def compute_sample_batches_for_contest( Batch.query.join(Jurisdiction) .filter(Jurisdiction.election_id == contest.election_id) .join(SampledBatchDraw) - # Don't include non-RLA batches - .filter( - and_( - SampledBatchDraw.contest_id == contest.id, - SampledBatchDraw.ticket_number != EXTRA_TICKET_NUMBER, - ) + .filter_by( + contest_id=contest.id, ) .with_entities(Jurisdiction.name, Batch.name) ) @@ -681,12 +673,35 @@ def compute_sample_batches_for_contest( for ticket_number, batch_key in sample ] - # Experimental feature - # Add extra batches on top of the original sample that will be audited, but - # not counted in the final risk measurement. + return sample_batches + + +# Add extra batches on top of the original sample that will be audited, to +# meet state requirements. These will not be counted in the final risk measurement. +def compute_extra_batches_for_round( + election: Election, + round_num: int, + sample_batches: list[BatchDraw], +) -> list[ExtraBatch]: + # Create a mapping from batch keys used in the sampling back to batch ids + batches = ( + Batch.query.join(Jurisdiction) + .filter(Jurisdiction.election_id == election.id) + .with_entities(Jurisdiction.name, Batch.name, Batch.id) + ) + batch_key_to_id = { + (jurisdiction_name, batch_name): batch_id + for jurisdiction_name, batch_name, batch_id in batches + } + batch_id_to_key = { + batch_id: (jurisdiction_name, batch_name) + for jurisdiction_name, batch_name, batch_id in batches + } + + extra_batches: list[ExtraBatch] = [] if is_enabled_sample_extra_batches_by_counting_group(election) and round_num == 1: rand = random.Random(str(election.random_seed)) - for jurisdiction in contest.jurisdictions: + for jurisdiction in election.jurisdictions: batch_key_to_num_ballots = { (jurisdiction.name, batch.name): batch.num_ballots for batch in jurisdiction.batches @@ -711,9 +726,9 @@ def compute_sample_batches_for_contest( in [CountingGroup.ABSENTEE_BY_MAIL, CountingGroup.PROVISIONAL] } sampled_batch_keys = { - batch_key - for _, batch_key in sample - if batch_key[0] == jurisdiction.name + batch_id_to_key[batch["batch_id"]] + for batch in sample_batches + if batch_id_to_key[batch["batch_id"]][0] == jurisdiction.name } extra_batch_keys = set() @@ -724,11 +739,9 @@ def compute_sample_batches_for_contest( ): extra_bmd_batch_key = rand.choice(sorted(bmd_batch_keys)) extra_batch_keys.add(extra_bmd_batch_key) - sample_batches.append( - BatchDraw( + extra_batches.append( + ExtraBatch( batch_id=batch_key_to_id[extra_bmd_batch_key], - contest_id=contest.id, - ticket_number=EXTRA_TICKET_NUMBER, ) ) # If we didn't sample any HMPB batches, add one to the sample @@ -738,11 +751,9 @@ def compute_sample_batches_for_contest( ): extra_hmpb_batch_key = rand.choice(sorted(hmpb_batch_keys)) extra_batch_keys.add(extra_hmpb_batch_key) - sample_batches.append( - BatchDraw( + extra_batches.append( + ExtraBatch( batch_id=batch_key_to_id[extra_hmpb_batch_key], - contest_id=contest.id, - ticket_number=EXTRA_TICKET_NUMBER, ) ) @@ -773,21 +784,19 @@ def compute_percentage_of_jurisdiction_ballots_selected( ) extra_batch_key = rand.choice(sorted(remaining_batch_keys)) extra_batch_keys.add(extra_batch_key) - sample_batches.append( - BatchDraw( + extra_batches.append( + ExtraBatch( batch_id=batch_key_to_id[extra_batch_key], - contest_id=contest.id, - ticket_number=EXTRA_TICKET_NUMBER, ) ) if is_enabled_sample_extra_batches_to_ensure_one_per_jurisdiction(election): rand = random.Random(str(election.random_seed)) - for jurisdiction in contest.jurisdictions: + for jurisdiction in election.jurisdictions: sampled_batch_keys_from_jurisdiction = { - batch_key - for _, batch_key in sample - if batch_key[0] == jurisdiction.name + batch_id_to_key[batch["batch_id"]] + for batch in sample_batches + if batch_id_to_key[batch["batch_id"]][0] == jurisdiction.name } # If we didn't sample any batches from this jurisdiction, add one if len(sampled_batch_keys_from_jurisdiction) == 0: @@ -796,30 +805,27 @@ def compute_percentage_of_jurisdiction_ballots_selected( } if len(jurisdiction_batch_keys) > 0: extra_batch_key = rand.choice(sorted(jurisdiction_batch_keys)) - sample_batches.append( - BatchDraw( + extra_batches.append( + ExtraBatch( batch_id=batch_key_to_id[extra_batch_key], - contest_id=contest.id, - ticket_number=EXTRA_TICKET_NUMBER, ) ) - return sample_batches + return extra_batches def compute_sample_batches( election: Election, round_num: int, contest_sample_sizes: list[tuple[Contest, SampleSize]], -) -> list[BatchDraw]: +) -> tuple[list[BatchDraw], list[ExtraBatch]]: sample_batches = [ batch for contest, sample_size in contest_sample_sizes - for batch in compute_sample_batches_for_contest( - election, round_num, contest, sample_size - ) + for batch in compute_sample_batches_for_contest(election, contest, sample_size) ] - return sample_batches + extra_batches = compute_extra_batches_for_round(election, round_num, sample_batches) + return sample_batches, extra_batches def compute_sample_ballots( diff --git a/server/models.py b/server/models.py index 4b1008e66..1c95ddf87 100644 --- a/server/models.py +++ b/server/models.py @@ -436,6 +436,12 @@ class Batch(BaseModel): cascade="all, delete-orphan", passive_deletes=True, ) + extra_draws = relationship( + "ExtraBatchDraw", + uselist=True, + cascade="all, delete-orphan", + passive_deletes=True, + ) result_tally_sheets = relationship( "BatchResultTallySheet", uselist=True, @@ -942,9 +948,19 @@ class SampledBatchDraw(BaseModel): ) -# (Experimental) To we add extra batches on top of the sample, give them a -# special ticket number to flag them. -EXTRA_TICKET_NUMBER = "EXTRA" +class ExtraBatchDraw(BaseModel): + batch_id = Column( + String(200), + ForeignKey("batch.id", ondelete="cascade"), + nullable=False, + ) + batch = relationship("Batch") + + round_id = Column( + String(200), ForeignKey("round.id", ondelete="cascade"), nullable=False + ) + + __table_args__ = (PrimaryKeyConstraint("batch_id", "round_id"),) # In a batch comparison audit, audit boards will record votes on tally sheets.