diff --git a/cms/pytest.ini b/cms/pytest.ini index ee9263d63c27..368ceb257099 100644 --- a/cms/pytest.ini +++ b/cms/pytest.ini @@ -1,6 +1,6 @@ [pytest] # Note: The first file of settings found is used, there is no combining, so -# this file is used for the tests in the cms tree, and setup.cfg is ignored. +# this file is used for the tests in the cms tree, and pyproject.toml is ignored. # Details at https://docs.pytest.org/en/latest/reference/customize.html DJANGO_SETTINGS_MODULE = cms.envs.test diff --git a/common/djangoapps/edxmako/README b/common/djangoapps/edxmako/README index 9896d78747c3..03674276986f 100644 --- a/common/djangoapps/edxmako/README +++ b/common/djangoapps/edxmako/README @@ -19,5 +19,5 @@ Mako: http://www.makotemplates.org/ How to install? ================================================================================ - $ sudo python setup.py install + $ pip install . diff --git a/common/test/pytest.ini b/common/test/pytest.ini index d93a7421722b..29e51b489f4a 100644 --- a/common/test/pytest.ini +++ b/common/test/pytest.ini @@ -1,6 +1,6 @@ [pytest] # Note: The first file of settings found is used, there is no combining, so -# this file is used for the tests in the common/test tree, and setup.cfg is ignored. +# this file is used for the tests in the common/test tree, and pyproject.toml is ignored. # Details at https://docs.pytest.org/en/latest/reference/customize.html addopts = -p no:randomly --durations=20 --json-report --json-report-omit keywords streams collectors log traceback tests --json-report-file=none diff --git a/docs/concepts/extension_points.rst b/docs/concepts/extension_points.rst index ac70edc43209..a64e2e58ff59 100644 --- a/docs/concepts/extension_points.rst +++ b/docs/concepts/extension_points.rst @@ -87,7 +87,7 @@ If you wish to customize aspects of the learner or educator experiences, you'll Most python plugins are enabled using one of two methods: -1. A Python Entry point: the core Open edX platform provides a standard plugin loading mechanism in |edx_django_utils.plugins|_ which uses `stevedore`_ to find all installed python packages that declare a specific "entry point" in their setup.py file. See the ``entry_points`` defined in edx-platform's own ``setup.py`` for examples. +1. A Python Entry point: the core Open edX platform provides a standard plugin loading mechanism in |edx_django_utils.plugins|_ which uses `stevedore`_ to find all installed python packages that declare a specific "entry point" in their package configuration (typically ``pyproject.toml`` or ``setup.py``). See the ``entry_points`` defined in edx-platform's own ``pyproject.toml`` for examples. 2. A Django setting: Some plugins require modification of Django settings, which is typically done by editing ``/edx/etc/lms.yml`` (in Production) or ``edx-platform/lms/envs/private.py`` (on Devstack). .. |edx_django_utils.plugins| replace:: ``edx_django_utils.plugins`` diff --git a/lms/djangoapps/course_blocks/transformers/access_denied_filter.py b/lms/djangoapps/course_blocks/transformers/access_denied_filter.py index b4115dd755bb..8b6a531d5162 100644 --- a/lms/djangoapps/course_blocks/transformers/access_denied_filter.py +++ b/lms/djangoapps/course_blocks/transformers/access_denied_filter.py @@ -18,8 +18,8 @@ class AccessDeniedMessageFilterTransformer(BlockStructureTransformer): @classmethod def name(cls): """ - Unique identifier for the transformer's class; - same identifier used in setup.py. + Unique identifier for the transformer's class. + This must match the entry point name in the package configuration. """ return "access_denied_message_filter" diff --git a/lms/djangoapps/course_blocks/transformers/hidden_content.py b/lms/djangoapps/course_blocks/transformers/hidden_content.py index e82d8d3441d6..80e602e6f29d 100644 --- a/lms/djangoapps/course_blocks/transformers/hidden_content.py +++ b/lms/djangoapps/course_blocks/transformers/hidden_content.py @@ -39,8 +39,8 @@ class HiddenContentTransformer(BlockStructureTransformer): @classmethod def name(cls): """ - Unique identifier for the transformer's class; - same identifier used in setup.py. + Unique identifier for the transformer's class. + This must match the entry point name in the package configuration. """ return "hidden_content" diff --git a/lms/djangoapps/course_blocks/transformers/library_content.py b/lms/djangoapps/course_blocks/transformers/library_content.py index 10ef8c2138b6..e7f2258483bc 100644 --- a/lms/djangoapps/course_blocks/transformers/library_content.py +++ b/lms/djangoapps/course_blocks/transformers/library_content.py @@ -36,8 +36,8 @@ class ContentLibraryTransformer(FilteringTransformerMixin, BlockStructureTransfo @classmethod def name(cls): """ - Unique identifier for the transformer's class; - same identifier used in setup.py. + Unique identifier for the transformer's class. + This must match the entry point name in the package configuration. """ return "library_content" @@ -197,8 +197,8 @@ class ContentLibraryOrderTransformer(BlockStructureTransformer): @classmethod def name(cls): """ - Unique identifier for the transformer's class; - same identifier used in setup.py + Unique identifier for the transformer's class. + This must match the entry point name in the package configuration. """ return "library_content_randomize" diff --git a/lms/djangoapps/course_blocks/transformers/load_override_data.py b/lms/djangoapps/course_blocks/transformers/load_override_data.py index 672922ea510d..7f57768b5069 100644 --- a/lms/djangoapps/course_blocks/transformers/load_override_data.py +++ b/lms/djangoapps/course_blocks/transformers/load_override_data.py @@ -67,8 +67,8 @@ def __init__(self, user): @classmethod def name(cls): """ - Unique identifier for the transformer's class; - same identifier used in setup.py. + Unique identifier for the transformer's class. + This must match the entry point name in the package configuration. """ return "load_override_data" diff --git a/lms/djangoapps/course_blocks/transformers/split_test.py b/lms/djangoapps/course_blocks/transformers/split_test.py index 4de70d8badff..45fdaa09813d 100644 --- a/lms/djangoapps/course_blocks/transformers/split_test.py +++ b/lms/djangoapps/course_blocks/transformers/split_test.py @@ -30,8 +30,8 @@ class SplitTestTransformer(FilteringTransformerMixin, BlockStructureTransformer) @classmethod def name(cls): """ - Unique identifier for the transformer's class; - same identifier used in setup.py. + Unique identifier for the transformer's class. + This must match the entry point name in the package configuration. """ return "split_test" diff --git a/lms/djangoapps/course_blocks/transformers/start_date.py b/lms/djangoapps/course_blocks/transformers/start_date.py index 13ba3b7470c2..0d7165034efe 100644 --- a/lms/djangoapps/course_blocks/transformers/start_date.py +++ b/lms/djangoapps/course_blocks/transformers/start_date.py @@ -39,8 +39,8 @@ class StartDateTransformer(FilteringTransformerMixin, BlockStructureTransformer) @classmethod def name(cls): """ - Unique identifier for the transformer's class; - same identifier used in setup.py. + Unique identifier for the transformer's class. + This must match the entry point name in the package configuration. """ return "start_date" diff --git a/lms/djangoapps/course_blocks/transformers/user_partitions.py b/lms/djangoapps/course_blocks/transformers/user_partitions.py index 087c6e5fc7e7..54424eb06fbd 100644 --- a/lms/djangoapps/course_blocks/transformers/user_partitions.py +++ b/lms/djangoapps/course_blocks/transformers/user_partitions.py @@ -32,8 +32,8 @@ class UserPartitionTransformer(BlockStructureTransformer): @classmethod def name(cls): """ - Unique identifier for the transformer's class; - same identifier used in setup.py. + Unique identifier for the transformer's class. + This must match the entry point name in the package configuration. """ return "user_partitions" diff --git a/lms/djangoapps/course_blocks/transformers/visibility.py b/lms/djangoapps/course_blocks/transformers/visibility.py index 19b0d2252d80..f7dd0da5f0af 100644 --- a/lms/djangoapps/course_blocks/transformers/visibility.py +++ b/lms/djangoapps/course_blocks/transformers/visibility.py @@ -32,8 +32,8 @@ class VisibilityTransformer(FilteringTransformerMixin, BlockStructureTransformer @classmethod def name(cls): """ - Unique identifier for the transformer's class; - same identifier used in setup.py. + Unique identifier for the transformer's class. + This must match the entry point name in the package configuration. """ return "visibility" diff --git a/lms/djangoapps/courseware/transformers.py b/lms/djangoapps/courseware/transformers.py index 2577a9c42331..f2bba80c2ba1 100644 --- a/lms/djangoapps/courseware/transformers.py +++ b/lms/djangoapps/courseware/transformers.py @@ -18,8 +18,8 @@ class OpenAssessmentDateTransformer(FilteringTransformerMixin, BlockStructureTra @classmethod def name(cls): """ - Unique identifier for the transformer's class; - same identifier used in setup.py. + Unique identifier for the transformer's class. + This must match the entry point name in the package configuration. """ return 'open_assessment_transformer' diff --git a/lms/djangoapps/grades/transformer.py b/lms/djangoapps/grades/transformer.py index 38fe903ba7d9..f322ea0162e5 100644 --- a/lms/djangoapps/grades/transformer.py +++ b/lms/djangoapps/grades/transformer.py @@ -55,8 +55,8 @@ class GradesTransformer(BlockStructureTransformer): @classmethod def name(cls): """ - Unique identifier for the transformer's class; - same identifier used in setup.py. + Unique identifier for the transformer's class. + This must match the entry point name in the package configuration. """ return 'grades' diff --git a/openedx/core/djangoapps/content/block_structure/__init__.py b/openedx/core/djangoapps/content/block_structure/__init__.py index 00ed1b12d2ef..cf345b73cf51 100644 --- a/openedx/core/djangoapps/content/block_structure/__init__.py +++ b/openedx/core/djangoapps/content/block_structure/__init__.py @@ -49,7 +49,7 @@ Registry. Transformers are registered using the platform's PluginManager (e.g., Stevedore). This is currently done by updating -setup.py. Only registered transformers are called during the Collect +pyproject.toml. Only registered transformers are called during the Collect Phase. And only registered transformers can be used during the Transform phase. Exceptions to this rule are any nested transformers that are contained within higher-order transformers - as long as the diff --git a/openedx/core/djangoapps/content/block_structure/transformer.py b/openedx/core/djangoapps/content/block_structure/transformer.py index 1bcde62e0650..b2ac620dc9a1 100644 --- a/openedx/core/djangoapps/content/block_structure/transformer.py +++ b/openedx/core/djangoapps/content/block_structure/transformer.py @@ -65,7 +65,7 @@ def name(cls): identify the transformer's cached data. So it should be unique and not conflict with other transformers. Consider using the same name that is used in the Transformer Registry. For example, - for Stevedore, it is specified in the setup.py file. + for Stevedore, it is specified in the package configuration (pyproject.toml). Once the transformer is in use and its data is cached, do not modify this name value without consideration of backward diff --git a/openedx/core/djangoapps/course_apps/docs/decisions/001-course-apps.rst b/openedx/core/djangoapps/course_apps/docs/decisions/001-course-apps.rst index 4491779a2751..cccd0eba8776 100644 --- a/openedx/core/djangoapps/course_apps/docs/decisions/001-course-apps.rst +++ b/openedx/core/djangoapps/course_apps/docs/decisions/001-course-apps.rst @@ -105,14 +105,14 @@ check. Course App Plugin Class ======================= -To be loaded as a Course App, you need to provide an entrypoint in ``setup.py`` +To be loaded as a Course App, you need to provide an entrypoint in ``pyproject.toml`` with the namespace ``openedx.course_app``. The entry should point to a Python class with the following basic structure: .. code-block:: python class CourseApp: - # The app id should match what is specified in the setup.py entrypoint + # The app id should match what is specified in the pyproject.toml entrypoint app_id: str = 'wiki' name: str = 'Wiki' description: str = 'A short description of what the Wiki does.' diff --git a/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py b/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py index 73f824d9fab5..1b6a4bdb18ae 100644 --- a/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py +++ b/openedx/core/djangoapps/course_groups/tests/test_partition_scheme.py @@ -254,7 +254,7 @@ def test_missing_partition(self): class TestExtension(django.test.TestCase): """ Ensure that the scheme extension is correctly plugged in (via entry point - in setup.py) + in pyproject.toml) """ def test_get_scheme(self): diff --git a/openedx/core/djangoapps/course_live/docs/decisions/001-course-live.rst b/openedx/core/djangoapps/course_live/docs/decisions/001-course-live.rst index 27ee3b488482..9fbed126c654 100644 --- a/openedx/core/djangoapps/course_live/docs/decisions/001-course-live.rst +++ b/openedx/core/djangoapps/course_live/docs/decisions/001-course-live.rst @@ -29,10 +29,10 @@ Decision We proposed to add the course live as a plugin with the following structure Course Live App Plugin Class ------------------------ +---------------------------- -The app will be loaded as a plugin and added to `setup.py` with the namespace -"openedx.course_app". +The app will be loaded as a plugin and added to ``pyproject.toml`` with the namespace +``openedx.course_app``. .. code-block :: python diff --git a/openedx/core/djangoapps/discussions/transformers.py b/openedx/core/djangoapps/discussions/transformers.py index 8fcf78bc1f98..a4d34434ab12 100644 --- a/openedx/core/djangoapps/discussions/transformers.py +++ b/openedx/core/djangoapps/discussions/transformers.py @@ -19,8 +19,8 @@ class DiscussionsTopicLinkTransformer(BlockStructureTransformer): @classmethod def name(cls): """ - Unique identifier for the transformer's class; - same identifier used in setup.py. + Unique identifier for the transformer's class. + This must match the entry point name in the package configuration. """ return "discussions_link" diff --git a/openedx/core/djangoapps/user_api/tests/test_partition_schemes.py b/openedx/core/djangoapps/user_api/tests/test_partition_schemes.py index b1fc0e6e577f..afa6ab7939db 100644 --- a/openedx/core/djangoapps/user_api/tests/test_partition_schemes.py +++ b/openedx/core/djangoapps/user_api/tests/test_partition_schemes.py @@ -141,7 +141,7 @@ def test_change_group_name(self): class TestExtension(TestCase): """ Ensure that the scheme extension is correctly plugged in (via entry point - in setup.py) + in pyproject.toml) """ def test_get_scheme(self): diff --git a/openedx/core/djangoapps/verified_track_content/tests/test_partition_scheme.py b/openedx/core/djangoapps/verified_track_content/tests/test_partition_scheme.py index f7de6042ef19..b30eea70d439 100644 --- a/openedx/core/djangoapps/verified_track_content/tests/test_partition_scheme.py +++ b/openedx/core/djangoapps/verified_track_content/tests/test_partition_scheme.py @@ -94,7 +94,7 @@ def setUpClass(cls): def test_get_scheme(self): """ - Ensure that the scheme extension is correctly plugged in (via entry point in setup.py) + Ensure that the scheme extension is correctly plugged in (via entry point in pyproject.toml) """ assert UserPartition.get_scheme('enrollment_track') == EnrollmentTrackPartitionScheme diff --git a/openedx/core/lib/xblock_pipeline/finder.py b/openedx/core/lib/xblock_pipeline/finder.py index a87b564afce1..6c6791f708d4 100644 --- a/openedx/core/lib/xblock_pipeline/finder.py +++ b/openedx/core/lib/xblock_pipeline/finder.py @@ -123,7 +123,7 @@ def __init__(self, *args, **kwargs): # xblock_resource_info holds (package_name, resources_dir) tuples. While # it never happens in practice, the XBlock API does allow different - # XBlocks installed with the same setup.py to refer to their shared + # XBlocks installed from the same package to refer to their shared # static assets using different prefixes. xblock_resource_info = { (xblock_resource_pkg(xblock_class), xblock_class.get_resources_dir()) diff --git a/openedx/features/content_type_gating/block_transformers.py b/openedx/features/content_type_gating/block_transformers.py index 94b66eda4367..b374e3ff5174 100644 --- a/openedx/features/content_type_gating/block_transformers.py +++ b/openedx/features/content_type_gating/block_transformers.py @@ -25,8 +25,8 @@ class ContentTypeGateTransformer(BlockStructureTransformer): @classmethod def name(cls): """ - Unique identifier for the transformer's class; - same identifier used in setup.py. + Unique identifier for the transformer's class. + This must match the entry point name in the package configuration. """ return "content_type_gate" diff --git a/openedx/features/effort_estimation/block_transformers.py b/openedx/features/effort_estimation/block_transformers.py index d315aefd065c..c3e6bce1f80e 100644 --- a/openedx/features/effort_estimation/block_transformers.py +++ b/openedx/features/effort_estimation/block_transformers.py @@ -53,7 +53,10 @@ class MissingEstimationData(Exception): @classmethod def name(cls): - """Unique identifier for the transformer's class; same identifier used in setup.py.""" + """ + Unique identifier for the transformer's class. + This must match the entry point name in the package configuration. + """ return 'effort_estimation' @classmethod diff --git a/openedx/tests/xblock_integration/test_external_xblocks.py b/openedx/tests/xblock_integration/test_external_xblocks.py index 01bdf2133cce..dbeba088fa47 100644 --- a/openedx/tests/xblock_integration/test_external_xblocks.py +++ b/openedx/tests/xblock_integration/test_external_xblocks.py @@ -29,9 +29,9 @@ class InvalidTestName(Exception): ''' This means you have an entry point for a test that does not correspond to a properly named test class. For example, if you cut-and-paste entry - points in `setup.py`, and forgot to repoint the class (so it points to - `DoneXBlock` instead of `TestDone`), or otherwise made an error, you - will see this exception. + points in your package configuration, and forgot to repoint the class + (so it points to `DoneXBlock` instead of `TestDone`), or otherwise made + an error, you will see this exception. ''' pass # lint-amnesty, pylint: disable=unnecessary-pass diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000000..ad14aaf08b7a --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,397 @@ +[build-system] +requires = ["setuptools>=61.0"] +build-backend = "setuptools.build_meta" + +[project] +name = "openedx-platform" +version = "0.13" +requires-python = ">=3.11" +dependencies = ["setuptools"] + +[tool.setuptools] +packages = ["cms", "common", "lms", "openedx", "xmodule"] + +[tool.setuptools.package-data] +xmodule = ["js/module/*"] + +[project.entry-points."xblock.v1"] +about = "xmodule.html_block:AboutBlock" +book = "xmodule.template_block:TranslateCustomTagBlock" +annotatable = "xmodule.annotatable_block:AnnotatableBlock" +chapter = "xmodule.seq_block:SectionBlock" +conditional = "xmodule.conditional_block:ConditionalBlock" +course = "xmodule.course_block:CourseBlock" +course_info = "xmodule.html_block:CourseInfoBlock" +customtag = "xmodule.template_block:CustomTagBlock" +custom_tag_template = "xmodule.template_block:CustomTagTemplateBlock" +discuss = "xmodule.template_block:TranslateCustomTagBlock" +discussion = "xmodule.discussion_block:DiscussionXBlock" +error = "xmodule.error_block:ErrorBlock" +hidden = "xmodule.hidden_block:HiddenBlock" +html = "xmodule.html_block:HtmlBlock" +itembank = "xmodule.item_bank_block:ItemBankBlock" +image = "xmodule.template_block:TranslateCustomTagBlock" +library = "xmodule.library_root_xblock:LibraryRoot" +library_content = "xmodule.library_content_block:LegacyLibraryContentBlock" +lti = "xmodule.lti_block:LTIBlock" +poll_question = "xmodule.poll_block:PollBlock" +problem = "xmodule.capa_block:ProblemBlock" +randomize = "xmodule.randomize_block:RandomizeBlock" +sequential = "xmodule.seq_block:SequenceBlock" +slides = "xmodule.template_block:TranslateCustomTagBlock" +split_test = "xmodule.split_test_block:SplitTestBlock" +static_tab = "xmodule.html_block:StaticTabBlock" +unit = "xmodule.unit_block:UnitBlock" +vertical = "xmodule.vertical_block:VerticalBlock" +video = "xmodule.video_block:VideoBlock" +videoalpha = "xmodule.video_block:VideoBlock" +videodev = "xmodule.template_block:TranslateCustomTagBlock" +word_cloud = "xmodule.word_cloud_block:WordCloudBlock" +wrapper = "xmodule.wrapper_block:WrapperBlock" + +[project.entry-points."xblock_asides.v1"] +tagging_aside = "cms.lib.xblock.tagging:StructuredTagsAside" + +[project.entry-points."openedx.course_tab"] +ccx = "lms.djangoapps.ccx.plugins:CcxCourseTab" +courseware = "lms.djangoapps.courseware.tabs:CoursewareTab" +dates = "lms.djangoapps.courseware.tabs:DatesTab" +discussion = "lms.djangoapps.discussion.plugins:DiscussionTab" +edxnotes = "lms.djangoapps.edxnotes.plugins:EdxNotesTab" +external_discussion = "lms.djangoapps.courseware.tabs:ExternalDiscussionCourseTab" +external_link = "lms.djangoapps.courseware.tabs:ExternalLinkCourseTab" +html_textbooks = "lms.djangoapps.courseware.tabs:HtmlTextbookTabs" +instructor = "lms.djangoapps.instructor.views.instructor_dashboard:InstructorDashboardTab" +lti_discussion = "openedx.features.lti_course_tab.tab:DiscussionLtiCourseTab" +lti_live = "openedx.core.djangoapps.course_live.tab:CourseLiveTab" +lti_tab = "openedx.features.lti_course_tab.tab:LtiCourseTab" +pdf_textbooks = "lms.djangoapps.courseware.tabs:PDFTextbookTabs" +progress = "lms.djangoapps.courseware.tabs:ProgressTab" +static_tab = "xmodule.tabs:StaticTab" +syllabus = "lms.djangoapps.courseware.tabs:SyllabusTab" +teams = "lms.djangoapps.teams.plugins:TeamsTab" +textbooks = "lms.djangoapps.courseware.tabs:TextbookTabs" +wiki = "lms.djangoapps.course_wiki.tab:WikiTab" + +[project.entry-points."openedx.course_app"] +calculator = "lms.djangoapps.courseware.plugins:CalculatorCourseApp" +custom_pages = "lms.djangoapps.courseware.plugins:CustomPagesCourseApp" +discussion = "openedx.core.djangoapps.discussions.plugins:DiscussionCourseApp" +edxnotes = "lms.djangoapps.edxnotes.plugins:EdxNotesCourseApp" +live = "openedx.core.djangoapps.course_live.plugins:LiveCourseApp" +ora_settings = "lms.djangoapps.courseware.plugins:ORASettingsApp" +proctoring = "lms.djangoapps.courseware.plugins:ProctoringCourseApp" +progress = "lms.djangoapps.courseware.plugins:ProgressCourseApp" +teams = "lms.djangoapps.teams.plugins:TeamsCourseApp" +textbooks = "lms.djangoapps.courseware.plugins:TextbooksCourseApp" +wiki = "lms.djangoapps.course_wiki.plugins.course_app:WikiCourseApp" + +[project.entry-points."openedx.course_tool"] +calendar_sync_toggle = "openedx.features.calendar_sync.plugins:CalendarSyncToggleTool" +course_bookmarks = "openedx.features.course_bookmarks.plugins:CourseBookmarksTool" +course_updates = "openedx.features.course_experience.plugins:CourseUpdatesTool" +financial_assistance = "lms.djangoapps.courseware.course_tools:FinancialAssistanceTool" + +[project.entry-points."lms.djangoapp"] +ace_common = "openedx.core.djangoapps.ace_common.apps:AceCommonConfig" +content_libraries = "openedx.core.djangoapps.content_libraries.apps:ContentLibrariesConfig" +course_apps = "openedx.core.djangoapps.course_apps.apps:CourseAppsConfig" +course_live = "openedx.core.djangoapps.course_live.apps:CourseLiveConfig" +courseware_api = "openedx.core.djangoapps.courseware_api.apps:CoursewareAPIConfig" +credentials = "openedx.core.djangoapps.credentials.apps:CredentialsConfig" +discussion = "lms.djangoapps.discussion.apps:DiscussionConfig" +discussions = "openedx.core.djangoapps.discussions.apps:DiscussionsConfig" +grades = "lms.djangoapps.grades.apps:GradesConfig" +plugins = "openedx.core.djangoapps.plugins.apps:PluginsConfig" +theming = "openedx.core.djangoapps.theming.apps:ThemingConfig" +bookmarks = "openedx.core.djangoapps.bookmarks.apps:BookmarksConfig" +zendesk_proxy = "openedx.core.djangoapps.zendesk_proxy.apps:ZendeskProxyConfig" +instructor = "lms.djangoapps.instructor.apps:InstructorConfig" +password_policy = "openedx.core.djangoapps.password_policy.apps:PasswordPolicyConfig" +user_authn = "openedx.core.djangoapps.user_authn.apps:UserAuthnConfig" +program_enrollments = "lms.djangoapps.program_enrollments.apps:ProgramEnrollmentsConfig" + +[project.entry-points."cms.djangoapp"] +ace_common = "openedx.core.djangoapps.ace_common.apps:AceCommonConfig" +bookmarks = "openedx.core.djangoapps.bookmarks.apps:BookmarksConfig" +course_live = "openedx.core.djangoapps.course_live.apps:CourseLiveConfig" +content_libraries = "openedx.core.djangoapps.content_libraries.apps:ContentLibrariesConfig" +content_staging = "openedx.core.djangoapps.content_staging.apps:ContentStagingAppConfig" +course_apps = "openedx.core.djangoapps.course_apps.apps:CourseAppsConfig" +# Importing an LMS app into the Studio process is not a good practice. +# We're ignoring this for Discussions here because its placement in LMS +# is a historical artifact. The eventual goal is to consolidate the multiple +# discussions-related Django apps and either put them in the openedx/ dir, +# or in another repo entirely. +discussion = "lms.djangoapps.discussion.apps:DiscussionConfig" +discussions = "openedx.core.djangoapps.discussions.apps:DiscussionsConfig" +instructor = "lms.djangoapps.instructor.apps:InstructorConfig" +olx_rest_api = "openedx.core.djangoapps.olx_rest_api.apps:OlxRestApiAppConfig" +password_policy = "openedx.core.djangoapps.password_policy.apps:PasswordPolicyConfig" +plugins = "openedx.core.djangoapps.plugins.apps:PluginsConfig" +theming = "openedx.core.djangoapps.theming.apps:ThemingConfig" +user_authn = "openedx.core.djangoapps.user_authn.apps:UserAuthnConfig" +zendesk_proxy = "openedx.core.djangoapps.zendesk_proxy.apps:ZendeskProxyConfig" + +[project.entry-points."openedx.block_structure_transformer"] +library_content = "lms.djangoapps.course_blocks.transformers.library_content:ContentLibraryTransformer" +library_content_randomize = "lms.djangoapps.course_blocks.transformers.library_content:ContentLibraryOrderTransformer" +split_test = "lms.djangoapps.course_blocks.transformers.split_test:SplitTestTransformer" +start_date = "lms.djangoapps.course_blocks.transformers.start_date:StartDateTransformer" +user_partitions = "lms.djangoapps.course_blocks.transformers.user_partitions:UserPartitionTransformer" +visibility = "lms.djangoapps.course_blocks.transformers.visibility:VisibilityTransformer" +hidden_content = "lms.djangoapps.course_blocks.transformers.hidden_content:HiddenContentTransformer" +course_blocks_api = "lms.djangoapps.course_api.blocks.transformers.blocks_api:BlocksAPITransformer" +milestones = "lms.djangoapps.course_api.blocks.transformers.milestones:MilestonesAndSpecialExamsTransformer" +grades = "lms.djangoapps.grades.transformer:GradesTransformer" +completion = "lms.djangoapps.course_api.blocks.transformers.block_completion:BlockCompletionTransformer" +load_override_data = "lms.djangoapps.course_blocks.transformers.load_override_data:OverrideDataTransformer" +content_type_gate = "openedx.features.content_type_gating.block_transformers:ContentTypeGateTransformer" +access_denied_message_filter = "lms.djangoapps.course_blocks.transformers.access_denied_filter:AccessDeniedMessageFilterTransformer" +open_assessment_transformer = "lms.djangoapps.courseware.transformers:OpenAssessmentDateTransformer" +effort_estimation = "openedx.features.effort_estimation.api:EffortEstimationTransformer" +discussions_link = "openedx.core.djangoapps.discussions.transformers:DiscussionsTopicLinkTransformer" + +[project.entry-points."openedx.user_partition_scheme"] +cohort = "openedx.core.djangoapps.course_groups.partition_scheme:CohortPartitionScheme" +content_type_gate = "openedx.features.content_type_gating.partitions:ContentTypeGatingPartitionScheme" +enrollment_track = "openedx.core.djangoapps.verified_track_content.partition_scheme:EnrollmentTrackPartitionScheme" +random = "openedx.core.djangoapps.user_api.partition_schemes:RandomUserPartitionScheme" +team = "lms.djangoapps.teams.team_partition_scheme:TeamPartitionScheme" +verification = "openedx.core.djangoapps.user_api.partition_schemes:ReturnGroup1PartitionScheme" + +[project.entry-points."openedx.ace.policy"] +bulk_email_optout = "lms.djangoapps.bulk_email.policies:CourseEmailOptout" +course_push_notification_optout = "openedx.core.djangoapps.notifications.policies:CoursePushNotificationOptout" +disabled_user_optout = "openedx.core.djangoapps.ace_common.policies:DisableUserOptout" + +[project.entry-points."openedx.call_to_action"] +personalized_learner_schedules = "openedx.features.personalized_learner_schedules.call_to_action:PersonalizedLearnerScheduleCallToAction" + +[project.entry-points."openedx.learning_context"] +lib = "openedx.core.djangoapps.content_libraries.library_context:LibraryContextImpl" + +[project.entry-points."openedx.dynamic_partition_generator"] +content_type_gating = "openedx.features.content_type_gating.partitions:create_content_gating_partition" +enrollment_track = "xmodule.partitions.enrollment_track_partition_generator:create_enrollment_track_partition" +team = "openedx.core.lib.teams_config:create_team_set_partition" + +[project.entry-points.console_scripts] +xmodule_assets = "xmodule.static_content:main" + +[tool.pytest.ini_options] +# Note: The first file of settings found is used, there is no combining, so +# this file is only used for tests that don't find a pytest.ini file first. +# Details at https://docs.pytest.org/en/latest/reference/customize.html +DJANGO_SETTINGS_MODULE = "lms.envs.test" +addopts = "--nomigrations --reuse-db --durations=20 --json-report --json-report-omit keywords streams collectors log traceback tests --json-report-file=none" +# Enable default handling for all warnings, including those that are ignored by default; +# but hide rate-limit warnings (because we deliberately don't throttle test user logins) +# and field_data deprecation warnings (because fixing them requires a major low-priority refactoring) +filterwarnings = [ + "default", + "ignore:No request passed to the backend, unable to rate-limit:UserWarning", + "ignore::xblock.exceptions.FieldDataDeprecationWarning", + # Remove default_app_config warning after updating Django to 4.2 + "ignore:.*You can remove default_app_config.*:PendingDeprecationWarning", + "ignore:Instead access HTTPResponse.headers directly.*:DeprecationWarning:elasticsearch", + # ABC deprecation Warning comes from libsass + "ignore:Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated.*:DeprecationWarning:sass", + "ignore:'etree' is deprecated. Use 'xml.etree.ElementTree' instead.:DeprecationWarning:wiki", +] +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_learning"] +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 import apps from openedx-learning (only import from openedx_learning.api.* and openedx_learning.lib.*)." +type = "forbidden" +source_modules = ["cms", "lms", "openedx"] +forbidden_modules = ["openedx_learning.apps"] +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/requirements/edx/github.in b/requirements/edx/github.in index 3c01759768c9..7fdb2c051ce8 100644 --- a/requirements/edx/github.in +++ b/requirements/edx/github.in @@ -57,19 +57,21 @@ # # * DIST-NAME is the distribution name, the same name you'd use in a # "pip install" command. It might be different than REPO-NAME. It must -# be the same as the `name="DIST-NAME"` value in the repo's setup.py. +# be the same as the package name defined in the repo's pyproject.toml +# (or setup.py for older packages). # # * VERSION might not be the same as TAG-OR-SHA, but if the tag names the # version, please make it match the VERSION, but with a "v" prefix. -# VERSION must be the same as the `version="VERSION"` value in the repo's -# setup.py. An alternative is to use 0.0 as VERSION: this forces pip to -# re-install the package each time, and can be useful when working with two -# repos before picking a version number. Don't use 0.0 on master, only for -# tight-loop work in progress. +# VERSION must be the same as the version defined in the repo's pyproject.toml +# (or setup.py for older packages). An alternative is to use 0.0 as VERSION: +# this forces pip to re-install the package each time, and can be useful when +# working with two repos before picking a version number. Don't use 0.0 on +# master, only for tight-loop work in progress. # # * Don't prefix the URL with "-e". That would install the package in "editable" -# mode A.K.A "development" mode, which takes longer and does not -# fully respect setup.py, making the transition back to PyPI more complex. +# mode A.K.A "development" mode, which takes longer and does not fully respect +# the package's build configuration, making the transition back to PyPI more +# complex. # # * Organize the URL into one of the two categories below: diff --git a/setup.cfg b/setup.cfg index ac0907b667c3..7e1ab370a043 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,29 +1,3 @@ -[tool:pytest] -# Note: The first file of settings found is used, there is no combining, so -# this file is only used for tests that don't find a pytest.ini file first. -# Details at https://docs.pytest.org/en/latest/reference/customize.html - -DJANGO_SETTINGS_MODULE = lms.envs.test -addopts = --nomigrations --reuse-db --durations=20 --json-report --json-report-omit keywords streams collectors log traceback tests --json-report-file=none -# Enable default handling for all warnings, including those that are ignored by default; -# but hide rate-limit warnings (because we deliberately don't throttle test user logins) -# and field_data deprecation warnings (because fixing them requires a major low-priority refactoring) -filterwarnings = - default - ignore:No request passed to the backend, unable to rate-limit:UserWarning - ignore::xblock.exceptions.FieldDataDeprecationWarning - # Remove default_app_config warning after updating Django to 4.2 - ignore:.*You can remove default_app_config.*:PendingDeprecationWarning - ignore:Instead access HTTPResponse.headers directly.*:DeprecationWarning:elasticsearch - # ABC deprecation Warning comes from libsass - ignore:Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated.*:DeprecationWarning:sass - ignore:'etree' is deprecated. Use 'xml.etree.ElementTree' instead.:DeprecationWarning:wiki - -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 - [pycodestyle] # error codes: https://pycodestyle.readthedocs.io/en/latest/intro.html#error-codes # E501: line too long @@ -46,205 +20,3 @@ python_files = tests.py test_*.py tests_*.py *_tests.py __init__.py # 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_learning -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 import apps from openedx-learning (only import from openedx_learning.api.* and openedx_learning.lib.*). -type = forbidden -source_modules = - cms - lms - openedx -forbidden_modules = - openedx_learning.apps -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 diff --git a/setup.py b/setup.py deleted file mode 100644 index eeb7b79f534d..000000000000 --- a/setup.py +++ /dev/null @@ -1,195 +0,0 @@ -""" # lint-amnesty, pylint: disable=django-not-configured -Setup script for the Open edX package. -""" - -from setuptools import setup - -XBLOCKS = [ - "about = xmodule.html_block:AboutBlock", - "book = xmodule.template_block:TranslateCustomTagBlock", - "annotatable = xmodule.annotatable_block:AnnotatableBlock", - "chapter = xmodule.seq_block:SectionBlock", - "conditional = xmodule.conditional_block:ConditionalBlock", - "course = xmodule.course_block:CourseBlock", - "course_info = xmodule.html_block:CourseInfoBlock", - "customtag = xmodule.template_block:CustomTagBlock", - "custom_tag_template = xmodule.template_block:CustomTagTemplateBlock", - "discuss = xmodule.template_block:TranslateCustomTagBlock", - "discussion = xmodule.discussion_block:DiscussionXBlock", - "error = xmodule.error_block:ErrorBlock", - "hidden = xmodule.hidden_block:HiddenBlock", - "html = xmodule.html_block:HtmlBlock", - "itembank = xmodule.item_bank_block:ItemBankBlock", - "image = xmodule.template_block:TranslateCustomTagBlock", - "library = xmodule.library_root_xblock:LibraryRoot", - "library_content = xmodule.library_content_block:LegacyLibraryContentBlock", - "lti = xmodule.lti_block:LTIBlock", - "poll_question = xmodule.poll_block:PollBlock", - "problem = xmodule.capa_block:ProblemBlock", - "randomize = xmodule.randomize_block:RandomizeBlock", - "sequential = xmodule.seq_block:SequenceBlock", - "slides = xmodule.template_block:TranslateCustomTagBlock", - "split_test = xmodule.split_test_block:SplitTestBlock", - "static_tab = xmodule.html_block:StaticTabBlock", - "unit = xmodule.unit_block:UnitBlock", - "vertical = xmodule.vertical_block:VerticalBlock", - "video = xmodule.video_block:VideoBlock", - "videoalpha = xmodule.video_block:VideoBlock", - "videodev = xmodule.template_block:TranslateCustomTagBlock", - "word_cloud = xmodule.word_cloud_block:WordCloudBlock", - "wrapper = xmodule.wrapper_block:WrapperBlock", -] -XBLOCKS_ASIDES = [ - 'tagging_aside = cms.lib.xblock.tagging:StructuredTagsAside', -] - - -setup( - name="Open edX", - version='0.13', - install_requires=["setuptools"], - requires=[], - # NOTE: These are not the names we should be installing. This tree should - # be reorganized to be a more conventional Python tree. - packages=[ - "cms", - "common", - "lms", - "openedx", - "xmodule", - ], - package_data={ - 'xmodule': ['js/module/*'], - }, - entry_points={ - "openedx.course_tab": [ - "ccx = lms.djangoapps.ccx.plugins:CcxCourseTab", - "courseware = lms.djangoapps.courseware.tabs:CoursewareTab", - "dates = lms.djangoapps.courseware.tabs:DatesTab", - "discussion = lms.djangoapps.discussion.plugins:DiscussionTab", - "edxnotes = lms.djangoapps.edxnotes.plugins:EdxNotesTab", - "external_discussion = lms.djangoapps.courseware.tabs:ExternalDiscussionCourseTab", - "external_link = lms.djangoapps.courseware.tabs:ExternalLinkCourseTab", - "html_textbooks = lms.djangoapps.courseware.tabs:HtmlTextbookTabs", - "instructor = lms.djangoapps.instructor.views.instructor_dashboard:InstructorDashboardTab", - "lti_discussion = openedx.features.lti_course_tab.tab:DiscussionLtiCourseTab", - "lti_live = openedx.core.djangoapps.course_live.tab:CourseLiveTab", - "lti_tab = openedx.features.lti_course_tab.tab:LtiCourseTab", - "pdf_textbooks = lms.djangoapps.courseware.tabs:PDFTextbookTabs", - "progress = lms.djangoapps.courseware.tabs:ProgressTab", - "static_tab = xmodule.tabs:StaticTab", - "syllabus = lms.djangoapps.courseware.tabs:SyllabusTab", - "teams = lms.djangoapps.teams.plugins:TeamsTab", - "textbooks = lms.djangoapps.courseware.tabs:TextbookTabs", - "wiki = lms.djangoapps.course_wiki.tab:WikiTab", - ], - "openedx.course_app": [ - "calculator = lms.djangoapps.courseware.plugins:CalculatorCourseApp", - "custom_pages = lms.djangoapps.courseware.plugins:CustomPagesCourseApp", - "discussion = openedx.core.djangoapps.discussions.plugins:DiscussionCourseApp", - "edxnotes = lms.djangoapps.edxnotes.plugins:EdxNotesCourseApp", - "live = openedx.core.djangoapps.course_live.plugins:LiveCourseApp", - "ora_settings = lms.djangoapps.courseware.plugins:ORASettingsApp", - "proctoring = lms.djangoapps.courseware.plugins:ProctoringCourseApp", - "progress = lms.djangoapps.courseware.plugins:ProgressCourseApp", - "teams = lms.djangoapps.teams.plugins:TeamsCourseApp", - "textbooks = lms.djangoapps.courseware.plugins:TextbooksCourseApp", - "wiki = lms.djangoapps.course_wiki.plugins.course_app:WikiCourseApp", - ], - "openedx.course_tool": [ - "calendar_sync_toggle = openedx.features.calendar_sync.plugins:CalendarSyncToggleTool", - "course_bookmarks = openedx.features.course_bookmarks.plugins:CourseBookmarksTool", - "course_updates = openedx.features.course_experience.plugins:CourseUpdatesTool", - "financial_assistance = lms.djangoapps.courseware.course_tools:FinancialAssistanceTool", - ], - "openedx.user_partition_scheme": [ - "cohort = openedx.core.djangoapps.course_groups.partition_scheme:CohortPartitionScheme", - "content_type_gate = openedx.features.content_type_gating.partitions:ContentTypeGatingPartitionScheme", - "enrollment_track = openedx.core.djangoapps.verified_track_content.partition_scheme:EnrollmentTrackPartitionScheme", # lint-amnesty, pylint: disable=line-too-long - "random = openedx.core.djangoapps.user_api.partition_schemes:RandomUserPartitionScheme", - "team = lms.djangoapps.teams.team_partition_scheme:TeamPartitionScheme", - "verification = openedx.core.djangoapps.user_api.partition_schemes:ReturnGroup1PartitionScheme", - ], - "openedx.block_structure_transformer": [ - "library_content = lms.djangoapps.course_blocks.transformers.library_content:ContentLibraryTransformer", - "library_content_randomize = lms.djangoapps.course_blocks.transformers.library_content:ContentLibraryOrderTransformer", # lint-amnesty, pylint: disable=line-too-long - "split_test = lms.djangoapps.course_blocks.transformers.split_test:SplitTestTransformer", - "start_date = lms.djangoapps.course_blocks.transformers.start_date:StartDateTransformer", - "user_partitions = lms.djangoapps.course_blocks.transformers.user_partitions:UserPartitionTransformer", - "visibility = lms.djangoapps.course_blocks.transformers.visibility:VisibilityTransformer", - "hidden_content = lms.djangoapps.course_blocks.transformers.hidden_content:HiddenContentTransformer", - "course_blocks_api = lms.djangoapps.course_api.blocks.transformers.blocks_api:BlocksAPITransformer", - "milestones = lms.djangoapps.course_api.blocks.transformers.milestones:MilestonesAndSpecialExamsTransformer", # lint-amnesty, pylint: disable=line-too-long - "grades = lms.djangoapps.grades.transformer:GradesTransformer", - "completion = lms.djangoapps.course_api.blocks.transformers.block_completion:BlockCompletionTransformer", - "load_override_data = lms.djangoapps.course_blocks.transformers.load_override_data:OverrideDataTransformer", - "content_type_gate = openedx.features.content_type_gating.block_transformers:ContentTypeGateTransformer", - "access_denied_message_filter = lms.djangoapps.course_blocks.transformers.access_denied_filter:AccessDeniedMessageFilterTransformer", # lint-amnesty, pylint: disable=line-too-long - "open_assessment_transformer = lms.djangoapps.courseware.transformers:OpenAssessmentDateTransformer", - 'effort_estimation = openedx.features.effort_estimation.api:EffortEstimationTransformer', - 'discussions_link = openedx.core.djangoapps.discussions.transformers:DiscussionsTopicLinkTransformer', - ], - "openedx.ace.policy": [ - "bulk_email_optout = lms.djangoapps.bulk_email.policies:CourseEmailOptout", - "course_push_notification_optout = openedx.core.djangoapps.notifications.policies:CoursePushNotificationOptout", # lint-amnesty, pylint: disable=line-too-long - "disabled_user_optout = openedx.core.djangoapps.ace_common.policies:DisableUserOptout", - ], - "openedx.call_to_action": [ - "personalized_learner_schedules = openedx.features.personalized_learner_schedules.call_to_action:PersonalizedLearnerScheduleCallToAction" # lint-amnesty, pylint: disable=line-too-long - ], - "lms.djangoapp": [ - "ace_common = openedx.core.djangoapps.ace_common.apps:AceCommonConfig", - "content_libraries = openedx.core.djangoapps.content_libraries.apps:ContentLibrariesConfig", - "course_apps = openedx.core.djangoapps.course_apps.apps:CourseAppsConfig", - "course_live = openedx.core.djangoapps.course_live.apps:CourseLiveConfig", - "courseware_api = openedx.core.djangoapps.courseware_api.apps:CoursewareAPIConfig", - "credentials = openedx.core.djangoapps.credentials.apps:CredentialsConfig", - "discussion = lms.djangoapps.discussion.apps:DiscussionConfig", - "discussions = openedx.core.djangoapps.discussions.apps:DiscussionsConfig", - "grades = lms.djangoapps.grades.apps:GradesConfig", - "plugins = openedx.core.djangoapps.plugins.apps:PluginsConfig", - "theming = openedx.core.djangoapps.theming.apps:ThemingConfig", - "bookmarks = openedx.core.djangoapps.bookmarks.apps:BookmarksConfig", - "zendesk_proxy = openedx.core.djangoapps.zendesk_proxy.apps:ZendeskProxyConfig", - "instructor = lms.djangoapps.instructor.apps:InstructorConfig", - "password_policy = openedx.core.djangoapps.password_policy.apps:PasswordPolicyConfig", - "user_authn = openedx.core.djangoapps.user_authn.apps:UserAuthnConfig", - "program_enrollments = lms.djangoapps.program_enrollments.apps:ProgramEnrollmentsConfig", - ], - "cms.djangoapp": [ - "ace_common = openedx.core.djangoapps.ace_common.apps:AceCommonConfig", - "bookmarks = openedx.core.djangoapps.bookmarks.apps:BookmarksConfig", - "course_live = openedx.core.djangoapps.course_live.apps:CourseLiveConfig", - "content_libraries = openedx.core.djangoapps.content_libraries.apps:ContentLibrariesConfig", - "content_staging = openedx.core.djangoapps.content_staging.apps:ContentStagingAppConfig", - "course_apps = openedx.core.djangoapps.course_apps.apps:CourseAppsConfig", - # Importing an LMS app into the Studio process is not a good - # practice. We're ignoring this for Discussions here because its - # placement in LMS is a historical artifact. The eventual goal is to - # consolidate the multiple discussions-related Django apps and - # either put them in the openedx/ dir, or in another repo entirely. - "discussion = lms.djangoapps.discussion.apps:DiscussionConfig", - "discussions = openedx.core.djangoapps.discussions.apps:DiscussionsConfig", - "instructor = lms.djangoapps.instructor.apps:InstructorConfig", - "olx_rest_api = openedx.core.djangoapps.olx_rest_api.apps:OlxRestApiAppConfig", - "password_policy = openedx.core.djangoapps.password_policy.apps:PasswordPolicyConfig", - "plugins = openedx.core.djangoapps.plugins.apps:PluginsConfig", - "theming = openedx.core.djangoapps.theming.apps:ThemingConfig", - "user_authn = openedx.core.djangoapps.user_authn.apps:UserAuthnConfig", - "zendesk_proxy = openedx.core.djangoapps.zendesk_proxy.apps:ZendeskProxyConfig", - ], - 'openedx.learning_context': [ - 'lib = openedx.core.djangoapps.content_libraries.library_context:LibraryContextImpl', - ], - 'openedx.dynamic_partition_generator': [ - 'content_type_gating = openedx.features.content_type_gating.partitions:create_content_gating_partition', - 'enrollment_track = xmodule.partitions.enrollment_track_partition_generator:create_enrollment_track_partition', # lint-amnesty, pylint: disable=line-too-long - 'team = openedx.core.lib.teams_config:create_team_set_partition', - ], - 'xblock.v1': XBLOCKS, - 'xblock_asides.v1': XBLOCKS_ASIDES, - 'console_scripts': [ - 'xmodule_assets = xmodule.static_content:main', - ], - } -) diff --git a/tox.ini b/tox.ini index e5df7f0fbd2f..c129fb8cf0d4 100644 --- a/tox.ini +++ b/tox.ini @@ -2,7 +2,7 @@ envlist = py{311} quality # This is needed to prevent the lms, cms, and openedx packages inside the "Open -# edX" package (defined in setup.py) from getting installed into site-packages +# edX" package (defined in pyproject.toml) from getting installed into site-packages # where they can get imported, which is bad because those won't even contain # most of the source code since we don't explicitly add anything to the source # distribution. diff --git a/xmodule/partitions/partitions.py b/xmodule/partitions/partitions.py index 9a9d637d318c..1ab152f81cf9 100644 --- a/xmodule/partitions/partitions.py +++ b/xmodule/partitions/partitions.py @@ -17,7 +17,7 @@ # * 1 -> 49: Unused/Reserved # * 50: The enrollment track partition # * 51: The content type gating partition (defined elsewhere) -# * 52-99: Available for other single user partitions, plugged in via setup.py. +# * 52-99: Available for other single user partitions, plugged in via entry points. # Operators, beware of conflicting IDs between plugins! # * 100 -> 2^31-1: General namespace for generating IDs at runtime. # This includes, at least: content partitions, the cohort partition, and teamset partitions.