learning-credentials 0.2.2rc1__tar.gz → 0.2.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/CHANGELOG.rst +7 -0
  2. {learning_credentials-0.2.2rc1/learning_credentials.egg-info → learning_credentials-0.2.3}/PKG-INFO +22 -27
  3. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/__init__.py +0 -2
  4. learning_credentials-0.2.3/learning_credentials/conf/locale/config.yaml +85 -0
  5. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/processors.py +25 -24
  6. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/templates/learning_credentials/edx_ace/certificate_generated/email/body.html +2 -2
  7. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/templates/learning_credentials/edx_ace/certificate_generated/email/body.txt +2 -2
  8. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3/learning_credentials.egg-info}/PKG-INFO +22 -27
  9. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials.egg-info/SOURCES.txt +1 -4
  10. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/pyproject.toml +95 -19
  11. learning_credentials-0.2.2rc1/learning_credentials.egg-info/not-zip-safe +0 -1
  12. learning_credentials-0.2.2rc1/requirements/base.in +0 -17
  13. learning_credentials-0.2.2rc1/requirements/constraints.txt +0 -15
  14. learning_credentials-0.2.2rc1/setup.py +0 -172
  15. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/LICENSE.txt +0 -0
  16. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/MANIFEST.in +0 -0
  17. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/README.rst +0 -0
  18. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/admin.py +0 -0
  19. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/apps.py +0 -0
  20. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/compat.py +0 -0
  21. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/exceptions.py +0 -0
  22. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/generators.py +0 -0
  23. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/migrations/0001_initial.py +0 -0
  24. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/migrations/0002_migrate_to_learning_credentials.py +0 -0
  25. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/migrations/0003_rename_certificates_to_credentials.py +0 -0
  26. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/migrations/0004_replace_course_keys_with_learning_context_keys.py +0 -0
  27. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/migrations/0005_rename_processors_and_generators.py +0 -0
  28. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/migrations/0006_cleanup_openedx_certificates_tables.py +0 -0
  29. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/migrations/__init__.py +0 -0
  30. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/models.py +0 -0
  31. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/settings/__init__.py +0 -0
  32. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/settings/common.py +0 -0
  33. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/settings/production.py +0 -0
  34. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/tasks.py +0 -0
  35. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/templates/learning_credentials/base.html +0 -0
  36. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/templates/learning_credentials/edx_ace/certificate_generated/email/from_name.txt +0 -0
  37. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/templates/learning_credentials/edx_ace/certificate_generated/email/head.html +0 -0
  38. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/templates/learning_credentials/edx_ace/certificate_generated/email/subject.txt +0 -0
  39. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/urls.py +0 -0
  40. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials/views.py +0 -0
  41. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials.egg-info/dependency_links.txt +0 -0
  42. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials.egg-info/entry_points.txt +0 -0
  43. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials.egg-info/requires.txt +7 -7
  44. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/learning_credentials.egg-info/top_level.txt +0 -0
  45. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/setup.cfg +0 -0
  46. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/tests/test_generators.py +0 -0
  47. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/tests/test_models.py +0 -0
  48. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/tests/test_processors.py +0 -0
  49. {learning_credentials-0.2.2rc1 → learning_credentials-0.2.3}/tests/test_tasks.py +0 -0
@@ -16,6 +16,13 @@ Unreleased
16
16
 
17
17
  *
18
18
 
19
+ 0.2.3 - 2025-08-18
20
+
21
+ Modified
22
+ ========
23
+
24
+ * Certificate email template wording.
25
+
19
26
  0.2.2 - 2025-08-05
20
27
 
21
28
  Added
@@ -1,17 +1,17 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: learning-credentials
3
- Version: 0.2.2rc1
3
+ Version: 0.2.3
4
4
  Summary: A pluggable service for preparing Open edX credentials.
5
- Home-page: https://github.com/open-craft/learning-credentials
6
- Author: OpenCraft
7
- Author-email: help@opencraft.com
8
- License: AGPL 3.0
9
- Keywords: Python edx
10
- Classifier: Development Status :: 3 - Alpha
5
+ Author-email: OpenCraft <help@opencraft.com>
6
+ License-Expression: AGPL-3.0-or-later
7
+ Project-URL: Homepage, https://github.com/open-craft/learning-credentials
8
+ Project-URL: Repository, https://github.com/open-craft/learning-credentials
9
+ Project-URL: Documentation, https://learning-credentials.readthedocs.io/
10
+ Keywords: Python,edx,credentials,django
11
+ Classifier: Development Status :: 5 - Production/Stable
11
12
  Classifier: Framework :: Django
12
13
  Classifier: Framework :: Django :: 4.2
