Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add python 3.11 and 3.12 support #79

Merged
merged 2 commits into from
Apr 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 21 additions & 21 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 @@ -18,27 +18,27 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ ubuntu-20.04 ]
python-version: [3.8]
toxenv: [django32, django42, quality, package]
os: [ubuntu-20.04]
python-version: ['3.8', '3.11', '3.12']
toxenv: [django42, quality, package]
steps:
- name: Install translations dependencies
run: sudo apt-get install -y gettext
- name: Install translations dependencies
run: sudo apt-get install -y gettext

- name: checkout repo
uses: actions/checkout@v3
with:
submodules: recursive
- name: checkout repo
uses: actions/checkout@v3
with:
submodules: recursive

- name: setup python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: setup python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Install Dependencies
run: pip install -r requirements/ci.txt
- name: Install Dependencies
run: pip install -r requirements/ci.txt

- name: Run Tests
env:
TOXENV: ${{ matrix.toxenv }}
run: tox
- name: Run Tests
env:
TOXENV: ${{ matrix.toxenv }}
run: tox
2 changes: 1 addition & 1 deletion google_drive/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
from .google_docs import GoogleDocumentBlock
from .google_calendar import GoogleCalendarBlock

__version__ = '0.6.1'
__version__ = '0.7.0'
4 changes: 2 additions & 2 deletions google_drive/google_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def studio_submit(self, submissions, suffix=''): # pylint: disable=unused-argum

# suffix argument is specified for xblocks, but we are not using herein
@XBlock.json_handler
def check_url(self, data, suffix=''): # pylint: disable=unused-argument,no-self-use
def check_url(self, data, suffix=''): # pylint: disable=unused-argument
"""
Checks that the given document url is accessible, and therefore assumed to be valid
"""
Expand All @@ -155,7 +155,7 @@ def check_url(self, data, suffix=''): # pylint: disable=unused-argument,no-self
}

try:
url_response = requests.head(test_url)
url_response = requests.head(test_url) # pylint: disable=missing-timeout
# Catch wide range of request exceptions
except requests.exceptions.RequestException as ex:
LOG.debug("Unable to connect to %s - %s", test_url, six.text_type(ex))
Expand Down
35 changes: 17 additions & 18 deletions google_drive/tests/unit/test_calendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from django.utils.html import escape
from django.utils.translation import override as override_language
from mock import Mock
from nose.tools import assert_equal, assert_in
from workbench.runtime import WorkbenchRuntime
from xblock.runtime import DictKeyValueStore, KvsFieldData

Expand Down Expand Up @@ -85,7 +84,7 @@ def make_calendar_block(cls):
ids = generate_scope_ids(runtime, 'google_calendar')
return GoogleCalendarBlock(runtime, db_model, scope_ids=ids)

def _render_calendar_block(self): # pylint: disable=no-self-use
def _render_calendar_block(self):
block = TestGoogleCalendarBlock.make_calendar_block()
block.usage_id = Mock()
student_fragment = block.render('student_view', Mock())
Expand All @@ -106,43 +105,43 @@ def test_calendar_template_content(self, override, activate_lang, expected_lang)
src_url = (f'https://www.google.com/calendar/embed?mode=Month&src'
f'={DEFAULT_CALENDAR_ID}&showCalendars=0&hl={expected_lang}')

assert_in('<div class="google-calendar-xblock-wrapper">', student_fragment.content)
assert_in(escape(src_url), student_fragment.content)
assert_in('Google Calendar', student_fragment.content)
assert '<div class="google-calendar-xblock-wrapper">' in student_fragment.content
assert escape(src_url) in student_fragment.content
assert 'Google Calendar' in student_fragment.content

assert_in(STUDIO_EDIT_WRAPPER, studio_fragment.content)
assert_in(VALIDATION_WRAPPER, studio_fragment.content)
assert_in(USER_INPUTS_WRAPPER, studio_fragment.content)
assert_in(BUTTONS_WRAPPER, studio_fragment.content)
assert STUDIO_EDIT_WRAPPER in studio_fragment.content
assert VALIDATION_WRAPPER in studio_fragment.content
assert USER_INPUTS_WRAPPER in studio_fragment.content
assert BUTTONS_WRAPPER in studio_fragment.content

def test_calendar_document_submit(self): # pylint: disable=no-self-use
def test_calendar_document_submit(self):
""" Test studio submission of GoogleCalendarBlock """
block = TestGoogleCalendarBlock.make_calendar_block()

body = json.dumps(TEST_SUBMIT_DATA)
res = block.handle('studio_submit', make_request(body))
# pylint: disable=no-value-for-parameter
assert_equal(json.loads(res.body.decode('utf8')), RESULT_SUCCESS)
assert json.loads(res.body.decode('utf8')) == RESULT_SUCCESS

assert_equal(block.display_name, TEST_SUBMIT_DATA['display_name'])
assert_equal(block.calendar_id, TEST_SUBMIT_DATA['calendar_id'])
assert_equal(block.default_view, TEST_SUBMIT_DATA['default_view'])
assert block.display_name == TEST_SUBMIT_DATA['display_name']
assert block.calendar_id == TEST_SUBMIT_DATA['calendar_id']
assert block.default_view == TEST_SUBMIT_DATA['default_view']

