Skip to content

Commit e959287

Browse files
committed
refactor: consolidates ObjectTag validation
1 parent 1b0afa3 commit e959287

File tree

8 files changed

+92
-136
lines changed

8 files changed

+92
-136
lines changed

MANIFEST.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ include LICENSE.txt
33
include README.rst
44
include requirements/base.in
55
recursive-include openedx_learning *.html *.png *.gif *.js *.css *.jpg *.jpeg *.svg *.py
6-
recursive-include openedx_tagging *.html *.png *.gif *.js *.css *.jpg *.jpeg *.svg *.py
6+
recursive-include openedx_tagging *.html *.png *.gif *.js *.css *.jpg *.jpeg *.svg *.py *.yaml

openedx_tagging/core/tagging/fixtures/system_defined.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@
77
required: true
88
allow_multiple: false
99
allow_free_text: false
10+
system_defined: true
11+
visible_to_authors: true

openedx_tagging/core/tagging/management/commands/build_language_fixture.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from django.core.management.base import BaseCommand
1212

1313
endpoint = "https://pkgstore.datahub.io/core/language-codes/language-codes_json/data/97607046542b532c395cf83df5185246/language-codes_json.json"
14-
output = "./openedx_tagging/core/tagging/system_defined_taxonomies/fixtures/language_taxonomy.yaml"
14+
output = "./openedx_tagging/core/tagging/fixtures/language_taxonomy.yaml"
1515

1616
class Command(BaseCommand):
1717

openedx_tagging/core/tagging/models.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
""" Tagging app data models """
2-
from enum import Enum
32
from typing import List, Type
43

54
from django.db import models
@@ -529,9 +528,6 @@ def _check_object(self):
529528
"""
530529
# Must have a valid object id/type:
531530
return self.object_id and self.object_type
532-
533-
def _check_tag(self):
534-
return self.value
535531

536532

537533
class ClosedObjectTag(OpenObjectTag):

openedx_tagging/core/tagging/system_defined_taxonomies/object_tags.py

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212

1313
from openedx_tagging.core.tagging.models import (
14-
Tag,
1514
Taxonomy,
1615
OpenObjectTag,
1716
ClosedObjectTag,
@@ -42,21 +41,20 @@ class SystemDefinedObjectTagMixin:
4241
taxonomy but with different objects.
4342
4443
Using this approach makes the connection between the ObjectTag
45-
and system defined taxonomy as hardcoded.
44+
and system defined taxonomy as hardcoded and can't be changed.
4645
"""
4746

4847
system_defined_taxonomy_id = None
4948

50-
@classmethod
51-
def _validate_taxonomy(cls, taxonomy: Taxonomy = None):
49+
def _check_system_taxonomy(self, taxonomy: Taxonomy = None):
5250
"""
5351
Validates if the taxonomy is system-defined and match
5452
with the name stored in the object tag
5553
"""
5654
return (
57-
bool(taxonomy) and
58-
taxonomy.system_defined and
59-
taxonomy.id == cls.system_defined_taxonomy_id
55+
bool(taxonomy) and
56+
taxonomy.system_defined and
57+
taxonomy.id == self.system_defined_taxonomy_id
6058
)
6159

6260

@@ -68,12 +66,11 @@ class OpenSystemObjectTag(OpenObjectTag, SystemDefinedObjectTagMixin):
6866
class Meta:
6967
proxy = True
7068

71-
@classmethod
72-
def valid_for(cls, taxonomy: Taxonomy = None, **kwars):
73-
"""
74-
Returns True if the the taxonomy is system-defined
75-
"""
76-
return super().valid_for(taxonomy=taxonomy) and cls._validate_taxonomy(taxonomy)
69+
def _check_taxonomy(self):
70+
return (
71+
super()._check_taxonomy() and
72+
self._check_system_taxonomy(self.taxonomy)
73+
)
7774

7875

7976
class ClosedSystemObjectTag(ClosedObjectTag, SystemDefinedObjectTagMixin):
@@ -84,12 +81,11 @@ class ClosedSystemObjectTag(ClosedObjectTag, SystemDefinedObjectTagMixin):
8481
class Meta:
8582
proxy = True
8683

87-
@classmethod
88-
def valid_for(cls, taxonomy: Taxonomy = None, tag: Tag = None, **kargs):
89-
"""
90-
Returns True if the the taxonomy is system-defined
91-
"""
92-
return super().valid_for(taxonomy=taxonomy, tag=tag) and cls._validate_taxonomy(taxonomy)
84+
def _check_taxonomy(self):
85+
return (
86+
super()._check_taxonomy() and
87+
self._check_system_taxonomy(self.taxonomy)
88+
)
9389

9490

9591
class ModelObjectTag(OpenSystemObjectTag):
@@ -104,21 +100,24 @@ class Meta:
104100

105101
tag_class_model = None
106102

