Remove most references to old teams config scheme (#22238)

This is a follow up from MST-16, which was commited
in 3858036a4e.

Changes:
* Enrich course teams_configuration from a plain Dict
  to a custom XBlock field that uses the new TeamsConfig
  wrapper class.
* Remove teams_conf property from course, as the previous
  change made it redundant.
* Update teams_enabled implementation.
* Remove teams_max_size field from course, which is
  no longer semantically correct, as max team size
  is now defined on a teamset level.
* Remove teams_topics in order to discourage use of raw
  teams config dict.
* Add convenience properties teamsets and teamsets_by_id
  to course.
* Allow periods and spaces in teamset IDs to avoid breaking
  existing course teams.

Some parts of the code still use the old raw config data
(identifiable by searching "cleaned_data_old_format"),
which we expect to be slowly factored away as we build
new teams features. MST-40 has been created to remove any
remaining references if necessary.

MST-18

* fix: bokchoy test

* fix: remove pdb break
This commit is contained in:
Kyle McCormick
2019-11-06 20:43:32 -05:00
committed by GitHub
parent d6099e08fd
commit 4f3262a40b
12 changed files with 203 additions and 168 deletions

View File

@@ -41,12 +41,25 @@ class TeamsConfig(object):
"""
Return developer-helpful string.
"""
return "<{} max_team_size={} teamsets=[{}]>".format(
return "<{} default_max_team_size={} teamsets=[{}]>".format(
self.__class__.__name__,
self.max_team_size,
self.default_max_team_size,
", ".join(repr(teamset) for teamset in self.teamsets),
)
def __eq__(self, other):
"""
Define equality based on cleaned data.
"""
return isinstance(other, self.__class__) and self.cleaned_data == other.cleaned_data
def __ne__(self, other):
"""
Overrides default inequality to be the inverse of our custom equality.
Safe to remove once we're in Python 3 -- Py3 does this for us.
"""
return not self.__eq__(other)
@property
def source_data(self):
"""
@@ -60,7 +73,7 @@ class TeamsConfig(object):
JSON-friendly dictionary containing cleaned data from this TeamsConfig.
"""
return {
'max_team_size': self.max_team_size,
'max_team_size': self.default_max_team_size,
'team_sets': [
teamset.cleaned_data for teamset in self.teamsets
]
@@ -72,10 +85,10 @@ class TeamsConfig(object):
JSON-friendly dictionary containing cleaned data from this TeamsConfig,
excluding newly added fields.
Here for backwards compatibility; to be removed (TODO MST-18).
Here for backwards compatibility; to be removed (TODO MST-40).
"""
return {
'max_team_size': self.max_team_size,
'max_team_size': self.default_max_team_size,
'topics': [
teamset.cleaned_data_old_format for teamset in self.teamsets
]
@@ -123,9 +136,11 @@ class TeamsConfig(object):
return {teamset.teamset_id: teamset for teamset in self.teamsets}
@cached_property
def max_team_size(self):
def default_max_team_size(self):
"""
The default maximum size for teams in this course.
Can be overriden by individual team sets; see `calc_max_team_size`.
"""
return _clean_max_team_size(self._data.get('max_team_size'))
@@ -147,7 +162,7 @@ class TeamsConfig(object):
return None
if teamset.max_team_size:
return teamset.max_team_size
return self.max_team_size
return self.default_max_team_size
class TeamsetConfig(object):
@@ -157,7 +172,7 @@ class TeamsetConfig(object):
Takes in a configuration from a JSON-friendly dictionary,
and exposes cleaned data from it.
"""
teamset_id_regex = re.compile(r'^[A-Za-z0-9_-]+$')
teamset_id_regex = re.compile(r'^[A-Za-z0-9_. -]+$')
def __init__(self, data):
"""
@@ -192,6 +207,19 @@ class TeamsetConfig(object):
),
)
def __eq__(self, other):
"""
Define equality based on cleaned data.
"""
return isinstance(other, self.__class__) and self.cleaned_data == other.cleaned_data
def __ne__(self, other):
"""
Overrides default inequality to be the inverse of our custom equality.
Safe to remove once we're in Python 3 -- Py3 does this for us.
"""
return not self.__eq__(other)
@property
def source_data(self):
"""
@@ -218,7 +246,7 @@ class TeamsetConfig(object):
JSON-friendly dictionary containing cleaned data from this TeamsConfig,
excluding newly added fields.
Here for backwards compatibility; to be removed (TODO MST-18).
Here for backwards compatibility; to be removed (TODO MST-40).
"""
return {
'id': self.teamset_id,
@@ -231,7 +259,8 @@ class TeamsetConfig(object):
"""
An identifier for this team-set.
Should be a URL-slug friendly string.
Should be a URL-slug friendly string,
but for a historical reasons may contain periods and spaces.
"""
teamset_id = _clean_string(self._data.get('id'))
if not self.teamset_id_regex.match(teamset_id):
@@ -301,11 +330,11 @@ class TeamsetType(Enum):
def _clean_string(value):
"""
Return `value` if it's a string, otherwise "".
Return `str(value)` if it's a string or int, otherwise "".
"""
if not isinstance(value, six.string_types):
return ""
return value
if isinstance(value, six.integer_types + six.string_types):
return six.text_type(value)
return ""
def _clean_max_team_size(value):

View File

@@ -91,14 +91,14 @@ class TeamsConfigTests(TestCase):
},
{
# Team-set should be dropped due to invalid ID.
"id": "Not a slug.",
"name": "Assignment about slugs",
"id": "the character & cannot be in an ID",
"name": "Assignment about ampersands",
},
{
# All fields invalid except ID;
# Team-set will exist but have all fallbacks.
"id": "horses",
"name": {"assignment", "about", "horses"},
"id": "_1. How quickly daft-jumping zebras vex",
"name": {"assignment", "about", "zebras"},
"description": object(),
"max_team_size": -1000,
"type": "matrix",
@@ -115,8 +115,8 @@ class TeamsConfigTests(TestCase):
"max_team_size": None,
"team_sets": [
{
"id": "horses",
"name": "horses",
"id": "_1. How quickly daft-jumping zebras vex",
"name": "_1. How quickly daft-jumping zebras vex",
"description": "",
"max_team_size": None,
"type": "open",
@@ -202,3 +202,11 @@ class TeamsConfigTests(TestCase):
assert '987' in config_repr
assert 'open' in config_repr
assert 'hedgehogs' in config_repr
def test_teamset_int_id(self):
"""
Assert integer teaset IDs are treated as strings,
for backwards compatibility.
"""
teamset = TeamsetConfig({"id": 5})
assert teamset.teamset_id == "5"