Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add setitem, delitem to Field #290

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion deform/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,47 @@ def __contains__(self, name):
return True
return False

def __setitem__(self, name, new_child):
""" Set a field directly by name, this will replace a field if it exists
or add it to the end of the children if it doesn't. """
new_child = new_child.clone()
new_child._parent = weakref.ref(self)
new_child.name = name

found = False
new_children = []

for child in self.children:
if child.name == new_child.name:
new_children.append(new_child)
new_child.order = child.order
new_child.oid = 'deformField%s' % child.order
found = True
else:
new_children.append(child)

if not found:
new_children.append(new_child)
new_child.order = next(self.counter)
new_child.oid = 'deformField%s' % new_child.order

self.children = new_children

def __delitem__(self, name):
""" Removes a field by name, raises KeyError if field doesn't exist """
new_children = []
found = False
for child in self.children:
if child.name == name:
found = True
continue
new_children.append(child)

if not found:
raise KeyError(name)

self.children = new_children

def clone(self):
""" Clone the field and its subfields, retaining attribute
information. Return the cloned field. The ``order``
Expand Down Expand Up @@ -319,7 +360,7 @@ def widget(self):
def _default_item_css_class(self):
if not self.name:
return None

css_class = unicodedata.normalize('NFKD', compat.text_type(self.name)).encode('ascii', 'ignore').decode('ascii')
css_class = re.sub('[^\w\s-]', '', css_class).strip().lower()
css_class = re.sub('[-\s]+', '-', css_class)
Expand Down
65 changes: 55 additions & 10 deletions deform/tests/test_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class TestField(unittest.TestCase):
def _getTargetClass(self):
from deform.field import Field
return Field

def _makeOne(self, schema, **kw):
cls = self._getTargetClass()
return cls(schema, **kw)
Expand Down Expand Up @@ -45,7 +45,7 @@ def test_ctor_with_children_in_schema(self):
grandchild = DummySchema(name='grandchild')
child = DummySchema(children=[grandchild], name='child')
root = DummySchema(children=[child], name='root')

root_field = self._makeOne(root, renderer='abc')
self.assertEqual(len(root_field.children), 1)
self.assertEqual(root_field.parent, None)
Expand All @@ -70,7 +70,7 @@ def test_get_root(self):
grandchild_field = field.children[0].children[0]
root = grandchild_field.get_root()
self.assertEqual(root.name, 'root')

def test_ctor_with_resource_registry(self):
from deform.field import Field
schema = DummySchema()
Expand Down Expand Up @@ -183,7 +183,7 @@ def test_normalizes_css_class(self):
def test_widget_no_maker_with_default_widget_maker(self):
from deform.widget import MappingWidget
from colander import Mapping
schema = DummySchema()
schema = DummySchema()
schema.typ = Mapping()
field = self._makeOne(schema)
widget = field.widget
Expand All @@ -196,7 +196,7 @@ def test_widget_no_maker_with_derived_from_default_field(self):
class CustomSequence(Sequence):
pass

schema = DummySchema()
schema = DummySchema()
schema.typ = CustomSequence()
field = self._makeOne(schema)
widget = field.widget
Expand Down Expand Up @@ -352,7 +352,7 @@ def test___getitem__success(self):
child = DummyField()
field.children = [child]
self.assertEqual(field['name'], child)

def test___getitem__fail(self):
schema = DummySchema()
field = self._makeOne(schema)
Expand All @@ -366,7 +366,51 @@ def test___contains__success(self):
child = DummyField()
field.children = [child]
self.assertTrue('name' in field)


def test___contains__fail(self):
schema = DummySchema()
field = self._makeOne(schema)
child = DummyField()
field.children = [child]
self.assertFalse('nope' in field)

def test___setitem__empty(self):
schema = DummySchema()
field = self._makeOne(schema)
child = DummyField()
field['name'] = child
self.assertEqual(field['name'], child)
field['name'] = child # should only set it once
self.assertEqual(field.children, [child])

def test___setitem__existing(self):
schema = DummySchema()
field = self._makeOne(schema)
child1 = DummyField(name='child1')
child2 = DummyField(name='child2')
field.children = [child1, child2]
replacer = DummyField(name='replacer')
field['child1'] = replacer
self.assertEqual(field['child1'], replacer)

def test___delitem__existing(self):
schema = DummySchema()
field = self._makeOne(schema)
child1 = DummyField(name='child1')
child2 = DummyField(name='child2')
field.children = [child1, child2]
del(field['child1'])
self.assertEqual(field.children, [child2])
del(field['child2'])
self.assertEqual(field.children, [])

def test___delitem__missing(self):
schema = DummySchema()
field = self._makeOne(schema)
child = DummyField()
field.children = [child]
self.assertRaises(KeyError, field.__delitem__, 'nope')

def test___contains__fail(self):
schema = DummySchema()
field = self._makeOne(schema)
Expand All @@ -378,7 +422,7 @@ def test_errormsg_error_None(self):
schema = DummySchema()
field = self._makeOne(schema)
self.assertEqual(field.errormsg, None)

def test_errormsg_error_not_None(self):
schema = DummySchema()
field = self._makeOne(schema)
Expand Down Expand Up @@ -581,7 +625,7 @@ def test_start_mapping_withname(self):
result,
'<input type="hidden" name="__start__" value="foo:mapping"/>'
)

def test_start_mapping_withoutname(self):
schema = DummySchema()
field = self._makeOne(schema)
Expand Down Expand Up @@ -688,6 +732,7 @@ def __init__(self, schema=None, renderer=None, name='name'):
self.schema = schema
self.renderer = renderer
self.name = name
self.order = 1

def clone(self):
self.cloned = True
Expand Down Expand Up @@ -727,7 +772,7 @@ def cstruct_children(self, cstruct):
class DummyType(object):
def __init__(self, maker=None):
self.widget_maker = maker

class DummyWidget(object):
rendered = None
def __init__(self, exc=None, **kw):
Expand Down