body = json.dumps('')
res = block.handle('studio_submit', make_request(body))
# pylint: disable=no-value-for-parameter
assert_equal(json.loads(res.body.decode('utf8')), RESULT_ERROR)
assert json.loads(res.body.decode('utf8')) == RESULT_ERROR

def test_calendar_publish_event(self): # pylint: disable=no-self-use
def test_calendar_publish_event(self):
""" Test event publishing in GoogleCalendarBlock"""
block = TestGoogleCalendarBlock.make_calendar_block()

body = json.dumps(TEST_COMPLETE_PUBLISH_DATA)
res = block.handle('publish_event', make_request(body))
# pylint: disable=no-value-for-parameter
assert_equal(json.loads(res.body.decode('utf8')), RESULT_SUCCESS)
assert json.loads(res.body.decode('utf8')) == RESULT_SUCCESS

body = json.dumps(TEST_INCOMPLETE_PUBLISH_DATA)
res = block.handle('publish_event', make_request(body))

assert_equal(json.loads(res.body.decode('utf8')), RESULT_MISSING_EVENT_TYPE)
assert json.loads(res.body.decode('utf8')) == RESULT_MISSING_EVENT_TYPE
47 changes: 23 additions & 24 deletions google_drive/tests/unit/test_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import unittest

from mock import Mock
from nose.tools import assert_equal, assert_in
from workbench.runtime import WorkbenchRuntime
from xblock.runtime import DictKeyValueStore, KvsFieldData

Expand Down Expand Up @@ -76,79 +75,79 @@ def make_document_block(cls):
ids = generate_scope_ids(runtime, 'google_document')
return GoogleDocumentBlock(runtime, db_model, scope_ids=ids)

def test_document_template_content(self): # pylint: disable=no-self-use
def test_document_template_content(self):
""" Test content of GoogleDocumentBlock's rendered views """
block = TestGoogleDocumentBlock.make_document_block()
block.usage_id = Mock()

student_fragment = block.render('student_view', Mock())
# pylint: disable=no-value-for-parameter
assert_in('<div class="google-docs-xblock-wrapper"', student_fragment.content)
assert_in('Google Document', student_fragment.content)
assert_in(DEFAULT_EMBED_CODE, student_fragment.content)
assert '<div class="google-docs-xblock-wrapper"' in student_fragment.content
assert 'Google Document' in student_fragment.content
assert DEFAULT_EMBED_CODE in student_fragment.content

studio_fragment = block.render('studio_view', Mock())
assert_in(STUDIO_EDIT_WRAPPER, studio_fragment.content)
assert_in(VALIDATION_WRAPPER, studio_fragment.content)
assert_in(USER_INPUTS_WRAPPER, studio_fragment.content)
assert_in(BUTTONS_WRAPPER, studio_fragment.content)
assert STUDIO_EDIT_WRAPPER in studio_fragment.content
assert VALIDATION_WRAPPER in studio_fragment.content
assert USER_INPUTS_WRAPPER in studio_fragment.content
assert BUTTONS_WRAPPER in studio_fragment.content

def test_studio_document_submit(self): # pylint: disable=no-self-use
def test_studio_document_submit(self):
""" Test studio submission of GoogleDocumentBlock """
block = TestGoogleDocumentBlock.make_document_block()

body = json.dumps(TEST_SUBMIT_DATA)
res = block.handle('studio_submit', make_request(body))
# pylint: disable=no-value-for-parameter
assert_equal(json.loads(res.body.decode('utf8')), RESULT_SUCCESS)
assert json.loads(res.body.decode('utf8')) == RESULT_SUCCESS

assert_equal(block.display_name, TEST_SUBMIT_DATA['display_name'])
assert_equal(block.embed_code, TEST_SUBMIT_DATA['embed_code'])
assert_equal(block.alt_text, TEST_SUBMIT_DATA['alt_text'])
assert block.display_name == TEST_SUBMIT_DATA['display_name']
assert block.embed_code == TEST_SUBMIT_DATA['embed_code']
assert block.alt_text == TEST_SUBMIT_DATA['alt_text']

body = json.dumps('')
res = block.handle('studio_submit', make_request(body))
assert_equal(json.loads(res.body.decode('utf8')), RESULT_ERROR)
assert json.loads(res.body.decode('utf8')) == RESULT_ERROR

def test_check_document_url(self): # pylint: disable=no-self-use
def test_check_document_url(self):
""" Test verification of the provided Google Document URL"""
block = TestGoogleDocumentBlock.make_document_block()

data = json.dumps(TEST_VALIDATE_URL_DATA)
res = block.handle('check_url', make_request(data))
# pylint: disable=no-value-for-parameter
assert_equal(json.loads(res.body.decode('utf8')), STATUS_CODE_200)
assert json.loads(res.body.decode('utf8')) == STATUS_CODE_200

data = json.dumps(TEST_VALIDATE_UNDEFINED_DATA)
res = block.handle('check_url', make_request(data))

