openedx-learning 0.1.0__py2.py3-none-any.whl → 0.1.2__py2.py3-none-any.whl

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 (25) hide show
  1. openedx_learning/__init__.py +1 -1
  2. {openedx_learning-0.1.0.dist-info → openedx_learning-0.1.2.dist-info}/METADATA +4 -3
  3. {openedx_learning-0.1.0.dist-info → openedx_learning-0.1.2.dist-info}/RECORD +25 -9
  4. openedx_tagging/core/tagging/api.py +45 -1
  5. openedx_tagging/core/tagging/fixtures/language_taxonomy.yaml +1298 -0
  6. openedx_tagging/core/tagging/management/commands/__init__.py +0 -0
  7. openedx_tagging/core/tagging/management/commands/build_language_fixture.py +48 -0
  8. openedx_tagging/core/tagging/migrations/0003_auto_20230721_1238.py +76 -0
  9. openedx_tagging/core/tagging/migrations/0004_auto_20230723_2001.py +34 -0
  10. openedx_tagging/core/tagging/migrations/0005_language_taxonomy.py +29 -0
  11. openedx_tagging/core/tagging/migrations/0006_alter_objecttag_unique_together.py +16 -0
  12. openedx_tagging/core/tagging/models/__init__.py +11 -0
  13. openedx_tagging/core/tagging/{models.py → models/base.py} +112 -24
  14. openedx_tagging/core/tagging/models/system_defined.py +269 -0
  15. openedx_tagging/core/tagging/rest_api/urls.py +9 -0
  16. openedx_tagging/core/tagging/rest_api/v1/__init__.py +0 -0
  17. openedx_tagging/core/tagging/rest_api/v1/permissions.py +17 -0
  18. openedx_tagging/core/tagging/rest_api/v1/serializers.py +31 -0
  19. openedx_tagging/core/tagging/rest_api/v1/urls.py +14 -0
  20. openedx_tagging/core/tagging/rest_api/v1/views.py +147 -0
  21. openedx_tagging/core/tagging/rules.py +14 -15
  22. openedx_tagging/core/tagging/urls.py +10 -0
  23. {openedx_learning-0.1.0.dist-info → openedx_learning-0.1.2.dist-info}/LICENSE.txt +0 -0
  24. {openedx_learning-0.1.0.dist-info → openedx_learning-0.1.2.dist-info}/WHEEL +0 -0
  25. {openedx_learning-0.1.0.dist-info → openedx_learning-0.1.2.dist-info}/top_level.txt +0 -0
@@ -1 +1 @@
1
- __version__ = "0.1.0"
1
+ __version__ = "0.1.2"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: openedx-learning
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: An experiment.
5
5
  Home-page: https://github.com/openedx/openedx-learning
6
6
  Author: David Ormsbee
@@ -17,9 +17,10 @@ Classifier: Natural Language :: English
17
17
  Classifier: Programming Language :: Python :: 3
18
18
  Classifier: Programming Language :: Python :: 3.8
19
19
  Requires-Python: >=3.8
20
- Requires-Dist: Django (<5.0)
21
- Requires-Dist: rules (<4.0)
22
20
  Requires-Dist: djangorestframework (<4.0)
21
+ Requires-Dist: edx-drf-extensions
22
+ Requires-Dist: rules (<4.0)
23
+ Requires-Dist: Django (<5.0)
23
24
 
24
25
  openedx-learning
25
26
  =============================
@@ -1,4 +1,4 @@
1
- openedx_learning/__init__.py,sha256=kUR5RAFc7HCeiqdlX36dZOHkUI5wI6V_43RpEcD8b-0,22
1
+ openedx_learning/__init__.py,sha256=YvuYzWnKtqBb-IqG8HAu-nhIYAsgj9Vmc_b9o7vO-js,22
2
2
  openedx_learning/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  openedx_learning/contrib/media_server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  openedx_learning/contrib/media_server/apps.py,sha256=DWPy77j5hdv_tk8Y9MsoscgwRBxplO-sBVJT5grhHPA,754
@@ -41,15 +41,31 @@ openedx_learning/rest_api/v1/urls.py,sha256=lY-i3VzANvtdcJHjwygMtqEhfyMOjgIfaWpn
41
41
  openedx_tagging/__init__.py,sha256=N_pklgjdCZO62lWysvHk0w9RnDRXCBVhok0GheQrFaE,28
42
42
  openedx_tagging/core/tagging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
43
43
  openedx_tagging/core/tagging/admin.py,sha256=efVW_mA5MEey14VJdazacyxnBgbYPPfJQVS7XLKaWEg,192