13
14
  Classifier: Intended Audience :: Developers
14
- Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
15
15
  Classifier: Natural Language :: English
16
16
  Classifier: Programming Language :: Python :: 3
17
17
  Classifier: Programming Language :: Python :: 3.11
@@ -19,31 +19,20 @@ Classifier: Programming Language :: Python :: 3.12
19
19
  Requires-Python: >=3.11
20
20
  Description-Content-Type: text/x-rst
21
21
  License-File: LICENSE.txt
22
- Requires-Dist: celery
23
22
  Requires-Dist: django
24
- Requires-Dist: django-celery-beat
25
23
  Requires-Dist: django-model-utils
26
- Requires-Dist: django-object-actions
24
+ Requires-Dist: edx-opaque-keys
25
+ Requires-Dist: celery
26
+ Requires-Dist: django-celery-beat
27
27
  Requires-Dist: django_reverse_admin
28
28
  Requires-Dist: djangorestframework
29
- Requires-Dist: edx-opaque-keys
30
- Requires-Dist: edx_ace
31
- Requires-Dist: learning-paths-plugin>=0.3.4
32
- Requires-Dist: openedx-completion-aggregator
29
+ Requires-Dist: django-object-actions
33
30
  Requires-Dist: pypdf
34
31
  Requires-Dist: reportlab
35
- Dynamic: author
36
- Dynamic: author-email
37
- Dynamic: classifier
38
- Dynamic: description
39
- Dynamic: description-content-type
40
- Dynamic: home-page
41
- Dynamic: keywords
42
- Dynamic: license
32
+ Requires-Dist: openedx-completion-aggregator
33
+ Requires-Dist: edx_ace
34
+ Requires-Dist: learning-paths-plugin>=0.3.4
43
35
  Dynamic: license-file
44
- Dynamic: requires-dist
45
- Dynamic: requires-python
46
- Dynamic: summary
47
36
 
48
37
  learning-credentials
49
38
  ####################
@@ -167,7 +156,6 @@ Please do not report security issues in public. Please email security@openedx.or
167
156
  :target: https://mango-dune-07a8b7110.1.azurestaticapps.net/?repo=open-craft/learning-credentials
168
157
  :alt: Visualization
169
158
 
170
-
171
159
  Change Log
172
160
  ##########
173
161
 
@@ -186,6 +174,13 @@ Unreleased
186
174
 
187
175
  *
188
176
 
177
+ 0.2.3 - 2025-08-18
178
+
179
+ Modified
180
+ ========
181
+
182
+ * Certificate email template wording.
183
+
189
184
  0.2.2 - 2025-08-05
190
185
 
191
186
  Added
@@ -1,3 +1 @@
1
1
  """A pluggable service for preparing Open edX credentials."""