assert_equal(json.loads(res.body.decode('utf8')), STATUS_CODE_400)
assert json.loads(res.body.decode('utf8')) == STATUS_CODE_400

data = json.dumps(TEST_VALIDATE_NONEXISTENT_URL_DATA)
res = block.handle('check_url', make_request(data))

assert_equal(json.loads(res.body.decode('utf8')), STATUS_CODE_404)
assert json.loads(res.body.decode('utf8')) == STATUS_CODE_404

data = json.dumps({})
res = block.handle('check_url', make_request(data))

assert_equal(json.loads(res.body.decode('utf8')), STATUS_CODE_400)
assert json.loads(res.body.decode('utf8')) == STATUS_CODE_400

def test_document_publish_event(self): # pylint: disable=no-self-use
def test_document_publish_event(self):
""" Test event publishing in GoogleDocumentBlock"""
block = TestGoogleDocumentBlock.make_document_block()

body = json.dumps(TEST_COMPLETE_PUBLISH_DOCUMENT_DATA)
res = block.handle('publish_event', make_request(body))
# pylint: disable=no-value-for-parameter
assert_equal(json.loads(res.body.decode('utf8')), RESULT_SUCCESS)
assert json.loads(res.body.decode('utf8')) == RESULT_SUCCESS

body = json.dumps(TEST_COMPLETE_PUBLISH_IMAGE_DATA)
res = block.handle('publish_event', make_request(body))

assert_equal(json.loads(res.body.decode('utf8')), RESULT_SUCCESS)
assert json.loads(res.body.decode('utf8')) == RESULT_SUCCESS

body = json.dumps(TEST_INCOMPLETE_PUBLISH_DATA)
res = block.handle('publish_event', make_request(body))

assert_equal(json.loads(res.body.decode('utf8')), RESULT_MISSING_EVENT_TYPE)
assert json.loads(res.body.decode('utf8')) == RESULT_MISSING_EVENT_TYPE
32 changes: 17 additions & 15 deletions requirements/ci.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
#
# make upgrade
#
asgiref==3.7.2
asgiref==3.8.1
# via django
cachetools==5.3.2
backports-zoneinfo==0.2.1 ; python_version < "3.9"
# via
# -c requirements/constraints.txt
# django
cachetools==5.3.3
# via tox
certifi==2024.2.2
# via requests
Expand All @@ -22,27 +26,27 @@ coveralls==3.3.1
# via -r requirements/ci.in
distlib==0.3.8
# via virtualenv
django==3.2.24
django==4.2.11
# via
# -c requirements/common_constraints.txt
# edx-i18n-tools
docopt==0.6.2
# via coveralls
edx-i18n-tools==1.3.0
edx-i18n-tools==1.5.0
# via -r requirements/ci.in
filelock==3.13.1
filelock==3.13.4
# via
# tox
# virtualenv
idna==3.6
idna==3.7
# via requests
lxml==5.1.0
lxml==5.2.1
# via edx-i18n-tools
packaging==23.2
packaging==24.0
# via
# pyproject-api
# tox
path==16.10.0
path==16.14.0
# via edx-i18n-tools
platformdirs==4.2.0
# via
Expand All @@ -54,23 +58,21 @@ polib==1.2.0
# via edx-i18n-tools
pyproject-api==1.6.1
# via tox
pytz==2024.1
# via django
pyyaml==6.0.1
# via edx-i18n-tools
requests==2.31.0
# via coveralls
sqlparse==0.4.4
sqlparse==0.5.0
# via django
tomli==2.0.1
# via
# pyproject-api
# tox
tox==4.13.0
tox==4.14.2
# via -r requirements/ci.in
typing-extensions==4.10.0
typing-extensions==4.11.0
# via asgiref
urllib3==2.2.1
# via requests
virtualenv==20.25.1
virtualenv==20.25.2
# via tox
11 changes: 10 additions & 1 deletion requirements/common_constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,20 @@


# using LTS django version
Django<4.0
Django<5.0

# elasticsearch>=7.14.0 includes breaking changes in it which caused issues in discovery upgrade process.
# elastic search changelog: https://www.elastic.co/guide/en/enterprise-search/master/release-notes-7.14.0.html
elasticsearch<7.14.0

# django-simple-history>3.0.0 adds indexing and causes a lot of migrations to be affected
django-simple-history==3.0.0

# opentelemetry requires version 6.x at the moment:
# https://github.com/open-telemetry/opentelemetry-python/issues/3570
# Normally this could be added as a constraint in edx-django-utils, where we're
# adding the opentelemetry dependency. However, when we compile pip-tools.txt,
# that uses version 7.x, and then there's no undoing that when compiling base.txt.
# So we need to pin it globally, for now.
# Ticket for unpinning: https://github.com/openedx/edx-lint/issues/407
importlib-metadata<7
4 changes: 2 additions & 2 deletions requirements/constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@

-c common_constraints.txt

# TODO: Many pinned dependencies should be unpinned and/or moved to this constraints file.
pylint==2.12.2
# Temporary to Support the python 3.11 Upgrade
backports.zoneinfo;python_version<"3.9" # Newer versions have zoneinfo available in the standard library
Loading
Loading