diff --git a/pyproject.toml b/pyproject.toml index 5aab6cf8f5..60a8d20b23 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -204,3 +204,195 @@ junit_family = "xunit2" norecursedirs = ". .* *.egg build conf dist node_modules test_root cms/envs lms/envs openedx/envs" python_classes = [] python_files = ["tests.py", "test_*.py", "tests_*.py", "*_tests.py", "__init__.py"] + +[tool.isort] +indent = " " +line_length = 120 +multi_line_output = 3 +skip = ["envs", "migrations"] + +[tool.importlinter] +root_packages = ["lms", "cms", "openedx", "openedx_content"] +include_external_packages = true +# Our custom contract which checks that we're only importing from 'api.py' +# for participating packages. +contract_types = [ + "isolated_apps: openedx.testing.importlinter.isolated_apps_contract.IsolatedAppsContract", +] + +[[tool.importlinter.contracts]] +name = "lms and cms are independent" +type = "independence" +modules = ["lms", "cms"] +ignore_imports = [ + # lms side imports that we are ignoring for now + "lms.djangoapps.course_home_api.outline.tests.test_view -> cms.djangoapps.contentstore.outlines", + "lms.djangoapps.course_home_api.tests.utils -> cms.djangoapps.contentstore.outlines", + # lms.djangoapps.instructor.tests.test_api & lms.djangoapps.instructor.tests.test_tools + # -> openedx.core.djangoapps.course_date_signals.handlers + # -> cms.djangoapps.contentstore.config.waffle + "openedx.core.djangoapps.course_date_signals.handlers -> cms.djangoapps.contentstore.config.waffle", + # cms side imports that we are ignoring for now + "cms.djangoapps.contentstore.views.tests.test_block -> lms.djangoapps.lms_xblock.mixin", + "cms.djangoapps.contentstore.signals.handlers -> lms.djangoapps.grades.api", + "cms.djangoapps.contentstore.course_group_config -> lms.lib.utils", + "cms.djangoapps.contentstore.views.preview -> lms.djangoapps.lms_xblock.field_data", + # cms.envs.common + # -> openedx.envs.common + # -> lms.djangoapps.lms_xblock.mixin + "openedx.envs.common -> lms.djangoapps.lms_xblock.mixin", + # cms.djangoapps.contentstore.views.tests.test_group_configurations + # -> openedx.features.content_type_gating.helpers + # -> lms.djangoapps.courseware.masquerade + "openedx.features.content_type_gating.helpers -> lms.djangoapps.courseware.masquerade", + # cms.djangoapps.contentstore.utils + # -> openedx.core.djangoapps.django_comment_common.models + # -> openedx.core.djangoapps.course_groups.cohorts + # -> lms.djangoapps.courseware.courses + "openedx.core.djangoapps.course_groups.cohorts -> lms.djangoapps.courseware.courses", + # cms.djangoapps.contentstore.[various] + # -> openedx.features.content_type_gating.partitions + # -> lms.djangoapps.commerce.utils + "openedx.features.content_type_gating.partitions -> lms.djangoapps.commerce.utils", + # cms.djangoapps.contentstore.course_group_config + # -> openedx.core.djangoapps.course_groups.partition_scheme + # -> lms.djangoapps.courseware.masquerade + "openedx.core.djangoapps.course_groups.partition_scheme -> lms.djangoapps.courseware.masquerade", + # cms.djangoapps.export_course_metadata.tasks + # -> openedx.core.djangoapps.schedules.content_highlights + # -> lms.djangoapps.courseware.block_render & lms.djangoapps.courseware.model_data + "openedx.core.djangoapps.content_libraries.* -> lms.djangoapps.*.*", + # cms.djangoapps.contentstore.tasks -> openedx.core.djangoapps.content_libraries.[various] + # -> lms.djangoapps.grades.api + "openedx.core.djangoapps.xblock.*.* -> lms.djangoapps.*.*", + # cms.djangoapps.contentstore.tasks -> openedx.core.djangoapps.content_libraries.[various] -> openedx.core.djangoapps.xblock.[various] + # -> lms.djangoapps.courseware & lms.djangoapps.courseware.grades + "openedx.core.djangoapps.schedules.content_highlights -> lms.djangoapps.courseware.*", + # cms.djangoapps.contentstore.[various] + # -> openedx.core.lib.gating.api + # -> lms.djangoapps.course_blocks.api & lms.djangoapps.courseware.access & lms.djangoapps.grades.api + "openedx.core.lib.gating.api -> lms.djangoapps.*.*", + # cms.djangoapps.contentstore.[various] + # -> openedx.features.content_type_gating.partitions + # -> openedx.features.discounts.utils + # -> lms.djangoapps.courseware.utils & lms.djangoapps.experiments.models + "openedx.features.discounts.utils -> lms.djangoapps.courseware.utils", + "openedx.features.discounts.utils -> lms.djangoapps.experiments.models", + # cms.djangoapps.contentstore.signals.handlers + # -> openedx.core.djangoapps.discussions.tasks + # -> openedx.core.djangoapps.discussions.utils + # -> lms.djangoapps.courseware.access + "openedx.core.djangoapps.discussions.utils -> lms.djangoapps.courseware.access", + # cms.djangoapps.contentstore.[various] + # -> openedx.features.content_type_gating.partitions + # -> openedx.features.discounts.utils + # -> openedx.features.discounts.applicability + # -> lms.djangoapps.courseware.toggles + # & lms.djangoapps.courseware.utils + # & lms.djangoapps.experiments.models + # & lms.djangoapps.experiments.stable_bucketing + "openedx.features.discounts.applicability -> lms.djangoapps.courseware.*", + "openedx.features.discounts.applicability -> lms.djangoapps.experiments.*", + # cms.djangoapps.contentstore.[various] + # -> openedx.core.djangoapps.content.learning_sequences.api + # -> openedx.core.djangoapps.content.learning_sequences.api.outlines + # -> openedx.core.djangoapps.content.learning_sequences.api.permissions + # -> lms.djangoapps.courseware.access + "openedx.core.djangoapps.content.learning_sequences.api.permissions -> lms.djangoapps.courseware.access", + # cms.djangoapps.contentstore.[various] + # -> openedx.features.content_type_gating.partitions + # -> openedx.features.discounts.utils + # -> openedx.features.discounts.applicability + # -> openedx.features.enterprise_support.utils + "openedx.features.enterprise_support.utils -> lms.djangoapps.branding.api", + "cms.djangoapps.contentstore.rest_api.v1.views.settings -> lms.djangoapps.certificates.api", + # We are ignoring this existing import until we can refactor contenstore/helpers. + # https://github.com/openedx/edx-platform/issues/37637 + "openedx.core.djangoapps.content_libraries.api.libraries -> cms.djangoapps.contentstore.helpers", + "openedx.core.djangoapps.content_libraries.api.blocks -> cms.djangoapps.contentstore.helpers", + "openedx.core.djangoapps.content_staging.serializers -> cms.djangoapps.contentstore.helpers", + # These imports will become OK once we move content_libraries into CMS + # https://github.com/openedx/edx-platform/issues/33428 + "openedx.core.djangoapps.content_libraries.permissions -> cms.djangoapps.course_creators.views", + "openedx.core.djangoapps.content_libraries.tasks -> cms.djangoapps.contentstore.storage", + # Outstanding arch issue: course_overviews is tangled up with LMS + # https://github.com/openedx/edx-platform/issues/37658 + "openedx.core.djangoapps.content.course_overviews.models -> lms.djangoapps.**", + # Outstanding arch issue: content_highlights uses courseware block_render + # https://github.com/openedx/edx-platform/issues/37659 + "openedx.core.djangoapps.schedules.content_highlights -> lms.djangoapps.courseware.block_render", +] + +[[tool.importlinter.contracts]] +name = "Do not depend on non-public API of isolated apps." +type = "isolated_apps" +isolated_apps = [ + "cms.djangoapps.modulestore_migrator", + "openedx.core.djangoapps.agreements", + "openedx.core.djangoapps.bookmarks", + "openedx.core.djangoapps.content_libraries", + "openedx.core.djangoapps.content_staging", + "openedx.core.djangoapps.olx_rest_api", + "openedx.core.djangoapps.xblock", + "openedx.core.lib.xblock_serializer", +] +allowed_modules = [ + # Only imports from api.py and data.py are allowed elsewhere in the code + # See https://open-edx-proposals.readthedocs.io/en/latest/best-practices/oep-0049-django-app-patterns.html#api-py + "api", + "data", + "tests", +] + +[[tool.importlinter.contracts]] +name = "Do not directly import internals of openedx_content (only import from openedx_content.api)." +type = "forbidden" +source_modules = ["cms", "lms", "openedx", "common", "xmodule"] +forbidden_modules = ["openedx_content.applets", "openedx_content.backcompat"] +allow_indirect_imports = true + +[[tool.importlinter.contracts]] +name = "Low-level apps should not depend on high-level apps" +type = "layers" +layers = [ + # Layers from high-level to low-level. Imports should only occur from higher to lower. + "cms.lib.xblock.upstream_sync | openedx.core.djangoapps.content.search | openedx.core.djangoapps.olx_rest_api", + "openedx.core.djangoapps.content_libraries", + "openedx.core.djangoapps.content_staging", + "openedx.core.djangoapps.xblock", + "openedx.core.lib.xblock_serializer", + "openedx.core.djangoapps.content_tagging", +] +ignore_imports = [ + # Test code can break these layering rules + "**.tests.** -> **", + # FIXME: the exceptions below are from before we added this import linting rule. Should refactor to eliminate them. + # In particular, the contentstore.helpers module is too big and has too many imports + # See https://github.com/openedx/edx-platform/issues/37637 + # The CSV export hard-codes support for courses and libraries. Refactor to do something like learning_context.get_children() + "openedx.core.djangoapps.content_tagging.helpers.objecttag_export_helpers -> openedx.core.djangoapps.content_libraries.api", + # The permissions checking code for tagging requires libraries model data to get all the orgs that a user is using: + "openedx.core.djangoapps.content_tagging.utils -> openedx.core.djangoapps.content_libraries.api", + # Content staging POST to clipboard API uses libraries APIs. We're working on moving this code to content_libraries + "openedx.core.djangoapps.content_staging.views -> openedx.core.djangoapps.content_libraries.api", + # content_staging.serializers imports contentstore.helpers which imports contentstore.utils which imports the libraries API. + "openedx.core.djangoapps.content_staging.serializers -> cms.djangoapps.contentstore.helpers", + # content_libraries.rest_api.libraries imports cms.djangoapps.contentstore.views.course which imports + # contentstore.toggles which imports djangoapps.content.search.api + "openedx.core.djangoapps.content_libraries.rest_api.libraries -> cms.djangoapps.contentstore.views.course", + # Content libraries imports contentstore.helpers which imports upstream_sync + "openedx.core.djangoapps.content_libraries.api.blocks -> cms.djangoapps.contentstore.helpers", + "openedx.core.djangoapps.content_libraries.api.libraries -> cms.djangoapps.contentstore.helpers", + # Outstanding arch issue: course_overviews is tangled up with LMS + # https://github.com/openedx/edx-platform/issues/37658 + "openedx.core.djangoapps.content.course_overviews.models -> lms.djangoapps.**", + # Outstanding arch issue: content_highlights uses courseware block_render + # https://github.com/openedx/edx-platform/issues/37659 + "openedx.core.djangoapps.schedules.content_highlights -> lms.djangoapps.courseware.block_render", + # This import happens only because grading signals are defined in LMS rather than openedx-events + # https://github.com/openedx/edx-platform/issues/37660 + "openedx.core.djangoapps.xblock.runtime.runtime -> lms.djangoapps.grades.api", + # These imports will become OK once we worked on the following issue: + # https://github.com/openedx/edx-platform/issues/33428 + "openedx.core.djangoapps.video_config.services -> openedx.core.djangoapps.content_libraries.api", +] diff --git a/setup.cfg b/setup.cfg index 78236a2881..7e1ab370a0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,208 +20,3 @@ # 1.5.7 that we haven't cleaned up yet ignore=E203,E265,E266,E305,E402,E501,E722,E731,E741,E743,W503,W504,W602 exclude=migrations,.git,.pycharm_helpers,.tox,test_root/staticfiles,node_modules - -[isort] -indent=' ' -line_length=120 -multi_line_output=3 -skip= - envs - migrations - -[importlinter] -root_packages = - lms - cms - openedx - openedx_content -include_external_packages = True -contract_types = - # Our custom contract which checks that we're only importing from 'api.py' - # for participating packages. - isolated_apps: openedx.testing.importlinter.isolated_apps_contract.IsolatedAppsContract - -[importlinter:contract:1] -name = lms and cms are independent -type = independence -modules = - lms - cms -ignore_imports = - ############################################################################ - # lms side imports that we are ignoring for now - lms.djangoapps.course_home_api.outline.tests.test_view -> cms.djangoapps.contentstore.outlines - lms.djangoapps.course_home_api.tests.utils -> cms.djangoapps.contentstore.outlines - # lms.djangoapps.instructor.tests.test_api & lms.djangoapps.instructor.tests.test_tools - # -> openedx.core.djangoapps.course_date_signals.handlers - # -> cms.djangoapps.contentstore.config.waffle - openedx.core.djangoapps.course_date_signals.handlers -> cms.djangoapps.contentstore.config.waffle - ############################################################################ - # cms side imports that we are ignoring for now - cms.djangoapps.contentstore.views.tests.test_block -> lms.djangoapps.lms_xblock.mixin - cms.djangoapps.contentstore.signals.handlers -> lms.djangoapps.grades.api - cms.djangoapps.contentstore.course_group_config -> lms.lib.utils - cms.djangoapps.contentstore.views.preview -> lms.djangoapps.lms_xblock.field_data - # cms.envs.common - # -> openedx.envs.common - # -> lms.djangoapps.lms_xblock.mixin - openedx.envs.common -> lms.djangoapps.lms_xblock.mixin - # cms.djangoapps.contentstore.views.tests.test_group_configurations - # -> openedx.features.content_type_gating.helpers - # -> lms.djangoapps.courseware.masquerade - openedx.features.content_type_gating.helpers -> lms.djangoapps.courseware.masquerade - # cms.djangoapps.contentstore.utils - # -> openedx.core.djangoapps.django_comment_common.models - # -> openedx.core.djangoapps.course_groups.cohorts - # -> lms.djangoapps.courseware.courses - openedx.core.djangoapps.course_groups.cohorts -> lms.djangoapps.courseware.courses - # cms.djangoapps.contentstore.[various] - # -> openedx.features.content_type_gating.partitions - # -> lms.djangoapps.commerce.utils - openedx.features.content_type_gating.partitions -> lms.djangoapps.commerce.utils - # cms.djangoapps.contentstore.course_group_config - # -> openedx.core.djangoapps.course_groups.partition_scheme - # -> lms.djangoapps.courseware.masquerade - openedx.core.djangoapps.course_groups.partition_scheme -> lms.djangoapps.courseware.masquerade - # cms.djangoapps.export_course_metadata.tasks - # -> openedx.core.djangoapps.schedules.content_highlights - # -> lms.djangoapps.courseware.block_render & lms.djangoapps.courseware.model_data - openedx.core.djangoapps.content_libraries.* -> lms.djangoapps.*.* - # cms.djangoapps.contentstore.tasks -> openedx.core.djangoapps.content_libraries.[various] - # -> lms.djangoapps.grades.api - openedx.core.djangoapps.xblock.*.* -> lms.djangoapps.*.* - # cms.djangoapps.contentstore.tasks -> openedx.core.djangoapps.content_libraries.[various] -> openedx.core.djangoapps.xblock.[various] - # -> lms.djangoapps.courseware & lms.djangoapps.courseware.grades - openedx.core.djangoapps.schedules.content_highlights -> lms.djangoapps.courseware.* - # cms.djangoapps.contentstore.[various] - # -> openedx.core.lib.gating.api - # -> lms.djangoapps.course_blocks.api & lms.djangoapps.courseware.access & lms.djangoapps.grades.api - openedx.core.lib.gating.api -> lms.djangoapps.*.* - # cms.djangoapps.contentstore.[various] - # -> openedx.features.content_type_gating.partitions - # -> openedx.features.discounts.utils - # -> lms.djangoapps.courseware.utils & lms.djangoapps.experiments.models - openedx.features.discounts.utils -> lms.djangoapps.courseware.utils - openedx.features.discounts.utils -> lms.djangoapps.experiments.models - # cms.djangoapps.contentstore.signals.handlers - # -> openedx.core.djangoapps.discussions.tasks - # -> openedx.core.djangoapps.discussions.utils - # -> lms.djangoapps.courseware.access - openedx.core.djangoapps.discussions.utils -> lms.djangoapps.courseware.access - # cms.djangoapps.contentstore.[various] - # -> openedx.features.content_type_gating.partitions - # -> openedx.features.discounts.utils - # -> openedx.features.discounts.applicability - # -> lms.djangoapps.courseware.toggles - # & lms.djangoapps.courseware.utils - # & lms.djangoapps.experiments.models - # & lms.djangoapps.experiments.stable_bucketing - openedx.features.discounts.applicability -> lms.djangoapps.courseware.* - openedx.features.discounts.applicability -> lms.djangoapps.experiments.* - # cms.djangoapps.contentstore.[various] - # -> openedx.core.djangoapps.content.learning_sequences.api - # -> openedx.core.djangoapps.content.learning_sequences.api.outlines - # -> openedx.core.djangoapps.content.learning_sequences.api.permissions - # -> lms.djangoapps.courseware.access - openedx.core.djangoapps.content.learning_sequences.api.permissions -> lms.djangoapps.courseware.access - # cms.djangoapps.contentstore.[various] - # -> openedx.features.content_type_gating.partitions - # -> openedx.features.discounts.utils - # -> openedx.features.discounts.applicability - # -> openedx.features.enterprise_support.utils - openedx.features.enterprise_support.utils -> lms.djangoapps.branding.api - cms.djangoapps.contentstore.rest_api.v1.views.settings -> lms.djangoapps.certificates.api - # We are ignoring this existing import until we can refactor contenstore/helpers. - # https://github.com/openedx/edx-platform/issues/37637 - openedx.core.djangoapps.content_libraries.api.libraries -> cms.djangoapps.contentstore.helpers - openedx.core.djangoapps.content_libraries.api.blocks -> cms.djangoapps.contentstore.helpers - openedx.core.djangoapps.content_staging.serializers -> cms.djangoapps.contentstore.helpers - # These imports will become OK once we move content_libraries into CMS - # https://github.com/openedx/edx-platform/issues/33428 - openedx.core.djangoapps.content_libraries.permissions -> cms.djangoapps.course_creators.views - openedx.core.djangoapps.content_libraries.tasks -> cms.djangoapps.contentstore.storage - # Outstanding arch issue: course_overviews is tangled up with LMS - # https://github.com/openedx/edx-platform/issues/37658 - openedx.core.djangoapps.content.course_overviews.models -> lms.djangoapps.** - # Outstanding arch issue: content_highlights uses courseware block_render - # https://github.com/openedx/edx-platform/issues/37659 - openedx.core.djangoapps.schedules.content_highlights -> lms.djangoapps.courseware.block_render - -[importlinter:contract:2] -name = Do not depend on non-public API of isolated apps. -type = isolated_apps -isolated_apps = - cms.djangoapps.modulestore_migrator - openedx.core.djangoapps.agreements - openedx.core.djangoapps.bookmarks - openedx.core.djangoapps.content_libraries - openedx.core.djangoapps.content_staging - openedx.core.djangoapps.olx_rest_api - openedx.core.djangoapps.xblock - openedx.core.lib.xblock_serializer -allowed_modules = - # Only imports from api.py and data.py are allowed elsewhere in the code - # See https://open-edx-proposals.readthedocs.io/en/latest/best-practices/oep-0049-django-app-patterns.html#api-py - api - data - tests - -[importlinter:contract:3] -name = Do not directly import internals of openedx_content (only import from openedx_content.api). -type = forbidden -source_modules = - cms - lms - openedx - common - xmodule -forbidden_modules = - openedx_content.applets - openedx_content.backcompat -allow_indirect_imports = True - -[importlinter:contract:4] -name = Low-level apps should not depend on high-level apps -type = layers -layers = - # Layers from high-level to low-level. Imports should only occur from higher to lower. - cms.lib.xblock.upstream_sync | openedx.core.djangoapps.content.search | openedx.core.djangoapps.olx_rest_api - openedx.core.djangoapps.content_libraries - openedx.core.djangoapps.content_staging - openedx.core.djangoapps.xblock - openedx.core.lib.xblock_serializer - openedx.core.djangoapps.content_tagging -ignore_imports = - # Test code can break these layering rules - **.tests.** -> ** - - # FIXME: the exceptions below are from before we added this import linting rule. Should refactor to eliminate them. - # In particular, the contentstore.helpers module is too big and has too many imports - # See https://github.com/openedx/edx-platform/issues/37637 - - # The CSV export hard-codes support for courses and libraries. Refactor to do something like learning_context.get_children() - openedx.core.djangoapps.content_tagging.helpers.objecttag_export_helpers -> openedx.core.djangoapps.content_libraries.api - # The permissions checking code for tagging requires libraries model data to get all the orgs that a user is using: - openedx.core.djangoapps.content_tagging.utils -> openedx.core.djangoapps.content_libraries.api - # Content staging POST to clipboard API uses libraries APIs. We're working on moving this code to content_libraries - openedx.core.djangoapps.content_staging.views -> openedx.core.djangoapps.content_libraries.api - # content_staging.serializers imports contentstore.helpers which imports contentstore.utils which imports the libraries API. - openedx.core.djangoapps.content_staging.serializers -> cms.djangoapps.contentstore.helpers - # content_libraries.rest_api.libraries imports cms.djangoapps.contentstore.views.course which imports - # contentstore.toggles which imports djangoapps.content.search.api - openedx.core.djangoapps.content_libraries.rest_api.libraries -> cms.djangoapps.contentstore.views.course - # Content libraries imports contentstore.helpers which imports upstream_sync - openedx.core.djangoapps.content_libraries.api.blocks -> cms.djangoapps.contentstore.helpers - openedx.core.djangoapps.content_libraries.api.libraries -> cms.djangoapps.contentstore.helpers - # Outstanding arch issue: course_overviews is tangled up with LMS - # https://github.com/openedx/edx-platform/issues/37658 - openedx.core.djangoapps.content.course_overviews.models -> lms.djangoapps.** - # Outstanding arch issue: content_highlights uses courseware block_render - # https://github.com/openedx/edx-platform/issues/37659 - openedx.core.djangoapps.schedules.content_highlights -> lms.djangoapps.courseware.block_render - # This import happens only because grading signals are defined in LMS rather than openedx-events - # https://github.com/openedx/edx-platform/issues/37660 - openedx.core.djangoapps.xblock.runtime.runtime -> lms.djangoapps.grades.api - # These imports will become OK once we worked on the following issue: - # https://github.com/openedx/edx-platform/issues/33428 - openedx.core.djangoapps.video_config.services -> openedx.core.djangoapps.content_libraries.api