44
- openedx_tagging/core/tagging/api.py,sha256=wLpix1LeQULtiJYYYIDTVZI_h915GT286EHYRG7QiCE,4314
44
+ openedx_tagging/core/tagging/api.py,sha256=ilRZVGWPq2AtQkF6n_jeiwOPIKEDvTbkYrneUiuEeXw,6602
45
45
  openedx_tagging/core/tagging/apps.py,sha256=-gp0VYqX4XQzwjjd-G68Ev2Op0INLh9Byz5UOqF5_7k,345
46
- openedx_tagging/core/tagging/models.py,sha256=PZtHVFjSaG6-GciSE5DDV-83rV3F--eRqPDACrN6kSM,21475
47
- openedx_tagging/core/tagging/rules.py,sha256=7PG2PtzUh4d4BL-d5U7H_Gb42XaZdNaNU1WMvrbVC-4,2531
46
+ openedx_tagging/core/tagging/rules.py,sha256=_a5waGxbHmAvSeFG6SefRCF4hpVdCw1hlJuyd440X_k,2688
47
+ openedx_tagging/core/tagging/urls.py,sha256=XOZ0CNp7w1Z4zcTZ9orX-uEfqogCRYTpLhVkNG8yfw8,159
48
+ openedx_tagging/core/tagging/fixtures/language_taxonomy.yaml,sha256=AIC_0L5C7jQRDqojMKi2lyvWD-tZ6qu57OLSa5AZB14,22225
49
+ openedx_tagging/core/tagging/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
+ openedx_tagging/core/tagging/management/commands/build_language_fixture.py,sha256=OScLCA9FZtoTRd83tIujIx4CO_cjGD42wZJEsW5DDx0,1899
48
51
  openedx_tagging/core/tagging/migrations/0001_initial.py,sha256=Co9qmy8c_BUOvRgf-RTpUcYqHEKolj3wBfYhPPuE-vw,8556
49
52
  openedx_tagging/core/tagging/migrations/0002_auto_20230718_2026.py,sha256=UG_q6UBmbcH92HTdC8yhO9IJRBUzSazoGG6Sm6Q90cc,2832
53
+ openedx_tagging/core/tagging/migrations/0003_auto_20230721_1238.py,sha256=c8q2apdZPNcr9U4VstFaLSO5z1k0ZlzL87qObobN7Mw,2109
54
+ openedx_tagging/core/tagging/migrations/0004_auto_20230723_2001.py,sha256=Onnc6T12BxOQX5QTFUC9Qc5leiR7014qT2jVE7N8MBU,1080
55
+ openedx_tagging/core/tagging/migrations/0005_language_taxonomy.py,sha256=WaWh4JAnbPCqPo2uFRWHPZfUC1wa9zgGuLU8Qgri68U,708
56
+ openedx_tagging/core/tagging/migrations/0006_alter_objecttag_unique_together.py,sha256=Jx7B8ZQ5u8sZksKEkpZFrcaQpBXkaJVBtTXa-k3c4xY,376
50
57
  openedx_tagging/core/tagging/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
