Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Monkey-patch FieldProperty so we can avoid double-validation.
Fixes #67 Add tests that this doesn't break anything. In our simple tests, this makes us at least 10% faster. 2.7: | Benchmark | 27_list_fieldproperty3 | 27_list_fieldproperty_patched3 | |------------------------------|------------------------|--------------------------------| | __main__: fromExternalObject | 1.43 ms | 1.27 ms: 1.12x faster (-11%) | Not significant (1): __main__: toExternalObject 3.6 (taken during a backup, results for toExternalObject had a *huge* stddev of 40%): | Benchmark | 36_list_fieldproperty | 36_list_fieldproperty_patched2 | |------------------------------|-----------------------|--------------------------------| | __main__: toExternalObject | 428 us | 577 us: 1.35x slower (+35%) | | __main__: fromExternalObject | 1.43 ms | 1.19 ms: 1.20x faster (-17%) |
- Loading branch information
Showing
4 changed files
with
157 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
95 changes: 95 additions & 0 deletions
95
src/nti/externalization/internalization/tests/test_fields.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
# -*- coding: utf-8 -*- | ||
from __future__ import absolute_import | ||
from __future__ import division | ||
from __future__ import print_function | ||
|
||
import unittest | ||
|
||
from zope import interface | ||
from zope.component import eventtesting | ||
|
||
|
||
from zope.schema.interfaces import IBeforeObjectAssignedEvent | ||
from zope.schema.interfaces import IFieldUpdatedEvent | ||
from zope.schema.interfaces import SchemaNotProvided | ||
from zope.schema import Object | ||
from zope.schema.fieldproperty import createFieldProperties | ||
|
||
from zope.testing.cleanup import CleanUp | ||
|
||
from hamcrest import assert_that | ||
from hamcrest import has_length | ||
from hamcrest import has_property as has_attr | ||
from hamcrest import is_ | ||
from hamcrest import same_instance | ||
|
||
from nti.externalization.internalization.fields import validate_named_field_value | ||
|
||
# pylint:disable=inherit-non-class | ||
|
||
class IThing(interface.Interface): | ||
pass | ||
|
||
class IBar(interface.Interface): | ||
|
||
thing = Object(IThing) | ||
|
||
@interface.implementer(IThing) | ||
class Thing(object): | ||
pass | ||
|
||
@interface.implementer(IBar) | ||
class Bar(object): | ||
createFieldProperties(IBar) | ||
|
||
class TestValidateFieldValueEvents(CleanUp, | ||
unittest.TestCase): | ||
|
||
def setUp(self): | ||
eventtesting.setUp() | ||
|
||
|
||
def test_before_object_assigned_event_fired_valid_value(self): | ||
|
||
thing = Thing() | ||
root = Bar() | ||
|
||
validate_named_field_value(root, IBar, 'thing', thing)() | ||
|
||
events = eventtesting.getEvents(IBeforeObjectAssignedEvent) | ||
assert_that(events, has_length(1)) | ||
assert_that(events[0], has_attr('object', is_(same_instance(thing)))) | ||
|
||
events = eventtesting.getEvents(IFieldUpdatedEvent) | ||
assert_that(events, has_length(1)) | ||
|
||
|
||
def test_before_object_assigned_event_fired_invalid_value_fixed(self): | ||
thing = Thing() | ||
root = Bar() | ||
|
||
class NotThing(object): | ||
def __conform__(self, iface): | ||
return thing if iface is IThing else None | ||
|
||
|
||
validate_named_field_value(root, IBar, 'thing', NotThing())() | ||
|
||
events = eventtesting.getEvents(IBeforeObjectAssignedEvent) | ||
assert_that(events, has_length(1)) | ||
assert_that(events[0], has_attr('object', is_(same_instance(thing)))) | ||
|
||
events = eventtesting.getEvents(IFieldUpdatedEvent) | ||
assert_that(events, has_length(1)) | ||
|
||
|
||
def test_before_object_assigned_event_not_fired_invalid_value(self): | ||
|
||
with self.assertRaises(SchemaNotProvided): | ||
validate_named_field_value(Bar(), IBar, 'thing', object()) | ||
|
||
events = eventtesting.getEvents(IBeforeObjectAssignedEvent) | ||
assert_that(events, has_length(0)) | ||
|
||
events = eventtesting.getEvents(IFieldUpdatedEvent) | ||
assert_that(events, has_length(0)) |