2
-
3
- __version__ = '0.2.2-rc1'
@@ -0,0 +1,85 @@
1
+ # Configuration for i18n workflow.
2
+
3
+ locales:
4
+ - en # English - Source Language
5
+ - am # Amharic
6
+ - ar # Arabic
7
+ - az # Azerbaijani
8
+ - bg_BG # Bulgarian (Bulgaria)
9
+ - bn_BD # Bengali (Bangladesh)
10
+ - bn_IN # Bengali (India)
11
+ - bs # Bosnian
12
+ - ca # Catalan
13
+ - ca@valencia # Catalan (Valencia)
14
+ - cs # Czech
15
+ - cy # Welsh
16
+ - da # Danish
17
+ - de_DE # German (Germany)
18
+ - el # Greek
19
+ - en # English
20
+ - en_GB # English (United Kingdom)
21
+ # Don't pull these until we figure out why pages randomly display in these locales,
22
+ # when the user's browser is in English and the user is not logged in.
23
+ # - en@lolcat # LOLCAT English
24
+ # - en@pirate # Pirate English
25
+ - es_419 # Spanish (Latin America)
26
+ - es_AR # Spanish (Argentina)
27
+ - es_EC # Spanish (Ecuador)
28
+ - es_ES # Spanish (Spain)
29
+ - es_MX # Spanish (Mexico)
30
+ - es_PE # Spanish (Peru)
31
+ - et_EE # Estonian (Estonia)
32
+ - eu_ES # Basque (Spain)
33
+ - fa # Persian
34
+ - fa_IR # Persian (Iran)
35
+ - fi_FI # Finnish (Finland)
36
+ - fil # Filipino
37
+ - fr # French
38
+ - gl # Galician
39
+ - gu # Gujarati
40
+ - he # Hebrew
41
+ - hi # Hindi
42
+ - hr # Croatian
43
+ - hu # Hungarian
44
+ - hy_AM # Armenian (Armenia)
45
+ - id # Indonesian
46
+ - it_IT # Italian (Italy)
47
+ - ja_JP # Japanese (Japan)
48
+ - kk_KZ # Kazakh (Kazakhstan)
49
+ - km_KH # Khmer (Cambodia)
50
+ - kn # Kannada
51
+ - ko_KR # Korean (Korea)
52
+ - lt_LT # Lithuanian (Lithuania)
53
+ - ml # Malayalam
54
+ - mn # Mongolian
55
+ - mr # Marathi
56
+ - ms # Malay
57
+ - nb # Norwegian Bokmål
58
+ - ne # Nepali
59
+ - nl_NL # Dutch (Netherlands)
60
+ - or # Oriya
61
+ - pl # Polish
62
+ - pt_BR # Portuguese (Brazil)
63
+ - pt_PT # Portuguese (Portugal)
64
+ - ro # Romanian
65
+ - ru # Russian
66
+ - si # Sinhala
67
+ - sk # Slovak
68
+ - sl # Slovenian
69
+ - sq # Albanian
70
+ - sr # Serbian
71
+ - ta # Tamil
72
+ - te # Telugu
73
+ - th # Thai
74
+ - tr_TR # Turkish (Turkey)
75
+ - uk # Ukranian
76
+ - ur # Urdu
77
+ - uz # Uzbek
78
+ - vi # Vietnamese
79
+ - zh_CN # Chinese (China)
80
+ - zh_HK # Chinese (Hong Kong)
81
+ - zh_TW # Chinese (Taiwan)
82
+
83
+ # The locales used for fake-accented English, for testing.
84
+ dummy_locales:
85
+ - eo
@@ -191,7 +191,7 @@ def retrieve_subsection_grades(learning_context_key: LearningContextKey, options
191
191
  Options:
192
192
  - required_grades: A dictionary of required grades for each category, where the keys are the category names and
193
193
  the values are the minimum required grades. The grades are percentages, so they should be in the range [0, 1].
194
- See the following example:
194
+ See the following example::
195
195
 
196
196
  {
197
197
  "required_grades": {
@@ -211,26 +211,26 @@ def retrieve_subsection_grades(learning_context_key: LearningContextKey, options
211
211
  total_grade = (homework_grade * 0.2) + (lab_grade * 0.1) + (exam_grade * 0.7)
212
212
  - steps: For learning paths only. A dictionary with step-specific options in the format
213
213
  {"&lt;course_key&gt;": {...}}. If provided, each course in the learning path will use its specific
214
- options instead of the global options. Example:
214
+ options instead of the global options. Example::
215
215
 
216
216
  {
217
217
  "required_grades": {
218
- "Total": 0.8
218
+ "Total": 0.8
219
219
  },
220
220
  "steps": {
221
- "course-v1:edX+DemoX+Demo_Course": {
222
- "required_grades": {
223
- "Total": 0.9
224
- }
225
- },
226
- "course-v1:edX+CS101+2023": {
227
- "required_grades": {
228
- "Homework": 0.5,
229
- "Total": 0.7
230
- }
221
+ "course-v1:edX+DemoX+Demo_Course": {
222
+ "required_grades": {
223
+ "Total": 0.9
231
224
  }
225
+ },
226
+ "course-v1:edX+CS101+2023": {
227
+ "required_grades": {
228
+ "Homework": 0.5,
229
+ "Total": 0.7
230
+ }
231
+ }
232
232
  }
233
- }
233
+ }
234
234
  """
235
235
  return _process_learning_context(learning_context_key, _retrieve_course_subsection_grades, options)
236
236
 
@@ -305,19 +305,19 @@ def retrieve_completions(learning_context_key: LearningContextKey, options: dict
305
305
  - required_completion: The minimum required completion percentage. The default value is 0.9.
306
306
  - steps: For learning paths only. A dictionary with step-specific options in the format
307
307
  {"&lt;course_key&gt;": {...}}. If provided, each course in the learning path will use its specific
308
- options instead of the global options. Example:
308
+ options instead of the global options. Example::
309
309
 
310
310
  {
311
311
  "required_completion": 0.8,
312
312
  "steps": {
313
- "course-v1:edX+DemoX+Demo_Course": {
314
- "required_completion": 0.9
315
- },
316
- "course-v1:edX+CS101+2023": {
317
- "required_completion": 0.7
318
- }
313
+ "course-v1:edX+DemoX+Demo_Course": {
314
+ "required_completion": 0.9
315
+ },
316
+ "course-v1:edX+CS101+2023": {
317
+ "required_completion": 0.7
318
+ }
319
319
  }
320
- }
320
+ }
321
321
  """
322
322
  return _process_learning_context(learning_context_key, _retrieve_course_completions, options)
323
323
 
@@ -336,7 +336,7 @@ def retrieve_completions_and_grades(learning_context_key: LearningContextKey, op
336
336
  Options:
337
337
  - required_completion: The minimum required completion percentage (default: 0.9)
338
338
  - required_grades: A dictionary of required grades for each category, where the keys are the category names and
339
- the values are the minimum required grades. The grades are percentages in the range [0, 1]. Example:
339
+ the values are the minimum required grades. The grades are percentages in the range [0, 1]. Example::
340
340
 
341
341
  {
342
342
  "required_grades": {
@@ -345,9 +345,10 @@ def retrieve_completions_and_grades(learning_context_key: LearningContextKey, op
345
345
  "Total": 0.8
346
346
  }
347
347
  }
348
+
348
349
  - steps: For learning paths only. A dictionary with step-specific options in the format
349
350
  {"&lt;course_key&gt;": {...}}. If provided, each course in the learning path will use its specific
350
- options instead of the global options. Example:
351
+ options instead of the global options. Example::
351
352
 
352
353
  {
353
354
  "required_completion": 0.8,
@@ -5,7 +5,7 @@
5
5
  </p>
6
6
 
7
7
  <p>
8
- {% blocktrans %}We are happy to inform you that you have earned a certificate. You should feel very proud of the work you have done in this course. We congratulate you on your efforts and your learning.{% endblocktrans %}
8
+ {% blocktrans %}We are happy to inform you that you have earned a certificate. You should feel very proud of the work you have done in this program. We congratulate you on your efforts and your learning.{% endblocktrans %}
9
9
  </p>
10
10
 
11
11
  <p>
@@ -15,7 +15,7 @@
15
15
 
16
16
  <div>
17
17
  <div>
18
- {% blocktrans %}Thank you for choosing {{ platform_name }} for your learning journey. We look forward to seeing you in more courses in the future.{% endblocktrans %}
18
+ {% blocktrans %}Thank you for choosing {{ platform_name }} for your learning journey. We look forward to seeing you in more programs in the future.{% endblocktrans %}
19
19
  </div>
20
20
  </div>
21
21
 
@@ -2,12 +2,12 @@
2
2
 
3
3
  {% blocktrans %}Thank you for your participation in {{ course_name }} at {{ platform_name }}!{% endblocktrans %}
4
4
 
5
- {% blocktrans %}We are happy to inform you that you have earned a certificate. You should feel very proud of the work you have done in this course. We congratulate you on your efforts and your learning.{% endblocktrans %}
5
+ {% blocktrans %}We are happy to inform you that you have earned a certificate. You should feel very proud of the work you have done in this program. We congratulate you on your efforts and your learning.{% endblocktrans %}
6
6
 
7
7
  {% trans "To view and download your certificate, please click on the following link:" %}
8
8
 
9
9
  {{ certificate_link }}
10
10
 
11
- {% blocktrans %}Thank you for choosing {{ platform_name }} for your learning journey. We look forward to seeing you in more courses in the future.{% endblocktrans %}
11
+ {% blocktrans %}Thank you for choosing {{ platform_name }} for your learning journey. We look forward to seeing you in more programs in the future.{% endblocktrans %}
12
12
 
13
13
  {% endautoescape %}
@@ -1,17 +1,17 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: learning-credentials
3
- Version: 0.2.2rc1
3
+ Version: 0.2.3
4
4
  Summary: A pluggable service for preparing Open edX credentials.
5
- Home-page: https://github.com/open-craft/learning-credentials
6
- Author: OpenCraft
7
- Author-email: help@opencraft.com
8
- License: AGPL 3.0
9
- Keywords: Python edx
10
- Classifier: Development Status :: 3 - Alpha
5
+ Author-email: OpenCraft <help@opencraft.com>
6
+ License-Expression: AGPL-3.0-or-later
7
+ Project-URL: Homepage, https://github.com/open-craft/learning-credentials
8
+ Project-URL: Repository, https://github.com/open-craft/learning-credentials
9
+ Project-URL: Documentation, https://learning-credentials.readthedocs.io/
10
+ Keywords: Python,edx,credentials,django
11
+ Classifier: Development Status :: 5 - Production/Stable
11
12
  Classifier: Framework :: Django
12
13
  Classifier: Framework :: Django :: 4.2
13
14
  Classifier: Intended Audience :: Developers
14
- Classifier: License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)
15
15
  Classifier: Natural Language :: English
16
16
  Classifier: Programming Language :: Python :: 3
17
17
  Classifier: Programming Language :: Python :: 3.11
@@ -19,31 +19,20 @@ Classifier: Programming Language :: Python :: 3.12
19
19
  Requires-Python: >=3.11
20
20
  Description-Content-Type: text/x-rst
21
21
  License-File: LICENSE.txt
22
- Requires-Dist: celery
23
22
  Requires-Dist: django
24
- Requires-Dist: django-celery-beat
25
23
  Requires-Dist: django-model-utils
26
- Requires-Dist: django-object-actions
24
+ Requires-Dist: edx-opaque-keys
25
+ Requires-Dist: celery
26
+ Requires-Dist: django-celery-beat
27
27
  Requires-Dist: django_reverse_admin
28
28
  Requires-Dist: djangorestframework
29
- Requires-Dist: edx-opaque-keys
30
- Requires-Dist: edx_ace
31
- Requires-Dist: learning-paths-plugin>=0.3.4
32
- Requires-Dist: openedx-completion-aggregator
29
+ Requires-Dist: django-object-actions
33
30
  Requires-Dist: pypdf
34
31
  Requires-Dist: reportlab
35
- Dynamic: author
36
- Dynamic: author-email
37
- Dynamic: classifier
38
- Dynamic: description
39
- Dynamic: description-content-type
40
- Dynamic: home-page
41
- Dynamic: keywords
42
- Dynamic: license
32
+ Requires-Dist: openedx-completion-aggregator
33
+ Requires-Dist: edx_ace
34
+ Requires-Dist: learning-paths-plugin>=0.3.4
43
35
  Dynamic: license-file
44
- Dynamic: requires-dist
45
- Dynamic: requires-python
46
- Dynamic: summary
47
36
 
48
37
  learning-credentials
49
38
  ####################
@@ -167,7 +156,6 @@ Please do not report security issues in public. Please email security@openedx.or
167
156
  :target: https://mango-dune-07a8b7110.1.azurestaticapps.net/?repo=open-craft/learning-credentials
168
157
  :alt: Visualization
169
158
 
170
-
171
159
  Change Log
172
160
  ##########
173
161
 
@@ -186,6 +174,13 @@ Unreleased
186
174
 
187
175
  *
188
176
 
177
+ 0.2.3 - 2025-08-18
178
+
179
+ Modified
180
+ ========
181
+
182
+ * Certificate email template wording.
183
+
189
184
  0.2.2 - 2025-08-05
190
185
 
191
186
  Added
@@ -3,7 +3,6 @@ LICENSE.txt
3
3
  MANIFEST.in
4
4
  README.rst
5
5
  pyproject.toml
6
- setup.py
7
6
  learning_credentials/__init__.py
8
7
  learning_credentials/admin.py
9
8
  learning_credentials/apps.py
@@ -19,9 +18,9 @@ learning_credentials.egg-info/PKG-INFO
19
18
  learning_credentials.egg-info/SOURCES.txt
20
19
  learning_credentials.egg-info/dependency_links.txt
21
20
  learning_credentials.egg-info/entry_points.txt
22
- learning_credentials.egg-info/not-zip-safe
23
21
  learning_credentials.egg-info/requires.txt
24
22
  learning_credentials.egg-info/top_level.txt
23
+ learning_credentials/conf/locale/config.yaml
25
24
  learning_credentials/migrations/0001_initial.py
26
25
  learning_credentials/migrations/0002_migrate_to_learning_credentials.py
27
26
  learning_credentials/migrations/0003_rename_certificates_to_credentials.py
@@ -38,8 +37,6 @@ learning_credentials/templates/learning_credentials/edx_ace/certificate_generate
38
37
  learning_credentials/templates/learning_credentials/edx_ace/certificate_generated/email/from_name.txt
39
38
  learning_credentials/templates/learning_credentials/edx_ace/certificate_generated/email/head.html
40
39
  learning_credentials/templates/learning_credentials/edx_ace/certificate_generated/email/subject.txt
41
- requirements/base.in
42
- requirements/constraints.txt
43
40
  tests/test_generators.py
44
41
  tests/test_models.py
45
42
  tests/test_processors.py
@@ -1,3 +1,97 @@
1
+ [project]
2
+ name = "learning-credentials"
3
+ version = "0.2.3"
4
+ description = "A pluggable service for preparing Open edX credentials."
5
+ dynamic = ["readme"]
6
+ requires-python = ">=3.11"
7
+ license = "AGPL-3.0-or-later"
8
+ license-files = ["LICENSE.txt"]
9
+ authors = [{ name = "OpenCraft", email = "help@opencraft.com" }]
10
+ keywords = ["Python", "edx", "credentials", "django"]
11
+ classifiers = [
12
+ "Development Status :: 5 - Production/Stable",
13
+ "Framework :: Django",
14
+ "Framework :: Django :: 4.2",
15
+ "Intended Audience :: Developers",
16
+ "Natural Language :: English",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ ]
21
+ dependencies = [
22
+ "django", # Web application framework
23
+ "django-model-utils", # Provides TimeStampedModel abstract base class
24
+ "edx-opaque-keys", # Create and introspect Course and XBlock identities
25
+ "celery", # Distributed task queue
26
+ "django-celery-beat", # Periodic task scheduler
27
+ "django_reverse_admin", # Provides reverse inlines in the admin interface
28
+ "djangorestframework", # RESTful API framework
29
+ "django-object-actions", # Provides actions on objects in the admin interface
30
+ # TODO: Extract these to a plugin.
31
+ "pypdf", # PDF manipulation library
32
+ "reportlab", # PDF generation library
33
+ "openedx-completion-aggregator", # Completion aggregation service
34
+ "edx_ace", # Messaging library
35
+ "learning-paths-plugin>=0.3.4", # Learning Paths support
36
+ ]
37
+
38
+ [project.urls]
39
+ Homepage = "https://github.com/open-craft/learning-credentials"
40
+ Repository = "https://github.com/open-craft/learning-credentials"
41
+ Documentation = "https://learning-credentials.readthedocs.io/"
42
+
43
+ [project.entry-points."lms.djangoapp"]
44
+ learning_credentials = "learning_credentials.apps:LearningCredentialsConfig"
45
+
46
+ [tool.setuptools.packages.find]
47
+ include = ["learning_credentials", "learning_credentials.*"]
48
+ exclude = ["*tests"]
49
+
50
+ [tool.setuptools.package-data]
51
+ learning_credentials = ["templates/**/*", "conf/locale/**/*"]
52
+
53
+ [tool.setuptools.dynamic]
54
+ readme = { file = ["README.rst", "CHANGELOG.rst"], content-type = "text/x-rst" }
55
+
56
+ [dependency-groups]
57
+ test = [
58
+ "pytest-cov",
59
+ "django-coverage-plugin",
60
+ "pytest-django",
61
+ "code-annotations",
62
+ "dj-inmemorystorage",
63
+ "factory-boy",
64
+ ]
65
+ django42 = ["django>=4.2,<5.0"]
66
+ django52 = ["django>=5.2,<5.3"]
67
+ ci = ["tox", "tox-uv"]
68
+ quality = ["ruff", "yamllint"]
69
+ doc = ["Sphinx", "doc8", "sphinx-book-theme", "twine"]
70
+ dev = [
71
+ { include-group = "test" },
72
+ { include-group = "ci" },
73
+ { include-group = "quality" },
74
+ { include-group = "doc" },
75
+ "diff-cover",
76
+ "edx-i18n-tools",
77
+ # External dev constraints (DO NOT REMOVE THIS LINE)
78
+ "Django<5.0",
79
+ ]
80
+
81
+ [tool.uv]
82
+ constraint-dependencies = [
83
+ # External constraints (DO NOT REMOVE THIS LINE)
84
+ "elasticsearch<7.14.0",
85
+ "pip<24.3",
86
+ ]
87
+ conflicts = [
88
+ [
89
+ { group = "django42" },
90
+ { group = "django52" },
91
+ { group = "dev" },
92
+ ],
93
+ ]
94
+
1
95
  [tool.coverage.run]
2
96
  include = ['learning_credentials/**']
3
97
  omit = ['*/migrations/*', 'tests/*']
@@ -79,6 +173,7 @@ ignore = [
79
173
  'TD002', # missing-t\odo-author
80
174
  'TD003', # missing-t\odo-link
81
175
  'TRY003', # raise-vanilla-args
176
+ 'COM812' # missing-trailing-comma (incompatible with ruff formatter)
82
177
  ]
83
178
 
84
179
  [tool.ruff.lint.per-file-ignores]
@@ -101,25 +196,6 @@ allow-magic-value-types = ['int', 'str']
101
196
  [tool.ruff.format]
102
197
  quote-style = "preserve"
103
198
 
104
- [tool.black]
105
- line-length = 120
106
- target-version = ['py311']
107
- skip_string_normalization = true
108
- exclude = '''
109
- /(
110
- \.git
111
- | \.hg
112
- | \.mypy_cache
113
- | \.tox
114
- | \.venv
115
- | _build
116
- | buck-out
117
- | build
118
- | dist
119
- | migrations
120
- )/
121
- '''
122
-
123
199
  [tool.pytest.ini_options]
124
200
  filterwarnings = [
125
201
  # https://github.com/openedx/completion/pull/259
@@ -1,17 +0,0 @@
1
- # Core requirements for using this application
2
- -c constraints.txt
3
-
4
- django # Web application framework
5
- django-model-utils # Provides TimeStampedModel abstract base class
6
- edx-opaque-keys # Create and introspect Course and XBlock identities
7
- celery # Distributed task queue
8
- django-celery-beat # Periodic task scheduler
9
- django_reverse_admin # Provides reverse inlines in the admin interface
10
- djangorestframework # RESTful API framework
11
- django-object-actions # Provides actions on objects in the admin interface
12
- # TODO: Extract these to a plugin.
13
- pypdf # PDF manipulation library
14
- reportlab # PDF generation library
15
- openedx-completion-aggregator # Completion aggregation service
16
- edx_ace # Messaging library
17
- learning-paths-plugin>=0.3.4
@@ -1,15 +0,0 @@
1
- # Version constraints for pip-installation.
2
- #
3
- # This file doesn't install any packages. It specifies version constraints
4
- # that will be applied if a package is needed.
5
- #
6
- # When pinning something here, please provide an explanation of why. Ideally,
7
- # link to other information that will help people in the future to remove the
8
- # pin when possible. Writing an issue against the offending project and
9
- # linking to it here is good.
10
-
11
- # Common constraints for edx repos
12
- -c https://raw.githubusercontent.com/edx/edx-lint/master/edx_lint/files/common_constraints.txt
13
-
14
- # TODO: Delete this once https://github.com/googleapis/google-auth-library-python/pull/1797 is merged.
15
- cachetools<6
@@ -1,172 +0,0 @@
1
- #!/usr/bin/env python
2
- """Package metadata for learning_credentials."""
3
- from __future__ import annotations
4
-
5
- import os
6
- import re
7
- import sys
8
- from pathlib import Path
9
-
10
- from setuptools import find_packages, setup
11
-
12
-
13
- def get_version(file_path: Path) -> str:
14
- """
15
- Extract the version string from the file.
16
-
17
- Input:
18
- - file_paths: relative path fragments to file with
19
- version string
20
- """
21
- filename = Path(__file__).parent / file_path
22
- with Path(filename).open(encoding="utf8") as f:
23
- version_file = f.read()
24
- version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.MULTILINE)
25
- if version_match:
26
- return version_match.group(1)
27
- raise RuntimeError('Unable to find version string.') # noqa: EM101
28
-
29
-
30
- def load_requirements(*requirements_paths: Path) -> list[str]: # noqa: C901
31
- """
32
- Load all requirements from the specified requirements files.
33
-
34
- Requirements will include any constraints from files specified
35
- with -c in the requirements files.
36
- Returns a list of requirement strings.
37
- """
38
- # e.g. {"django": "Django", "confluent-kafka": "confluent_kafka[avro]"}
39
- by_canonical_name = {}
40
-
41
- def check_name_consistent(package: str) -> None:
42
- """
43
- Raise exception if package is named different ways.
44
-
45
- This ensures that packages are named consistently so we can match
46
- constraints to packages. It also ensures that if we require a package
47
- with extras we don't constrain it without mentioning the extras (since
48
- that too would interfere with matching constraints.)
49
- """
50
- canonical = package.lower().replace('_', '-').split('[')[0]
51
- seen_spelling = by_canonical_name.get(canonical)
52
- if seen_spelling is None:
53
- by_canonical_name[canonical] = package
54
- elif seen_spelling != package:
55
- raise Exception( # noqa: TRY002
56
- f'Encountered both "{seen_spelling}" and "{package}" in requirements ' # noqa: EM102
57
- 'and constraints files; please use just one or the other.',
58
- )
59
-
60
- requirements = {}
61
- constraint_files = set()
62
-
63
- # groups "pkg<=x.y.z,..." into ("pkg", "<=x.y.z,...")
64
- re_package_name_base_chars = r"a-zA-Z0-9\-_." # chars allowed in base package name
65
- # Two groups: name[maybe,extras], and optionally a constraint
66
- requirement_line_regex = re.compile(
67
- fr"([{re_package_name_base_chars}]+(?:\[[{re_package_name_base_chars},\s]+])?)([<>=][^#\s]+)?",
68
- )
69
-
70
- def add_version_constraint_or_raise(
71
- current_line: str,
72
- current_requirements: dict[str, str],
73
- add_if_not_present: bool, # noqa: FBT001
74
- ):
75
- regex_match = requirement_line_regex.match(current_line)
76
- if regex_match:
77
- package = regex_match.group(1)
78
- version_constraints = regex_match.group(2)
79
- check_name_consistent(package)
80
- existing_version_constraints = current_requirements.get(package)
81
- # It's fine to add constraints to an unconstrained package,
82
- # but raise an error if there are already constraints in place.
83
- if existing_version_constraints and existing_version_constraints != version_constraints:
84
- # noinspection PyExceptionInherit
85
- raise BaseException( # noqa: TRY002
86
- f'Multiple constraint definitions found for {package}:' # noqa: EM102
87
- f' "{existing_version_constraints}" and "{version_constraints}".'
88
- f'Combine constraints into one location with {package}'
89
- f'{existing_version_constraints},{version_constraints}.',
90
- )
91
- if add_if_not_present or package in current_requirements:
92
- current_requirements[package] = version_constraints
93
-
94
- # Read requirements from .in files and store the path to any
95
- # constraint files that are pulled in.
96
- for path in requirements_paths:
97
- with path.open() as reqs:
98
- for line in reqs:
99
- if is_requirement(line):
100
- add_version_constraint_or_raise(line, requirements, add_if_not_present=True)
101
- if line and line.startswith('-c') and not line.startswith('-c http'):
102
- constraint_files.add(path.parent / line.split('#')[0].replace('-c', '').strip())
103
-
104
- # process constraint files: add constraints to existing requirements
105
- for constraint_file in constraint_files:
106
- with constraint_file.open() as reader:
107
- for line in reader:
108
- if is_requirement(line):
109
- add_version_constraint_or_raise(line, requirements, add_if_not_present=False)
110
-
111
- # process back into list of pkg><=constraints strings
112
- return [f'{pkg}{version or ""}' for (pkg, version) in sorted(requirements.items())]
113
-
114
-
115
- def is_requirement(line: str) -> bool:
116
- """
117
- Return True if the requirement line is a package requirement.
118
-
119
- Returns:
120
- bool: True if the line is not blank, a comment, a URL, or an included file.
121
- """
122
- return bool(line and line.strip() and not line.startswith(("-r", "#", "-e", "git+", "-c")))
123
-
124
-
125
- VERSION = get_version(Path('learning_credentials/__init__.py'))
126
-
127
- if sys.argv[-1] == 'tag':
128
- print("Tagging the version on github:") # noqa: T201
129
- os.system(f"git tag -a {VERSION} -m 'version {VERSION}'") # noqa: S605
130
- os.system("git push --tags") # noqa: S605, S607
131
- sys.exit()
132
-
133
- README = (Path(__file__).parent / 'README.rst').open(encoding="utf8").read()
134
- CHANGELOG = (Path(__file__).parent / 'CHANGELOG.rst').open(encoding="utf8").read()
135
-
136
- setup(
137
- name='learning-credentials',
138
- version=VERSION,
139
- description="""A pluggable service for preparing Open edX credentials.""",
140
- long_description=README + '\n\n' + CHANGELOG,
141
- long_description_content_type='text/x-rst',
142
- author='OpenCraft',
143
- author_email='help@opencraft.com',
144
- url='https://github.com/open-craft/learning-credentials',
145
- packages=find_packages(
146
- include=['learning_credentials', 'learning_credentials.*'],
147
- exclude=["*tests"],
148
- ),
149
- entry_points={
150
- "lms.djangoapp": [
151
- "learning_credentials = learning_credentials.apps:LearningCredentialsConfig",
152
- ],
153
- },
154
- include_package_data=True,
155
- install_requires=load_requirements(Path('requirements/base.in')),
156
- options={'bdist_wheel': {'universal': True}},
157
- python_requires=">=3.11",
158
- license="AGPL 3.0",
159
- zip_safe=False,
160
- keywords='Python edx',
161
- classifiers=[
162
- 'Development Status :: 3 - Alpha',
163
- 'Framework :: Django',
164
- 'Framework :: Django :: 4.2',
165
- 'Intended Audience :: Developers',
166
- 'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)',
167
- 'Natural Language :: English',
168
- 'Programming Language :: Python :: 3',
169
- 'Programming Language :: Python :: 3.11',
170
- 'Programming Language :: Python :: 3.12',
171
- ],
172
- )
@@ -1,13 +1,13 @@
1
- celery
2
1
  django
3
- django-celery-beat
4
2
  django-model-utils
5
- django-object-actions
3
+ edx-opaque-keys
4
+ celery
5
+ django-celery-beat
6
6
  django_reverse_admin
7
7
  djangorestframework
8
- edx-opaque-keys
9
- edx_ace
10
- learning-paths-plugin>=0.3.4
11
- openedx-completion-aggregator
8
+ django-object-actions
12
9
  pypdf
13
10
  reportlab
11
+ openedx-completion-aggregator
12
+ edx_ace
13
+ learning-paths-plugin>=0.3.4