From 437eccc7fd44cdcbca4a91e653761e8d5f4f4e19 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Thu, 7 Sep 2017 22:42:17 -0500 Subject: [PATCH 01/11] Stop using mypy option --fast-parser --- run-mypy.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/run-mypy.sh b/run-mypy.sh index 6896ff9a..e867afda 100755 --- a/run-mypy.sh +++ b/run-mypy.sh @@ -1,7 +1,6 @@ #! /bin/bash mypy \ - --fast-parser \ --strict-optional \ --ignore-missing-imports \ --follow-imports=skip \ -- GitLab From 6c58c6b05188fa821f9666b2394d0f8f177f5fa6 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Thu, 7 Sep 2017 22:42:47 -0500 Subject: [PATCH 02/11] Fix type annotations: frozenset[type] -> FrozenSet[type] --- course/constants.py | 4 +++- course/content.py | 6 +++--- course/enrollment.py | 4 ++-- course/flow.py | 14 +++++++------- course/page/base.py | 4 ++-- course/utils.py | 12 ++++++------ 6 files changed, 23 insertions(+), 21 deletions(-) diff --git a/course/constants.py b/course/constants.py index 7c50b9f1..f418746b 100644 --- a/course/constants.py +++ b/course/constants.py @@ -24,6 +24,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ +if False: + import typing # noqa from django.utils.translation import pgettext_lazy, ugettext # Allow 10x extra credit at the very most. @@ -286,7 +288,7 @@ FLOW_SESSION_EXPIRATION_MODE_CHOICES = ( def is_expiration_mode_allowed(expmode, permissions): - # type: (str, frozenset[str]) -> bool + # type: (str, typing.FrozenSet[str]) -> bool if expmode == flow_session_expiration_mode.roll_over: if (flow_permission.set_roll_over_expiration_mode in permissions): diff --git a/course/content.py b/course/content.py index 407d1ada..9d320f6c 100644 --- a/course/content.py +++ b/course/content.py @@ -24,7 +24,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -from typing import cast, Union +from typing import cast, Union, FrozenSet from django.conf import settings from django.utils.translation import ugettext as _ @@ -1215,7 +1215,7 @@ def compute_chunk_weight_and_shown( chunk, # type: ChunkDesc roles, # type: List[Text] now_datetime, # type: datetime.datetime - facilities, # type: frozenset[Text] + facilities, # type: FrozenSet[Text] ): # type: (...) -> Tuple[float, bool] if not hasattr(chunk, "rules"): @@ -1274,7 +1274,7 @@ def get_processed_page_chunks( page_desc, # type: StaticPageDesc roles, # type: List[Text] now_datetime, # type: datetime.datetime - facilities, # type: frozenset[Text] + facilities, # type: FrozenSet[Text] ): # type: (...) -> List[ChunkDesc] for chunk in page_desc.chunks: diff --git a/course/enrollment.py b/course/enrollment.py index abad3046..cd8ee4d3 100644 --- a/course/enrollment.py +++ b/course/enrollment.py @@ -71,7 +71,7 @@ from pytools.lex import RE as REBase # noqa # {{{ for mypy if False: - from typing import Any, Tuple, Text, Optional, List # noqa + from typing import Any, Tuple, Text, Optional, List, FrozenSet # noqa from course.utils import CoursePageContext # noqa # }}} @@ -137,7 +137,7 @@ def get_participation_permissions( course, # type: Course participation, # type: Optional[Participation] ): - # type: (...) -> frozenset[Tuple[Text, Optional[Text]]] + # type: (...) -> FrozenSet[Tuple[Text, Optional[Text]]] if participation is not None: return participation.permissions() diff --git a/course/flow.py b/course/flow.py index 9122f446..bdac6e17 100644 --- a/course/flow.py +++ b/course/flow.py @@ -88,7 +88,7 @@ from relate.utils import retry_transaction_decorator # {{{ mypy if False: - from typing import Any, Optional, Iterable, Tuple, Text, List # noqa + from typing import Any, Optional, Iterable, Tuple, Text, List, FrozenSet # noqa import datetime # noqa from course.models import Course # noqa from course.utils import ( # noqa @@ -1347,7 +1347,7 @@ def recalculate_session_grade(repo, course, session): def lock_down_if_needed( request, # type: http.HttpRequest - permissions, # type: frozenset[Text] + permissions, # type: FrozenSet[Text] flow_session, # type: FlowSession ): # type: (...) -> None @@ -1607,7 +1607,7 @@ def get_and_check_flow_session(pctx, flow_session_id): def will_receive_feedback(permissions): - # type: (frozenset[Text]) -> bool + # type: (FrozenSet[Text]) -> bool return ( flow_permission.see_correctness in permissions @@ -1615,14 +1615,14 @@ def will_receive_feedback(permissions): def may_send_email_about_flow_page(permissions): - # type: (frozenset[Text]) -> bool + # type: (FrozenSet[Text]) -> bool return flow_permission.send_email_about_flow_page in permissions def get_page_behavior( page, # type: PageBase - permissions, # type: frozenset[Text] + permissions, # type: FrozenSet[Text] session_in_progress, # type: bool answer_was_graded, # type: bool generates_grade, # type: bool @@ -1679,7 +1679,7 @@ def get_page_behavior( def add_buttons_to_form(form, fpctx, flow_session, permissions): - # type: (StyledForm, FlowPageContext, FlowSession, frozenset[Text]) -> StyledForm + # type: (StyledForm, FlowPageContext, FlowSession, FrozenSet[Text]) -> StyledForm from crispy_forms.layout import Submit show_save_button = getattr(form, "show_save_button", True) @@ -2137,7 +2137,7 @@ def post_flow_page( flow_session, # type: FlowSession fpctx, # type: FlowPageContext request, # type: http.HttpRequest - permissions, # type: frozenset[Text] + permissions, # type: FrozenSet[Text] generates_grade, # type: bool ): # type: (...) -> Tuple[PageBehavior, List[FlowPageVisit], forms.Form, Optional[AnswerFeedback], Any, bool] # noqa diff --git a/course/page/base.py b/course/page/base.py index 4bc5c7eb..2a5c3b6e 100644 --- a/course/page/base.py +++ b/course/page/base.py @@ -44,7 +44,7 @@ from django.conf import settings # {{{ mypy if False: - from typing import Text, Optional, Any, Tuple, Dict, Callable # noqa + from typing import Text, Optional, Any, Tuple, Dict, Callable, FrozenSet # noqa from django import http # noqa from course.models import ( # noqa Course, @@ -371,7 +371,7 @@ class PageBase(object): ) def get_modified_permissions_for_page(self, permissions): - # type: (frozenset[Text]) -> frozenset[Text] + # type: (FrozenSet[Text]) -> FrozenSet[Text] rw_permissions = set(permissions) if hasattr(self.page_desc, "access_rules"): diff --git a/course/utils.py b/course/utils.py index 2ff1f3f5..2be2311b 100644 --- a/course/utils.py +++ b/course/utils.py @@ -58,7 +58,7 @@ from course.page.base import ( # noqa # {{{ mypy if False: - from typing import Tuple, List, Text, Iterable, Any, Optional, Union, Dict # noqa + from typing import Tuple, List, Text, Iterable, Any, Optional, Union, Dict, FrozenSet # noqa from relate.utils import Repo_ish # noqa from course.models import ( # noqa Course, @@ -105,7 +105,7 @@ class FlowSessionStartRule(FlowSessionRuleBase): class FlowSessionAccessRule(FlowSessionRuleBase): def __init__( self, - permissions, # type: frozenset[Text] + permissions, # type: FrozenSet[Text] message=None, # type: Optional[Text] ): # type: (...) -> None @@ -280,7 +280,7 @@ def get_session_start_rule( flow_id, # type: Text flow_desc, # type: FlowDesc now_datetime, # type: datetime.datetime - facilities=None, # type: Optional[frozenset[Text]] + facilities=None, # type: Optional[FrozenSet[Text]] for_rollover=False, # type: bool login_exam_ticket=None, # type: Optional[ExamTicket] ): @@ -373,7 +373,7 @@ def get_session_access_rule( session, # type: FlowSession flow_desc, # type: FlowDesc now_datetime, # type: datetime.datetime - facilities=None, # type: Optional[frozenset[Text]] + facilities=None, # type: Optional[FrozenSet[Text]] login_exam_ticket=None, # type: Optional[ExamTicket] ): # type: (...) -> FlowSessionAccessRule @@ -552,7 +552,7 @@ class CoursePageContext(object): self.request = request self.course_identifier = course_identifier - self._permissions_cache = None # type: Optional[frozenset[Tuple[Text, Optional[Text]]]] # noqa + self._permissions_cache = None # type: Optional[FrozenSet[Tuple[Text, Optional[Text]]]] # noqa self._role_identifiers_cache = None # type: Optional[List[Text]] from course.models import Course # noqa @@ -612,7 +612,7 @@ class CoursePageContext(object): return self._role_identifiers_cache def permissions(self): - # type: () -> frozenset[Tuple[Text, Optional[Text]]] + # type: () -> FrozenSet[Tuple[Text, Optional[Text]]] if self.participation is None: if self._permissions_cache is not None: return self._permissions_cache -- GitLab From 4b4103130db8fc121e6fa421364785fc2cfd67e9 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Thu, 7 Sep 2017 22:45:13 -0500 Subject: [PATCH 03/11] Add missing typing.List import --- course/grading.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/course/grading.py b/course/grading.py index 910edc9a..b20b0154 100644 --- a/course/grading.py +++ b/course/grading.py @@ -58,7 +58,7 @@ from course.constants import ( # {{{ for mypy if False: - from typing import Text, Any, Optional, Dict # noqa + from typing import Text, Any, Optional, Dict, List # noqa from course.models import ( # noqa GradingOpportunity) from course.utils import ( # noqa -- GitLab From 10125d0d131afc23dba89cd345ecf59d02d391eb Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Thu, 7 Sep 2017 22:59:01 -0500 Subject: [PATCH 04/11] Fix Flake8 complaint about type import --- course/content.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/course/content.py b/course/content.py index 9d320f6c..fc276860 100644 --- a/course/content.py +++ b/course/content.py @@ -24,7 +24,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ -from typing import cast, Union, FrozenSet +from typing import cast, Union from django.conf import settings from django.utils.translation import ugettext as _ @@ -62,7 +62,7 @@ else: if False: # for mypy from typing import ( # noqa - Any, List, Tuple, Optional, Callable, Text, Dict) + Any, List, Tuple, Optional, Callable, Text, Dict, FrozenSet) from course.models import Course, Participation # noqa import dulwich # noqa from course.validation import ValidationContext # noqa -- GitLab From 43174f39956bb186f2e9f4910c3c797061eef69d Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Thu, 7 Sep 2017 22:59:22 -0500 Subject: [PATCH 05/11] Update call to prepare-and-run-mypy.sh to include desired mypy version --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fb58f198..22d961db 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -30,9 +30,9 @@ Mypy: script: - curl -L -O -k https://gitlab.tiker.net/inducer/ci-support/raw/master/prepare-and-run-mypy.sh - "cp local_settings.example.py local_settings.py" - - ". ./prepare-and-run-mypy.sh" + - ". ./prepare-and-run-mypy.sh python3.6 mypy==0.521 typed-ast==1.0.4" tags: - - python3.5 + - python3.6 except: - tags -- GitLab From 1bb0cae4c6b74630d7b6b4bc18a694b48d6969f8 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Thu, 7 Sep 2017 22:59:29 -0500 Subject: [PATCH 06/11] Add type annotation for permissions functions --- course/models.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/course/models.py b/course/models.py index 6a0f84c3..45fa1d67 100644 --- a/course/models.py +++ b/course/models.py @@ -61,7 +61,7 @@ from course.page.base import AnswerFeedback # {{{ mypy if False: - from typing import List, Dict, Any, Optional, Text, Iterable # noqa # noqa + from typing import List, Dict, Any, Optional, Text, Iterable, Tuple, FrozenSet # noqa from course.content import FlowDesc # noqa # }}} @@ -468,7 +468,10 @@ class Participation(models.Model): # {{{ permissions handling + _permissions_cache = None # type: FrozenSet[Tuple[Text, Optional[Text]]] + def permissions(self): + # type: () -> FrozenSet[Tuple[Text, Optional[Text]]] try: return self._permissions_cache except AttributeError: @@ -486,14 +489,15 @@ class Participation(models.Model): participation=self) .values_list("permission", "argument"))) - perm = frozenset( + fset_perm = frozenset( (permission, argument) if argument else (permission, None) for permission, argument in perm) - self._permissions_cache = perm - return perm + self._permissions_cache = fset_perm + return fset_perm def has_permission(self, perm, argument=None): + # type: (Text, Optional[Text]) -> bool return (perm, argument) in self.permissions() # }}} -- GitLab From 236f20b5eaff1f4e47eb61e7ac4d20443e74183c Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Thu, 7 Sep 2017 23:04:42 -0500 Subject: [PATCH 07/11] Fix typing of get_repo_blob_data_cached --- course/content.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/course/content.py b/course/content.py index fc276860..6e798c38 100644 --- a/course/content.py +++ b/course/content.py @@ -312,7 +312,7 @@ def get_repo_blob_data_cached(repo, full_name, commit_sha): def_cache = cache.caches["default"] - result = None + result = None # type: Optional[bytes] # Memcache is apparently limited to 250 characters. if len(cache_key) < 240: result = def_cache.get(cache_key) @@ -323,6 +323,7 @@ def get_repo_blob_data_cached(repo, full_name, commit_sha): result = get_repo_blob(repo, full_name, commit_sha, allow_tree=False).data + assert result is not None if len(result) <= getattr(settings, "RELATE_CACHE_MAX_BYTES", 0): def_cache.add(cache_key, (result,), None) -- GitLab From fad7c4f9095c81100fecdbdc418580e9ccd8485b Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Thu, 7 Sep 2017 23:06:29 -0500 Subject: [PATCH 08/11] Add type to UnsubmitFlowPageForm constructor --- course/flow.py | 1 + 1 file changed, 1 insertion(+) diff --git a/course/flow.py b/course/flow.py index bdac6e17..8c680a67 100644 --- a/course/flow.py +++ b/course/flow.py @@ -2832,6 +2832,7 @@ def regrade_flows_view(pctx): class UnsubmitFlowPageForm(forms.Form): def __init__(self, *args, **kwargs): + # type: (*Any, **Any) -> None self.helper = FormHelper() super(UnsubmitFlowPageForm, self).__init__(*args, **kwargs) -- GitLab From 6007347581c4b8d58ba1eb1ae086291e333afd25 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Thu, 7 Sep 2017 23:09:34 -0500 Subject: [PATCH 09/11] Re-Fix typing of get_repo_blob_data_cached --- course/content.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/course/content.py b/course/content.py index 6e798c38..a011cd5a 100644 --- a/course/content.py +++ b/course/content.py @@ -300,6 +300,7 @@ def get_repo_blob_data_cached(repo, full_name, commit_sha): except ImproperlyConfigured: cache_key = None + result = None # type: Optional[bytes] if cache_key is None: result = get_repo_blob(repo, full_name, commit_sha, allow_tree=False).data @@ -312,14 +313,14 @@ def get_repo_blob_data_cached(repo, full_name, commit_sha): def_cache = cache.caches["default"] - result = None # type: Optional[bytes] # Memcache is apparently limited to 250 characters. if len(cache_key) < 240: - result = def_cache.get(cache_key) - if result is not None: - (result,) = result - assert isinstance(result, six.binary_type), cache_key - return result + cached_result = def_cache.get(cache_key) + + if cached_result is not None: + (result,) = cached_result + assert isinstance(result, six.binary_type), cache_key + return result result = get_repo_blob(repo, full_name, commit_sha, allow_tree=False).data -- GitLab From 18cd7a4d19154fb374af5ea1271df892ce03f1b8 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Thu, 7 Sep 2017 23:39:24 -0500 Subject: [PATCH 10/11] Get mypy-clean on mypy 0.521 --- course/content.py | 13 ++++++++----- course/enrollment.py | 2 ++ course/exam.py | 2 +- course/flow.py | 3 ++- course/grading.py | 5 ++--- course/models.py | 2 +- course/page/base.py | 4 +++- course/sandbox.py | 9 +++++++-- course/utils.py | 10 +++++----- course/validation.py | 3 ++- course/views.py | 9 ++++++--- 11 files changed, 39 insertions(+), 23 deletions(-) diff --git a/course/content.py b/course/content.py index a011cd5a..294d871d 100644 --- a/course/content.py +++ b/course/content.py @@ -563,18 +563,20 @@ def get_raw_yaml_from_repo(repo, full_name, commit_sha): import django.core.cache as cache def_cache = cache.caches["default"] - result = None + + result = None # type: Optional[Any] # Memcache is apparently limited to 250 characters. if len(cache_key) < 240: result = def_cache.get(cache_key) if result is not None: return result - result = load_yaml( - expand_yaml_macros( + yaml_str = expand_yaml_macros( repo, commit_sha, get_repo_blob(repo, full_name, commit_sha, - allow_tree=False).data)) + allow_tree=False).data) + + result = load_yaml(yaml_str) # type: ignore def_cache.add(cache_key, result, None) @@ -621,7 +623,8 @@ def get_yaml_from_repo(repo, full_name, commit_sha, cached=True): expanded = expand_yaml_macros( repo, commit_sha, yaml_bytestream) - result = dict_to_struct(load_yaml(expanded)) + yaml_data = load_yaml(expanded) # type:ignore + result = dict_to_struct(yaml_data) if cached: def_cache.add(cache_key, result, None) diff --git a/course/enrollment.py b/course/enrollment.py index cd8ee4d3..cfbc7802 100644 --- a/course/enrollment.py +++ b/course/enrollment.py @@ -233,6 +233,8 @@ def enroll_view(request, course_identifier): course, user, participation_status.requested, roles, request) + assert participation is not None + with translation.override(settings.RELATE_ADMIN_EMAIL_LOCALE): from django.template.loader import render_to_string message = render_to_string("course/enrollment-request-email.txt", { diff --git a/course/exam.py b/course/exam.py index 6cd666c7..ee6d5391 100644 --- a/course/exam.py +++ b/course/exam.py @@ -615,7 +615,7 @@ def is_from_exams_only_facility(request): def get_login_exam_ticket(request): - # type: (http.HttpRequest) -> ExamTicket + # type: (http.HttpRequest) -> Optional[ExamTicket] exam_ticket_pk = request.session.get("relate_exam_ticket_pk_used_for_login") if exam_ticket_pk is None: diff --git a/course/flow.py b/course/flow.py index 8c680a67..23e178e6 100644 --- a/course/flow.py +++ b/course/flow.py @@ -88,7 +88,7 @@ from relate.utils import retry_transaction_decorator # {{{ mypy if False: - from typing import Any, Optional, Iterable, Tuple, Text, List, FrozenSet # noqa + from typing import Any, Optional, Iterable, Sequence, Tuple, Text, List, FrozenSet # noqa import datetime # noqa from course.models import Course # noqa from course.utils import ( # noqa @@ -494,6 +494,7 @@ def get_prev_answer_visits_qset(page_data): def get_first_from_qset(qset): + # type: (Sequence) -> Optional[Any] for item in qset[:1]: return item diff --git a/course/grading.py b/course/grading.py index b20b0154..5691309d 100644 --- a/course/grading.py +++ b/course/grading.py @@ -320,6 +320,8 @@ def grade_flow_page(pctx, flow_session_id, page_ordinal): else: grading_form = None + grading_form_html = None # type: Optional[Text] + if grading_form is not None: from crispy_forms.layout import Submit grading_form.helper.form_class += " relate-grading-form" @@ -332,9 +334,6 @@ def grade_flow_page(pctx, flow_session_id, page_ordinal): grading_form_html = fpctx.page.grading_form_to_html( pctx.request, fpctx.page_context, grading_form, grade_data) - else: - grading_form_html = None - # }}} # {{{ compute points_awarded diff --git a/course/models.py b/course/models.py index 45fa1d67..aa3f9306 100644 --- a/course/models.py +++ b/course/models.py @@ -797,7 +797,7 @@ class FlowSession(models.Model): __str__ = __unicode__ def append_comment(self, s): - # type: (Text) -> None + # type: (Optional[Text]) -> None if s is None: return diff --git a/course/page/base.py b/course/page/base.py index 2a5c3b6e..bfb3c81c 100644 --- a/course/page/base.py +++ b/course/page/base.py @@ -216,7 +216,7 @@ class AnswerFeedback(object): @staticmethod def from_json(json, bulk_json): - # type: (Any, Any) -> AnswerFeedback + # type: (Any, Any) -> Optional[AnswerFeedback] if json is None: return json @@ -387,9 +387,11 @@ class PageBase(object): return frozenset(rw_permissions) def make_page_data(self): + # type: () -> Dict return {} def initialize_page_data(self, page_context): + # type: (PageContext) -> Dict """Return (possibly randomly generated) data that is used to generate the content on this page. This is passed to methods below as the *page_data* argument. One possible use for this argument would be a random permutation diff --git a/course/sandbox.py b/course/sandbox.py index 3ffd16b6..23258395 100644 --- a/course/sandbox.py +++ b/course/sandbox.py @@ -240,7 +240,9 @@ def view_page_sandbox(pctx): from course.content import expand_yaml_macros new_page_source = expand_yaml_macros( pctx.repo, pctx.course_commit_sha, new_page_source) - page_desc = dict_to_struct(yaml.load(new_page_source)) + + yaml_data = yaml.load(new_page_source) # type: ignore + page_desc = dict_to_struct(yaml_data) if not isinstance(page_desc, Struct): raise ValidationError("Provided page source code is not " @@ -295,7 +297,8 @@ def view_page_sandbox(pctx): have_valid_page = page_source is not None if have_valid_page: - page_desc = cast(FlowPageDesc, dict_to_struct(yaml.load(page_source))) + yaml_data = yaml.load(page_source) # type: ignore + page_desc = cast(FlowPageDesc, dict_to_struct(yaml_data)) from course.content import instantiate_flow_page try: @@ -313,6 +316,8 @@ def view_page_sandbox(pctx): have_valid_page = False if have_valid_page: + page_desc = cast(FlowPageDesc, page_desc) + # Try to recover page_data, answer_data page_data = get_sandbox_data_for_page( pctx, page_desc, PAGE_DATA_SESSION_KEY) diff --git a/course/utils.py b/course/utils.py index 2be2311b..944fbcab 100644 --- a/course/utils.py +++ b/course/utils.py @@ -24,11 +24,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ +from typing import cast, Text + import six import datetime # noqa -from typing import cast - from django.shortcuts import ( # noqa render, get_object_or_404) from django import http @@ -58,7 +58,7 @@ from course.page.base import ( # noqa # {{{ mypy if False: - from typing import Tuple, List, Text, Iterable, Any, Optional, Union, Dict, FrozenSet # noqa + from typing import Tuple, List, Iterable, Any, Optional, Union, Dict, FrozenSet # noqa from relate.utils import Repo_ish # noqa from course.models import ( # noqa Course, @@ -518,7 +518,7 @@ def get_session_grading_rule( return FlowSessionGradingRule( grade_identifier=grade_identifier, - grade_aggregation_strategy=grade_aggregation_strategy, + grade_aggregation_strategy=cast(Text, grade_aggregation_strategy), due=due, generates_grade=generates_grade, description=getattr(rule, "description", None), @@ -966,7 +966,7 @@ def get_codemirror_widget( # {{{ facility processing def get_facilities_config(request=None): - # type: (Optional[http.HttpRequest]) -> Dict[Text, Dict[Text, Any]] + # type: (Optional[http.HttpRequest]) -> Optional[Dict[Text, Dict[Text, Any]]] from django.conf import settings # This is called during offline validation, where Django isn't really set up. diff --git a/course/validation.py b/course/validation.py index 27ed619c..76c1739a 100644 --- a/course/validation.py +++ b/course/validation.py @@ -1219,7 +1219,8 @@ def check_attributes_yml(vctx, repo, path, tree, access_kinds): from relate.utils import dict_to_struct from yaml import load as load_yaml - att_yml = dict_to_struct(load_yaml(true_repo[attr_blob_sha].data)) + yaml_data = load_yaml(true_repo[attr_blob_sha].data) # type: ignore + att_yml = dict_to_struct(yaml_data) if path: loc = path + "/" + ATTRIBUTES_FILENAME diff --git a/course/views.py b/course/views.py index 5128d3e2..40c5727e 100644 --- a/course/views.py +++ b/course/views.py @@ -24,6 +24,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ +from typing import cast, List, Text + import datetime from django.shortcuts import ( # noqa @@ -83,7 +85,7 @@ from course.utils import ( # noqa # {{{ for mypy if False: - from typing import Tuple, List, Text, Optional, Any, Iterable, Dict # noqa + from typing import Tuple, Any, Iterable, Dict, Optional # noqa from course.content import ( # noqa FlowDesc, @@ -1130,9 +1132,10 @@ def grant_exception_stage_3(pctx, participation_id, flow_id, session_id): flow_desc = get_flow_desc(pctx.repo, pctx.course, flow_id, pctx.course_commit_sha) - tags = None + + tags = [] # type: List[Text] if hasattr(flow_desc, "rules"): - tags = getattr(flow_desc.rules, "tags", None) + tags = cast(List[Text], getattr(flow_desc.rules, "tags", [])) # {{{ put together access rule -- GitLab From afd6b0628fda61e4f5ecb036203a5d583b6fbbd8 Mon Sep 17 00:00:00 2001 From: Andreas Kloeckner Date: Fri, 8 Sep 2017 00:01:23 -0500 Subject: [PATCH 11/11] Fix permission cache retrieval after type annotation --- course/models.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/course/models.py b/course/models.py index aa3f9306..f1f2fc87 100644 --- a/course/models.py +++ b/course/models.py @@ -472,10 +472,9 @@ class Participation(models.Model): def permissions(self): # type: () -> FrozenSet[Tuple[Text, Optional[Text]]] - try: + + if self._permissions_cache is not None: return self._permissions_cache - except AttributeError: - pass perm = ( list( -- GitLab