diff --git a/changelog.d/20230209_092607_regis_sec_lti.md b/changelog.d/20230209_092607_regis_sec_lti.md new file mode 100644 index 0000000..e2134b3 --- /dev/null +++ b/changelog.d/20230209_092607_regis_sec_lti.md @@ -0,0 +1 @@ +- [Security] Fix grading issue in LTI consumer XBlock. See [security advisory](https://github.com/openedx/xblock-lti-consumer/security/advisories/GHSA-7j9p-67mm-5g87). (by @regisb) diff --git a/docs/conf.py b/docs/conf.py index d6539b8..92f9a54 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -112,6 +112,7 @@ rst_prolog = f""" .. |tutor_version| replace:: {about["__version__"]} """ + # Custom directives def youtube( _name: Any, diff --git a/requirements/base.txt b/requirements/base.txt index 9a0c9df..b37b28f 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,34 +1,36 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.7 # by the following command: # # pip-compile requirements/base.in # appdirs==1.4.4 # via -r requirements/base.in -cachetools==5.2.0 +cachetools==5.3.0 # via google-auth certifi==2022.12.7 # via # kubernetes # requests -charset-normalizer==2.1.1 +charset-normalizer==3.0.1 # via requests click==8.1.3 # via -r requirements/base.in -google-auth==2.15.0 +google-auth==2.16.0 # via kubernetes idna==3.4 # via requests +importlib-metadata==6.0.0 + # via click jinja2==3.1.2 # via -r requirements/base.in kubernetes==25.3.0 # via -r requirements/base.in -markupsafe==2.1.1 +markupsafe==2.1.2 # via jinja2 -mypy==0.991 +mypy==1.0.0 # via -r requirements/base.in -mypy-extensions==0.4.3 +mypy-extensions==1.0.0 # via mypy oauthlib==3.2.2 # via requests-oauthlib @@ -38,7 +40,7 @@ pyasn1==0.4.8 # rsa pyasn1-modules==0.2.8 # via google-auth -pycryptodome==3.16.0 +pycryptodome==3.17 # via -r requirements/base.in python-dateutil==2.8.2 # via kubernetes @@ -46,7 +48,7 @@ pyyaml==6.0 # via # -r requirements/base.in # kubernetes -requests==2.28.1 +requests==2.28.2 # via # kubernetes # requests-oauthlib @@ -61,16 +63,21 @@ six==1.16.0 # python-dateutil tomli==2.0.1 # via mypy +typed-ast==1.5.4 + # via mypy typing-extensions==4.4.0 # via # -r requirements/base.in + # importlib-metadata # mypy -urllib3==1.26.13 +urllib3==1.26.14 # via # kubernetes # requests -websocket-client==1.4.2 +websocket-client==1.5.1 # via kubernetes +zipp==3.12.1 + # via importlib-metadata # The following packages are considered to be unsafe in a requirements file: # setuptools diff --git a/requirements/dev.txt b/requirements/dev.txt index caa9d45..49387b8 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with python 3.8 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.7 +# by the following command: # # pip-compile requirements/dev.in # @@ -8,17 +8,17 @@ altgraph==0.17.3 # via pyinstaller appdirs==1.4.4 # via -r requirements/base.txt -astroid==2.12.13 +astroid==2.14.1 # via pylint -attrs==22.1.0 +attrs==22.2.0 # via scriv -black==22.10.0 +black==23.1.0 # via -r requirements/dev.in -bleach==5.0.1 +bleach==6.0.0 # via readme-renderer -build==0.9.0 +build==0.10.0 # via pip-tools -cachetools==5.2.0 +cachetools==5.3.0 # via # -r requirements/base.txt # google-auth @@ -29,7 +29,7 @@ certifi==2022.12.7 # requests cffi==1.15.1 # via cryptography -charset-normalizer==2.1.1 +charset-normalizer==3.0.1 # via # -r requirements/base.txt # requests @@ -42,11 +42,9 @@ click==8.1.3 # scriv click-log==0.4.0 # via scriv -commonmark==0.9.1 - # via rich -coverage==6.5.0 +coverage==7.1.0 # via -r requirements/dev.in -cryptography==38.0.4 +cryptography==39.0.1 # via secretstorage dill==0.3.6 # via pylint @@ -54,7 +52,7 @@ docutils==0.17.1 # via # -r requirements/dev.in # readme-renderer -google-auth==2.15.0 +google-auth==2.16.0 # via # -r requirements/base.txt # kubernetes @@ -64,9 +62,15 @@ idna==3.4 # requests importlib-metadata==6.0.0 # via + # -r requirements/base.txt + # build + # click # keyring + # pyinstaller # twine -isort==5.10.1 +importlib-resources==5.10.2 + # via keyring +isort==5.11.5 # via pylint jaraco-classes==3.2.3 # via keyring @@ -78,23 +82,27 @@ jinja2==3.1.2 # via # -r requirements/base.txt # scriv -keyring==23.11.0 +keyring==23.13.1 # via twine kubernetes==25.3.0 # via -r requirements/base.txt -lazy-object-proxy==1.8.0 +lazy-object-proxy==1.9.0 # via astroid -markupsafe==2.1.1 +markdown-it-py==2.1.0 + # via rich +markupsafe==2.1.2 # via # -r requirements/base.txt # jinja2 mccabe==0.7.0 # via pylint +mdurl==0.1.2 + # via markdown-it-py more-itertools==9.0.0 # via jaraco-classes -mypy==0.991 +mypy==1.0.0 # via -r requirements/base.txt -mypy-extensions==0.4.3 +mypy-extensions==1.0.0 # via # -r requirements/base.txt # black @@ -103,17 +111,17 @@ oauthlib==3.2.2 # via # -r requirements/base.txt # requests-oauthlib -packaging==22.0 - # via build -pathspec==0.10.2 +packaging==23.0 + # via + # black + # build +pathspec==0.11.0 # via black -pep517==0.13.0 - # via build -pip-tools==6.11.0 +pip-tools==6.12.2 # via -r requirements/dev.in -pkginfo==1.9.2 +pkginfo==1.9.6 # via twine -platformdirs==2.6.0 +platformdirs==3.0.0 # via # black # pylint @@ -128,18 +136,20 @@ pyasn1-modules==0.2.8 # google-auth pycparser==2.21 # via cffi -pycryptodome==3.16.0 +pycryptodome==3.17 # via -r requirements/base.txt -pygments==2.13.0 +pygments==2.14.0 # via # readme-renderer # rich pyinstaller==5.7.0 # via -r requirements/dev.in -pyinstaller-hooks-contrib==2022.14 +pyinstaller-hooks-contrib==2022.15 # via pyinstaller -pylint==2.15.8 +pylint==2.16.1 # via -r requirements/dev.in +pyproject-hooks==1.0.0 + # via build python-dateutil==2.8.2 # via # -r requirements/base.txt @@ -150,7 +160,7 @@ pyyaml==6.0 # kubernetes readme-renderer==37.3 # via twine -requests==2.28.1 +requests==2.28.2 # via # -r requirements/base.txt # kubernetes @@ -166,13 +176,13 @@ requests-toolbelt==0.10.1 # via twine rfc3986==2.0.0 # via twine -rich==12.6.0 +rich==13.3.1 # via twine rsa==4.9 # via # -r requirements/base.txt # google-auth -scriv==1.1.0 +scriv==1.2.0 # via -r requirements/dev.in secretstorage==3.3.3 # via keyring @@ -189,27 +199,38 @@ tomli==2.0.1 # black # build # mypy - # pep517 # pylint + # pyproject-hooks tomlkit==0.11.6 # via pylint twine==4.0.2 # via -r requirements/dev.in -types-docutils==0.19.1.1 +typed-ast==1.5.4 + # via + # -r requirements/base.txt + # astroid + # black + # mypy +types-docutils==0.19.1.3 + # via + # -r requirements/dev.in + # types-setuptools +types-pyyaml==6.0.12.4 # via -r requirements/dev.in -types-pyyaml==6.0.12.2 - # via -r requirements/dev.in -types-setuptools==65.6.0.2 +types-setuptools==67.2.0.1 # via -r requirements/dev.in typing-extensions==4.4.0 # via # -r requirements/base.txt # astroid # black + # importlib-metadata + # markdown-it-py # mypy + # platformdirs # pylint # rich -urllib3==1.26.13 +urllib3==1.26.14 # via # -r requirements/base.txt # kubernetes @@ -217,7 +238,7 @@ urllib3==1.26.13 # twine webencodings==0.5.1 # via bleach -websocket-client==1.4.2 +websocket-client==1.5.1 # via # -r requirements/base.txt # kubernetes @@ -225,8 +246,11 @@ wheel==0.38.4 # via pip-tools wrapt==1.14.1 # via astroid -zipp==3.11.0 - # via importlib-metadata +zipp==3.12.1 + # via + # -r requirements/base.txt + # importlib-metadata + # importlib-resources # The following packages are considered to be unsafe in a requirements file: # pip diff --git a/requirements/docs.txt b/requirements/docs.txt index afd1b36..150ef71 100644 --- a/requirements/docs.txt +++ b/requirements/docs.txt @@ -1,16 +1,16 @@ # -# This file is autogenerated by pip-compile with Python 3.8 +# This file is autogenerated by pip-compile with Python 3.7 # by the following command: # # pip-compile requirements/docs.in # -alabaster==0.7.12 +alabaster==0.7.13 # via sphinx appdirs==1.4.4 # via -r requirements/base.txt babel==2.11.0 # via sphinx -cachetools==5.2.0 +cachetools==5.3.0 # via # -r requirements/base.txt # google-auth @@ -19,7 +19,7 @@ certifi==2022.12.7 # -r requirements/base.txt # kubernetes # requests -charset-normalizer==2.1.1 +charset-normalizer==3.0.1 # via # -r requirements/base.txt # requests @@ -27,12 +27,12 @@ click==8.1.3 # via # -r requirements/base.txt # sphinx-click -docutils==0.17.1 +docutils==0.18.1 # via # sphinx # sphinx-click # sphinx-rtd-theme -google-auth==2.15.0 +google-auth==2.16.0 # via # -r requirements/base.txt # kubernetes @@ -43,20 +43,23 @@ idna==3.4 imagesize==1.4.1 # via sphinx importlib-metadata==6.0.0 - # via sphinx + # via + # -r requirements/base.txt + # click + # sphinx jinja2==3.1.2 # via # -r requirements/base.txt # sphinx kubernetes==25.3.0 # via -r requirements/base.txt -markupsafe==2.1.1 +markupsafe==2.1.2 # via # -r requirements/base.txt # jinja2 -mypy==0.991 +mypy==1.0.0 # via -r requirements/base.txt -mypy-extensions==0.4.3 +mypy-extensions==1.0.0 # via # -r requirements/base.txt # mypy @@ -64,7 +67,7 @@ oauthlib==3.2.2 # via # -r requirements/base.txt # requests-oauthlib -packaging==22.0 +packaging==23.0 # via sphinx pyasn1==0.4.8 # via @@ -75,21 +78,21 @@ pyasn1-modules==0.2.8 # via # -r requirements/base.txt # google-auth -pycryptodome==3.16.0 +pycryptodome==3.17 # via -r requirements/base.txt -pygments==2.13.0 +pygments==2.14.0 # via sphinx python-dateutil==2.8.2 # via # -r requirements/base.txt # kubernetes -pytz==2022.6 +pytz==2022.7.1 # via babel pyyaml==6.0 # via # -r requirements/base.txt # kubernetes -requests==2.28.1 +requests==2.28.2 # via # -r requirements/base.txt # kubernetes @@ -118,7 +121,7 @@ sphinx==5.3.0 # sphinx-rtd-theme sphinx-click==4.4.0 # via -r requirements/docs.in -sphinx-rtd-theme==1.1.1 +sphinx-rtd-theme==1.2.0 # via -r requirements/docs.in sphinxcontrib-applehelp==1.0.2 # via sphinx @@ -126,6 +129,8 @@ sphinxcontrib-devhelp==1.0.2 # via sphinx sphinxcontrib-htmlhelp==2.0.0 # via sphinx +sphinxcontrib-jquery==2.0.0 + # via sphinx-rtd-theme sphinxcontrib-jsmath==1.0.1 # via sphinx sphinxcontrib-qthelp==1.0.3 @@ -136,21 +141,28 @@ tomli==2.0.1 # via # -r requirements/base.txt # mypy -typing-extensions==4.4.0 +typed-ast==1.5.4 # via # -r requirements/base.txt # mypy -urllib3==1.26.13 +typing-extensions==4.4.0 + # via + # -r requirements/base.txt + # importlib-metadata + # mypy +urllib3==1.26.14 # via # -r requirements/base.txt # kubernetes # requests -websocket-client==1.4.2 +websocket-client==1.5.1 # via # -r requirements/base.txt # kubernetes -zipp==3.11.0 - # via importlib-metadata +zipp==3.12.1 + # via + # -r requirements/base.txt + # importlib-metadata # The following packages are considered to be unsafe in a requirements file: # setuptools diff --git a/tests/commands/test_compose.py b/tests/commands/test_compose.py index 77ca602..9cccfb9 100644 --- a/tests/commands/test_compose.py +++ b/tests/commands/test_compose.py @@ -13,7 +13,6 @@ from tutor.commands.local import LocalContext class ComposeTests(unittest.TestCase): - maxDiff = None # Ensure we can see long diffs of YAML files. def test_mount_option_parsing(self) -> None: diff --git a/tutor/commands/config.py b/tutor/commands/config.py index 0c7eb49..a95e825 100644 --- a/tutor/commands/config.py +++ b/tutor/commands/config.py @@ -24,7 +24,6 @@ def config_command() -> None: class ConfigKeyParamType(click.ParamType): - name = "configkey" def shell_complete( diff --git a/tutor/core/hooks/actions.py b/tutor/core/hooks/actions.py index 7562181..e6050d9 100644 --- a/tutor/core/hooks/actions.py +++ b/tutor/core/hooks/actions.py @@ -14,15 +14,13 @@ from .contexts import Contextualized #: Action generic signature. T = ParamSpec("T") -# Similarly to CallableFilter, it should be possible to create a CallableAction alias in -# the future. -# CallableAction = t.Callable[T, None] +ActionCallbackFunc = t.Callable[T, None] class ActionCallback(Contextualized, t.Generic[T]): def __init__( self, - func: t.Callable[T, None], + func: ActionCallbackFunc[T], priority: t.Optional[int] = None, ): super().__init__() @@ -75,7 +73,7 @@ class Action(t.Generic[T]): def add( self, priority: t.Optional[int] = None - ) -> t.Callable[[t.Callable[T, None]], t.Callable[T, None]]: + ) -> t.Callable[[ActionCallbackFunc[T]], ActionCallbackFunc[T]]: """ Decorator to add a callback to an action. @@ -97,7 +95,7 @@ class Action(t.Generic[T]): to return any value. Returned values will be ignored. """ - def inner(func: t.Callable[T, None]) -> t.Callable[T, None]: + def inner(func: ActionCallbackFunc[T]) -> ActionCallbackFunc[T]: callback = ActionCallback(func, priority=priority) priorities.insert_callback(callback, self.callbacks) return func @@ -218,7 +216,7 @@ def get_template(name: str) -> ActionTemplate[t.Any]: def add( name: str, priority: t.Optional[int] = None -) -> t.Callable[[t.Callable[T, None]], t.Callable[T, None]]: +) -> t.Callable[[ActionCallbackFunc[T]], ActionCallbackFunc[T]]: """ Decorator to add a callback action associated to a name. """ diff --git a/tutor/core/hooks/filters.py b/tutor/core/hooks/filters.py index f2b505e..c513bae 100644 --- a/tutor/core/hooks/filters.py +++ b/tutor/core/hooks/filters.py @@ -17,16 +17,13 @@ T2 = ParamSpec("T2") #: Specialized typevar for list elements L = t.TypeVar("L") -# I wish we could create such an alias, which would greatly simply the definitions -# below. Unfortunately this does not work, yet. It will once the following issue is -# resolved: https://github.com/python/mypy/issues/11855 -# CallableFilter = t.Callable[Concatenate[T1, T2], T1] +FilterCallbackFunc = t.Callable[Concatenate[T1, T2], T1] class FilterCallback(contexts.Contextualized, t.Generic[T1, T2]): def __init__( self, - func: t.Callable[Concatenate[T1, T2], T1], + func: FilterCallbackFunc[T1, T2], priority: t.Optional[int] = None, ): super().__init__() @@ -83,9 +80,7 @@ class Filter(t.Generic[T1, T2]): def add( self, priority: t.Optional[int] = None - ) -> t.Callable[ - [t.Callable[Concatenate[T1, T2], T1]], t.Callable[Concatenate[T1, T2], T1] - ]: + ) -> t.Callable[[FilterCallbackFunc[T1, T2]], FilterCallbackFunc[T1, T2]]: """ Decorator to add a filter callback. @@ -112,10 +107,8 @@ class Filter(t.Generic[T1, T2]): final_value = my_filter.apply(initial_value, some_other_argument_value) """ - def inner( - func: t.Callable[Concatenate[T1, T2], T1] - ) -> t.Callable[Concatenate[T1, T2], T1]: - callback = FilterCallback(func, priority=priority) + def inner(func: FilterCallbackFunc[T1, T2]) -> FilterCallbackFunc[T1, T2]: + callback: FilterCallback[T1, T2] = FilterCallback(func, priority=priority) priorities.insert_callback(callback, self.callbacks) return func @@ -156,7 +149,6 @@ class Filter(t.Generic[T1, T2]): for callback in self.callbacks: if callback.is_in_context(context): try: - value = callback.apply( value, *args, @@ -232,6 +224,7 @@ class Filter(t.Generic[T1, T2]): my_filter.add_item("item1") my_filter.add_item("item2") """ + # Unfortunately we have to type-ignore this line. If not, mypy complains with: # # Argument 1 has incompatible type "Callable[[Arg(List[E], 'values'), **T2], List[E]]"; expected "Callable[[List[E], **T2], List[E]]" @@ -318,9 +311,7 @@ def get_template(name: str) -> FilterTemplate[t.Any, t.Any]: def add( name: str, priority: t.Optional[int] = None -) -> t.Callable[ - [t.Callable[Concatenate[T1, T2], T1]], t.Callable[Concatenate[T1, T2], T1] -]: +) -> t.Callable[[FilterCallbackFunc[T1, T2]], FilterCallbackFunc[T1, T2]]: """ Decorator for functions that will be applied to a single named filter. """ diff --git a/tutor/hooks/catalog.py b/tutor/hooks/catalog.py index cb45f1f..7e9a239 100644 --- a/tutor/hooks/catalog.py +++ b/tutor/hooks/catalog.py @@ -212,7 +212,7 @@ class Filters: #: - ``path`` is a tuple that corresponds to a template relative path. #: Example: ``("myplugin", "hooks", "myservice", "pre-init")`` (see :py:data:`IMAGES_BUILD`). #: The command to execute will be read from that template, after it is rendered. - COMMANDS_INIT: Filter[list[tuple[str, tuple[str, ...]]], str] = filters.get( + COMMANDS_INIT: Filter[list[tuple[str, tuple[str, ...]]], []] = filters.get( "commands:init" )