107-
@classmethod
108-
def valid_for(cls, taxonomy: Taxonomy = None, **kwars):
103+
104+
def _check_taxonomy(self):
109105
"""
110106
Validates if has an associated Django model that has an Id
111107
"""
112-
if not super().valid_for(taxonomy=taxonomy) or not cls.tag_class_model:
108+
if not super()._check_taxonomy():
113109
return False
114-
110+
111+
if not self.tag_class_model:
112+
return False
113+
115114
# Verify that is a Django model
116-
if not issubclass(cls.tag_class_model, models.Model):
115+
if not issubclass(self.tag_class_model, models.Model):
117116
return False
118117

119118
# Verify that the model has 'id' field
120119
try:
121-
cls.tag_class_model._meta.get_field('id')
120+
self.tag_class_model._meta.get_field('id')
122121
except FieldDoesNotExist:
123122
return False
124123

@@ -167,7 +166,7 @@ class LanguageObjectTag(ClosedSystemObjectTag):
167166
languages available in Django LANGUAGES settings var
168167
"""
169168

170-
system_defined_taxonomy_id = SystemDefinedIds.LanguageTaxonomy
169+
system_defined_taxonomy_id = SystemDefinedIds.LanguageTaxonomy.value
171170

172171
class Meta:
173172
proxy = True

tests/openedx_tagging/core/fixtures/system_defined.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@
77
required: false
88
allow_multiple: false
99
allow_free_text: false
10-
system_defined: true
10+
system_defined: true

tests/openedx_tagging/core/fixtures/tagging.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,4 +174,4 @@
174174
required: false
175175
allow_multiple: false
176176
allow_free_text: true
177-
system_defined: true
177+
system_defined: true

tests/openedx_tagging/core/tagging/test_system_defined.py

Lines changed: 61 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
""" Test the System-defined taxonomies and object tags """
22

3+
import ddt
4+
35
from django.contrib.auth import get_user_model
46
from django.db import models
57
from django.test.testcases import TestCase, override_settings
68

79
from openedx_tagging.core.tagging.system_defined_taxonomies.object_tags import (
8-
OpenSystemObjectTag,
9-
ClosedSystemObjectTag,
1010
ModelObjectTag,
1111
UserObjectTag,
1212
LanguageObjectTag,
@@ -41,7 +41,7 @@ class Meta:
4141
app_label = 'oel_tagging'
4242

4343

44-
class EmptyObjectTag(ModelObjectTag):
44+
class EmptyModelObjectTag(ModelObjectTag):
4545
"""
4646
Model ObjectTag used for testing
4747
"""
@@ -53,10 +53,8 @@ class Meta:
5353
managed = False
5454
app_label = 'oel_tagging'
5555

56-
tag_class_model = EmptyTestClass
57-
5856

59-
class EmptyModelObjectTag(ModelObjectTag):
57+
class NotDjangoModelObjectTag(ModelObjectTag):
6058
"""
6159
Model ObjectTag used for testing
6260
"""
@@ -68,12 +66,12 @@ class Meta:
6866
managed = False
6967
app_label = 'oel_tagging'
7068

71-
tag_class_model = EmptyTestModel
69+
tag_class_model = EmptyTestClass
7270

7371

74-
class TestOpenObjectTag(OpenSystemObjectTag):
72+
class NotIdModelObjectTag(ModelObjectTag):
7573
"""
76-
Open ObjectTag used for testing
74+
Model ObjectTag used for testing
7775
"""
7876

7977
system_defined_taxonomy_id = 3
@@ -83,18 +81,7 @@ class Meta:
8381
managed = False
8482
app_label = 'oel_tagging'
8583

86-
87-
class TestClosedObjectTag(ClosedSystemObjectTag):
88-
"""
89-
Closed ObjectTag used for testing
90-
"""
91-
92-
system_defined_taxonomy_id = 2
93-
94-
class Meta:
95-
proxy = True
96-
managed = False
97-
app_label = 'oel_tagging'
84+
tag_class_model = EmptyTestModel
9885

9986

10087
class TestUserObjectTag(UserObjectTag):
@@ -110,100 +97,72 @@ class Meta:
11097
app_label = 'oel_tagging'
11198

11299

100+
@ddt.ddt
113101
class TestSystemDefinedObjectTags(TestTagTaxonomyMixin, TestCase):
114102
"""
115103
Test for generic system defined object tags
116104
"""
117-
def test_open_valid_for(self):
118-
#Valid
119-
assert TestOpenObjectTag.valid_for(taxonomy=self.user_system_taxonomy)
120-
121-
# Not open system taxonomy
122-
assert not TestOpenObjectTag.valid_for(taxonomy=self.system_taxonomy)
123-
124-
# Not system taxonomy
125-
assert not TestOpenObjectTag.valid_for(taxonomy=self.taxonomy)
126-
127-
def test_closed_valid_for(self):
128-
#Valid
129-
assert TestClosedObjectTag.valid_for(taxonomy=self.system_taxonomy, tag=self.archaea)
130-
131-
# Not closed system taxonomy
132-
assert not TestClosedObjectTag.valid_for(taxonomy=self.user_system_taxonomy, tag=self.archaea)
133-
134-
# Not system taxonomy
135-
assert not TestClosedObjectTag.valid_for(taxonomy=self.taxonomy, tag=self.archaea)
136-
137-
def test_model_valid_for(self):
138-
# Without associated model
139-
assert not ModelObjectTag.valid_for(self.user_system_taxonomy)
140-
141-
# Associated class is not a Django model
142-
assert not EmptyObjectTag.valid_for(self.user_system_taxonomy)
143-
144-
# Associated model has not 'id' field
145-
assert not EmptyModelObjectTag.valid_for(self.user_system_taxonomy)
146-
147-
#Valid
148-
assert TestUserObjectTag.valid_for(self.user_system_taxonomy)
149-
150-
def test_model_is_valid(self):
151-
user = get_user_model()(
152-
username='username',
153-
email='email'
154-
)
155-
user.save()
156-
valid_object_tag = UserObjectTag(
157-
taxonomy=self.user_system_taxonomy,
158-
object_id='id 1',
159-
object_type='object',
160-
value=user.id,
161-
)
162-
invalid_object_tag_1 = UserObjectTag(
163-
taxonomy=self.user_system_taxonomy,
164-
object_id='id 2',
165-
object_type='object',
166-
value='user_id',
167-
)
168-
invalid_object_tag_2 = UserObjectTag(
169-
taxonomy=self.user_system_taxonomy,
170-
object_id='id 2',
171-
object_type='object',
172-
value='10000',
173-
)
174-
invalid_object_tag_3 = UserObjectTag(
105+
def test_system_defined_is_valid(self):
106+
# Valid
107+
assert TestUserObjectTag()._check_system_taxonomy(taxonomy=self.user_system_taxonomy)
108+
109+
# Null taxonomy
110+
assert not UserObjectTag()._check_system_taxonomy()
111+
112+
# Not system defined taxonomy
113+
assert not UserObjectTag()._check_system_taxonomy(taxonomy=self.taxonomy)
114+
115+
# Not connected with the taxonomy
116+
assert not UserObjectTag()._check_system_taxonomy(taxonomy=self.user_system_taxonomy)
117+
118+
@ddt.data(
119+
(EmptyModelObjectTag, False), # Without associated model
120+
(NotDjangoModelObjectTag, False), # Associated class is not a Django model
121+
(NotIdModelObjectTag, False), # Associated model has not 'id' field
122+
(ModelObjectTag, False), # Testing parent class validations
123+
(TestUserObjectTag, True), #Valid
124+
)
125+
@ddt.unpack
126+
def test_model_object_is_valid(self, object_tag, assert_value):
127+
args = {
128+
'taxonomy': self.user_system_taxonomy,
129+
'object_id': 'id',
130+
'object_type': 'object',
131+
'value': 'value',
132+
}
133+
result = object_tag(**args).is_valid(check_object=False, check_tag=False, check_taxonomy=True)
134+
self.assertEqual(result, assert_value)
135+
136+
@ddt.data(
137+
(None, True), # Valid
138+
('user_id', False), # Invalid user id
139+
('10000', False), # User don't exits
140+
(None, False), # Testing parent class validations
141+
)
142+
@ddt.unpack
143+
def test_user_object_is_valid(self, value, assert_value):
144+
if assert_value:
145+
user = get_user_model()(
146+
username='username',
147+
email='email'
148+
)
149+
user.save()
150+
value = user.id
151+
152+
object_tag = TestUserObjectTag(
175153
taxonomy=self.user_system_taxonomy,
176-
object_id='id 3',
154+
object_id='id',
177155
object_type='object',
156+
value=value,
178157
)
179158

180-
# Invalid user id
181-
assert not invalid_object_tag_1.is_valid(
159+
result = object_tag.is_valid(
182160
check_taxonomy=True,
183161
check_object=True,
184162
check_tag=True,
185163
)
186164

187-
# User don't exits
188-
assert not invalid_object_tag_2.is_valid(
189-
check_taxonomy=True,
190-
check_object=True,
191-
check_tag=True,
192-
)
193-
194-
# Testing parent class validations
195-
assert not invalid_object_tag_3.is_valid(
196-
check_taxonomy=True,
197-
check_object=True,
198-
check_tag=True,
199-
)
200-
201-
# Valid
202-
assert valid_object_tag.is_valid(
203-
check_taxonomy=True,
204-
check_object=True,
205-
check_tag=True,
206-
)
165+
self.assertEqual(result, assert_value)
207166

208167

209168
@override_settings(LANGUAGES=test_languages)

0 commit comments

Comments
 (0)