Skip to content

Commit

Permalink
feat: add python 3.12 support
Browse files Browse the repository at this point in the history
feat: add python 3.12 support
  • Loading branch information
edx-requirements-bot authored and UsamaSadiq committed Mar 20, 2024
1 parent 7a7e8d0 commit b427c6d
Show file tree
Hide file tree
Showing 17 changed files with 222 additions and 157 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ name: Python CI

on:
push:
branches: [ master ]
branches: [master]
pull_request:
branches:
- '**'
- '**'
workflow_dispatch:

concurrency:
Expand All @@ -19,8 +19,8 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-20.04]
python-version: [3.8]
toxenv: [py38-django32, py38-django42, quality, translations-django32, translations-django42]
python-version: ['3.8', '3.12']
toxenv: [py38-django42, quality, translations-django42, django42]

steps:
- name: checkout repo
Expand Down
1 change: 1 addition & 0 deletions drag_and_drop_v2/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ def get_grading_ignore_decoys_waffle_flag():
# Ref: https://github.com/openedx/public-engineering/issues/28
return CourseWaffleFlag(WAFFLE_NAMESPACE, GRADING_IGNORE_DECOYS, __name__)
except ValueError:
# pylint: disable=toggle-missing-annotation
return CourseWaffleFlag(f'{WAFFLE_NAMESPACE}.{GRADING_IGNORE_DECOYS}', __name__)
57 changes: 30 additions & 27 deletions drag_and_drop_v2/drag_and_drop_v2.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*- # pylint: disable=too-many-lines
# -*- coding: utf-8 -*- # pylint: disable=too-many-lines
#
""" Drag and Drop v2 XBlock """

Expand All @@ -11,9 +11,9 @@
import json
import logging

import six.moves.urllib.error # pylint: disable=import-error
import six.moves.urllib.parse # pylint: disable=import-error
import six.moves.urllib.request # pylint: disable=import-error
import six.moves.urllib.error
import six.moves.urllib.parse
import six.moves.urllib.request
import six
import webob

Expand Down Expand Up @@ -45,12 +45,11 @@
# Classes ###########################################################