- openedx_learning-0.1.0.dist-info/LICENSE.txt,sha256=QTW2QN7q3XszgUAXm9Dzgtu5LXYKbR1SGnqMa7ufEuY,35139
52
- openedx_learning-0.1.0.dist-info/METADATA,sha256=45f5kpDmKRvdSqT8_1ERtdtT-I7MWBsBq_N6UhWQWaE,8606
53
- openedx_learning-0.1.0.dist-info/WHEEL,sha256=Z-nyYpwrcSqxfdux5Mbn_DQ525iP7J2DG3JgGvOYyTQ,110
54
- openedx_learning-0.1.0.dist-info/top_level.txt,sha256=IYFbr5mgiEHd-LOtZmXj3q3a0bkGK1M9LY7GXgnfi4M,33
55
- openedx_learning-0.1.0.dist-info/RECORD,,
58
+ openedx_tagging/core/tagging/models/__init__.py,sha256=2THzqS9MSZvFiKTh_tGTjzXPw0GRoP7BleQMvhEJkqw,197
59
+ openedx_tagging/core/tagging/models/base.py,sha256=OYNMHqB2UHhgoAFv6E66KqtzSolsoguA337hQxMmZVU,25000
60
+ openedx_tagging/core/tagging/models/system_defined.py,sha256=o-x-ckdbiGSjLWQu0DJJsm5nETCuW4i9pPOPo-yqfxY,8422
61
+ openedx_tagging/core/tagging/rest_api/urls.py,sha256=HWK1uWlslaBeqcPdlgvRjcSk0_lm48Sq3cR3TPvTiKk,148
62
+ openedx_tagging/core/tagging/rest_api/v1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
+ openedx_tagging/core/tagging/rest_api/v1/permissions.py,sha256=xfiSuGzJ6b01XWzdPrbZWlJAAC8zjaEDhV6W7y_pq0Y,536
64
+ openedx_tagging/core/tagging/rest_api/v1/serializers.py,sha256=NX9AAVVTT9EChTIshLvitwej-TO1UJEt6VB5vgTR2y0,693
65
+ openedx_tagging/core/tagging/rest_api/v1/urls.py,sha256=Fc2nN4yFLZeKFOPPMYU_bXxNxd3Cw2gGXxiIJd5rV0c,292
66
+ openedx_tagging/core/tagging/rest_api/v1/views.py,sha256=uUl_aNEGVTu1vj36HWpZjQfw154Qq-iEGNpQ-0koZVs,5881
67
+ openedx_learning-0.1.2.dist-info/LICENSE.txt,sha256=QTW2QN7q3XszgUAXm9Dzgtu5LXYKbR1SGnqMa7ufEuY,35139
68
+ openedx_learning-0.1.2.dist-info/METADATA,sha256=xgX75erxBaiHLfBiefAd-j2VPJiws5LdA9yBt8OlfKI,8640
69
+ openedx_learning-0.1.2.dist-info/WHEEL,sha256=Z-nyYpwrcSqxfdux5Mbn_DQ525iP7J2DG3JgGvOYyTQ,110
70
+ openedx_learning-0.1.2.dist-info/top_level.txt,sha256=IYFbr5mgiEHd-LOtZmXj3q3a0bkGK1M9LY7GXgnfi4M,33
71
+ openedx_learning-0.1.2.dist-info/RECORD,,
@@ -106,8 +106,9 @@ def get_object_tags(
106
106
  Pass valid_only=False when displaying tags to content authors, so they can see invalid tags too.
107
107
  Invalid tags will (probably) be hidden from learners.
108
108
  """
109
+ ObjectTagClass = taxonomy.object_tag_class if taxonomy else ObjectTag
109
110
  tags = (
110
- ObjectTag.objects.filter(
111
+ ObjectTagClass.objects.filter(
111
112
  object_id=object_id,
112
113
  )
113
114
  .select_related("tag", "taxonomy")
@@ -136,3 +137,46 @@ def tag_object(
136
137
  Preserves existing (valid) tags, adds new (valid) tags, and removes omitted (or invalid) tags.
137
138
  """
138
139
  return taxonomy.cast().tag_object(tags, object_id)
140
+
141
+
142
+ def autocomplete_tags(
143
+ taxonomy: Taxonomy,
144
+ search: str,
145
+ object_id: str = None,
146
+ object_tags_only=True,
147
+ ) -> QuerySet:
148
+ """
149
+ Provides auto-complete suggestions by matching the `search` string against existing
150
+ ObjectTags linked to the given taxonomy. A case-insensitive search is used in order
151
+ to return the highest number of relevant tags.
152
+
153
+ If `object_id` is provided, then object tag values already linked to this object
154
+ are omitted from the returned suggestions. (ObjectTag values must be unique for a
155
+ given object + taxonomy, and so omitting these suggestions helps users avoid
156
+ duplication errors.).
157
+
158
+ Returns a QuerySet of dictionaries containing distinct `value` (string) and
159
+ `tag` (numeric ID) values, sorted alphabetically by `value`.
160
+ The `value` is what should be shown as a suggestion to users,
161
+ and if it's a free-text taxonomy, `tag` will be `None`: we include the `tag` ID
162
+ in anticipation of the second use case listed below.
163
+
164
+ Use cases:
165
+ * This method is useful for reducing tag variation in free-text taxonomies by showing
166
+ users tags that are similar to what they're typing. E.g., if the `search` string "dn"
167
+ shows that other objects have been tagged with "DNA", "DNA electrophoresis", and "DNA fingerprinting",
168
+ this encourages users to use those existing tags if relevant, instead of creating new ones that
169
+ look similar (e.g. "dna finger-printing").
170
+ * It could also be used to assist tagging for closed taxonomies with a list of possible tags which is too
171
+ large to return all at once, e.g. a user model taxonomy that dynamically creates tags on request for any
172
+ registered user in the database. (Note that this is not implemented yet, but may be as part of a future change.)
173
+ """
174
+ if not object_tags_only:
175
+ raise NotImplementedError(
176
+ _(
177
+ "Using this would return a query set of tags instead of object tags."
178
+ "For now we recommend fetching all of the taxonomy's tags "
179
+ "using get_tags() and filtering them on the frontend."
180
+ )
181
+ )
182
+ return taxonomy.cast().autocomplete_tags(search, object_id)