# pylint: disable=bad-continuation
@XBlock.wants('settings')
@XBlock.wants('replace_urls')
@XBlock.wants('user') # Using `needs` breaks the Course Outline page in Maple.
@XBlock.needs('i18n')
class DragAndDropBlock(
class DragAndDropBlock( # pylint: disable=too-many-instance-attributes
ScorableXBlockMixin,
XBlock,
XBlockWithSettingsMixin,
Expand Down Expand Up @@ -257,7 +256,8 @@ def score(self):
"""
return Score(self.raw_earned, self.raw_possible)

def max_score(self): # pylint: disable=no-self-use
def max_score(self):

"""
Return the problem's max score, which for DnDv2 always equals 1.
Required by the grading system in the LMS.
Expand Down Expand Up @@ -293,6 +293,7 @@ def has_submitted_answer(self):
"""
Returns True if the user has made a submission.
"""
# pylint: disable=unsubscriptable-object
return self.fields['raw_earned'].is_set_on(self) or self.fields['grade'].is_set_on(self)

def weighted_grade(self):
Expand Down Expand Up @@ -330,7 +331,7 @@ def _get_statici18n_js_url(self):
return None

@XBlock.supports("multi_device") # Enable this block for use in the mobile app via webview
def student_view(self, context):
def student_view(self, context): # pylint: disable=unused-argument
"""
Player view, displayed to the student
"""
Expand Down Expand Up @@ -361,7 +362,7 @@ def student_view(self, context):

return fragment

def student_view_data(self, context=None):
def student_view_data(self, context=None): # pylint: disable=unused-argument
"""
Get the configuration data for the student_view.
The configuration is all the settings defined by the author, except for correct answers
Expand Down Expand Up @@ -419,7 +420,7 @@ def items_without_answers():
# final feedback (data.feedback.finish) is not included - it may give away answers.
}

def studio_view(self, context):
def studio_view(self, context): # pylint: disable=unused-argument,useless-suppression
"""
Editing view in Studio
"""
Expand Down Expand Up @@ -483,7 +484,7 @@ def studio_view(self, context):
return fragment

@XBlock.json_handler
def studio_submit(self, submissions, suffix=''):
def studio_submit(self, submissions, suffix=''): # pylint: disable=unused-argument
"""
Handles studio save.
"""
Expand Down Expand Up @@ -515,7 +516,7 @@ def _get_block_id(self):
- In the workbench, use the usage_id.
"""
if hasattr(self, 'location'):
return self.location.html_id() # pylint: disable=no-member
return self.location.html_id() # pylint: disable=no-member,useless-suppression
else:
return six.text_type(self.scope_ids.usage_id)

Expand Down Expand Up @@ -553,7 +554,7 @@ def _get_max_items_per_zone(submissions):
return None

@XBlock.json_handler
def drop_item(self, item_attempt, suffix=''):
def drop_item(self, item_attempt, suffix=''): # pylint: disable=unused-argument
"""
Handles dropping item into a zone.
"""
Expand All @@ -570,7 +571,7 @@ def drop_item(self, item_attempt, suffix=''):
)

@XBlock.json_handler
def do_attempt(self, data, suffix=''):
def do_attempt(self, data, suffix=''): # pylint: disable=unused-argument
"""
Checks submitted solution and returns feedback.
Expand All @@ -581,7 +582,7 @@ def do_attempt(self, data, suffix=''):
self._validate_do_attempt()

self.attempts += 1
# pylint: disable=fixme
# pylint: disable=fixme,useless-suppression
# TODO: Refactor this method to "freeze" item_state and pass it to methods that need access to it.
# These implicit dependencies between methods exist because most of them use `item_state` or other
# fields, either as an "input" (i.e. read value) or as output (i.e. set value) or both. As a result,
Expand Down Expand Up @@ -610,7 +611,7 @@ def do_attempt(self, data, suffix=''):
}

@XBlock.json_handler
def publish_event(self, data, suffix=''):
def publish_event(self, data, suffix=''): # pylint: disable=unused-argument
"""
Handler to publish XBlock event from frontend
"""
Expand All @@ -623,15 +624,15 @@ def publish_event(self, data, suffix=''):
return {'result': 'success'}

@XBlock.json_handler
def reset(self, data, suffix=''):
def reset(self, data, suffix=''): # pylint: disable=unused-argument
"""
Resets problem to initial state
"""
self.item_state = {}
return self._get_user_state()

@XBlock.json_handler
def show_answer(self, data, suffix=''):
def show_answer(self, data, suffix=''): # pylint: disable=unused-argument
"""
Returns correct answer in assessment mode.
Expand Down Expand Up @@ -662,7 +663,7 @@ def show_answer(self, data, suffix=''):
return answer

@XBlock.json_handler
def expand_static_url(self, url, suffix=''):
def expand_static_url(self, url, suffix=''): # pylint: disable=unused-argument
""" AJAX-accessible handler for expanding URLs to static [image] files """
return {'url': self._expand_static_url(url)}

Expand Down Expand Up @@ -712,7 +713,7 @@ def has_submission_deadline_passed(self):
functionality.
"""
if hasattr(self, "has_deadline_passed"):
return self.has_deadline_passed() # pylint: disable=no-member
return self.has_deadline_passed() # pylint: disable=no-member,useless-suppression
else:
return False

Expand Down Expand Up @@ -776,7 +777,7 @@ def is_answer_available(self):
return check_permissions_function()

@XBlock.handler
def student_view_user_state(self, request, suffix=''):
def student_view_user_state(self, request, suffix=''): # pylint: disable=unused-argument
""" GET all user-specific data, and any applicable feedback """
data = self._get_user_state()
return webob.Response(body=json.dumps(data).encode('utf-8'), content_type='application/json')
Expand Down Expand Up @@ -949,7 +950,7 @@ def _mark_complete_and_publish_grade(self):
"""
Helper method to update `self.completed` and submit grade event if appropriate conditions met.
"""
# pylint: disable=fixme
# pylint: disable=fixme,useless-suppression
# TODO: (arguable) split this method into "clean" functions (with no side effects and implicit state)
# This method implicitly depends on self.item_state (via is_correct and _learner_raw_score)
# and also updates self.raw_earned if some conditions are met. As a result this method implies some order of
Expand Down Expand Up @@ -1052,7 +1053,9 @@ def _expand_static_url(self, url):
# edX Studio uses a different runtime for 'studio_view' than 'student_view',
# and the 'studio_view' runtime doesn't provide the replace_urls API.
try:
from common.djangoapps.static_replace import replace_static_urls # pylint: disable=import-error
# pylint: disable=import-outside-toplevel
from common.djangoapps.static_replace import replace_static_urls
# pylint: disable=redundant-u-string-prefix
url = replace_static_urls(u'"{}"'.format(url), None, course_id=self.runtime.course_id)[1:-1]
except ImportError:
pass
Expand Down Expand Up @@ -1108,7 +1111,7 @@ def _get_preferred_zone(zone_count, zones):
return preferred_zone

# Set states of all items dropped in correct zones
for item_id in self.item_state:
for item_id in self.item_state: # pylint: disable=consider-using-dict-items
if self.item_state[item_id]['correct']:
state[item_id] = self.item_state[item_id]
correct_items.add(item_id)
Expand Down Expand Up @@ -1252,7 +1255,7 @@ def _get_raw_earned_if_set(self):
Returns student's grade if already explicitly set, otherwise returns None.
This is different from self.raw_earned which returns 0 by default.
"""
if self.fields['raw_earned'].is_set_on(self):
if self.fields['raw_earned'].is_set_on(self): # pylint: disable=unsubscriptable-object
return self.raw_earned
else:
return None
Expand All @@ -1262,7 +1265,7 @@ def _get_weighted_earned_if_set(self):
Returns student's grade with the problem weight applied if set, otherwise
None.
"""
if self.fields['raw_earned'].is_set_on(self):
if self.fields['raw_earned'].is_set_on(self): # pylint: disable=unsubscriptable-object
return self.weighted_grade()
else:
return None
Expand Down Expand Up @@ -1319,7 +1322,7 @@ def index_dictionary(self):
# values may be numeric / string or dict
# default implementation is an empty dict

xblock_body = super(DragAndDropBlock, self).index_dictionary()
xblock_body = super(DragAndDropBlock, self).index_dictionary() # pylint: disable=super-with-arguments

zones_display_names = {
"zone_{}_display_name".format(zone_i):
Expand Down
14 changes: 7 additions & 7 deletions drag_and_drop_v2/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def sanitize_html(raw_body: str) -> str:
"""
Remove not allowed HTML tags to mitigate XSS vulnerabilities.
"""
bleach_options = dict(
bleach_options = dict( # pylint: disable=use-dict-literal
tags=ALLOWED_TAGS,
protocols=bleach.ALLOWED_PROTOCOLS,
strip=True,
Expand Down Expand Up @@ -165,8 +165,8 @@ def not_placed(number, ngettext=ngettext_fallback):
).format(missing_count=number)


FeedbackMessage = namedtuple("FeedbackMessage", ["message", "message_class"]) # pylint: disable=invalid-name
ItemStats = namedtuple( # pylint: disable=invalid-name
FeedbackMessage = namedtuple("FeedbackMessage", ["message", "message_class"])
ItemStats = namedtuple(
'ItemStats',
["required", "placed", "correctly_placed", "decoy", "decoy_in_bank"]
)
Expand Down Expand Up @@ -238,7 +238,7 @@ def apply_item_state_migrations(self, item_id, item_state):
return self._apply_migration(item_id, item_state, migrations)

@classmethod
def _zone_v1_to_v2(cls, unused_zone_id, zone):
def _zone_v1_to_v2(cls, unused_zone_id, zone): # pylint: disable=unused-argument
"""
Migrates zone data from v1.0 format to v2.0 format.
Expand All @@ -257,7 +257,7 @@ def _zone_v1_to_v2(cls, unused_zone_id, zone):
return zone

@classmethod
def _zone_v2_to_v2p1(cls, unused_zone_id, zone):
def _zone_v2_to_v2p1(cls, unused_zone_id, zone): # pylint: disable=unused-argument
"""
Migrates zone data from v2.0 to v2.1
Expand All @@ -279,7 +279,7 @@ def _zone_v2_to_v2p1(cls, unused_zone_id, zone):
return zone

@classmethod
def _item_state_v1_to_v1p5(cls, unused_item_id, item):
def _item_state_v1_to_v1p5(cls, unused_item_id, item): # pylint: disable=unused-argument
"""
Migrates item_state from v1.0 to v1.5
Expand All @@ -295,7 +295,7 @@ def _item_state_v1_to_v1p5(cls, unused_item_id, item):
return {'top': item[0], 'left': item[1]}

@classmethod
def _item_state_v1p5_to_v2(cls, unused_item_id, item):
def _item_state_v1p5_to_v2(cls, unused_item_id, item): # pylint: disable=unused-argument
"""
Migrates item_state from v1.5 to v2.0
Expand Down
29 changes: 19 additions & 10 deletions pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,34 @@ reports=no

[FORMAT]
max-line-length=120
max-module-lines=1500

[MESSAGES CONTROL]
disable=
attribute-defined-outside-init,
locally-disabled,
missing-docstring,
abstract-class-little-used,
too-many-ancestors,
too-many-instance-attributes,
too-few-public-methods,
too-many-public-methods,
unused-argument,
invalid-name,
no-member,
star-args,
no-else-return,
useless-object-inheritance,
unsubscriptable-object,
no-else-return
bad-option-value,
len-as-condition,
useless-super-delegation,
bad-option-value,
missing-docstring,
no-member,
wrong-import-order,
line-too-long,
consider-using-f-string

[SIMILARITIES]
min-similarity-lines=4
min-similarity-lines=6

[OPTIONS]
good-names=_,__,logger,loader
method-rgx=_?[a-z_][a-z0-9_]{2,40}$
function-rgx=_?[a-z_][a-z0-9_]{2,40}$
method-name-hint=_?[a-z_][a-z0-9_]{2,40}$
function-name-hint=_?[a-z_][a-z0-9_]{2,40}$
max-args=6
19 changes: 19 additions & 0 deletions pylintrc_tweaks
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[MASTER]
load-plugins = edx_lint.pylint

[FORMAT]
max-line-length=120
max-module-lines=1500

[MESSAGES CONTROL]
disable =
locally-disabled,
too-many-ancestors,
too-many-instance-attributes,
too-few-public-methods,
too-many-public-methods,
unused-argument,
unsubscriptable-object,
no-else-return,
consider-using-f-string,
feature-toggle-needs-doc
Loading

0 comments on commit b427c6d

Please sign in to comment.