Skip to content
This repository has been archived by the owner on Apr 9, 2023. It is now read-only.

Commit

Permalink
Merge pull request #25 from plone/default-value
Browse files Browse the repository at this point in the history
Default value for context
  • Loading branch information
bloodbare committed Nov 23, 2016
2 parents f397597 + 97880f5 commit d08e26d
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 3 deletions.
3 changes: 3 additions & 0 deletions src/plone.server/CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
- Correctly check parent object for allowed addable types
[vangheem]

- Get default values from schema when attribute on object is not set
[bloodbare]


1.0a6 (2016-11-21)
------------------
Expand Down
45 changes: 45 additions & 0 deletions src/plone.server/plone/server/content.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from copy import deepcopy
from BTrees.Length import Length
from BTrees.OOBTree import OOBTree
from datetime import datetime
Expand Down Expand Up @@ -27,6 +28,7 @@
from plone.server.transactions import get_current_request
from plone.server.transactions import synccontext
from plone.server.utils import Lazy
from zope.schema.interfaces import IContextAwareDefaultFactory
from zope.annotation.interfaces import IAttributeAnnotatable
from zope.component import adapter
from zope.component import getUtility
Expand All @@ -46,6 +48,7 @@


_zone = tzlocal()
_marker = object()


@implementer(IResourceFactory)
Expand Down Expand Up @@ -219,6 +222,24 @@ def enumerateBehaviors(self):
yield behavior


def _default_from_schema(context, schema, fieldname):
"""helper to lookup default value of a field
"""
if schema is None:
return _marker
field = schema.get(fieldname, None)
if field is None:
return _marker
if IContextAwareDefaultFactory.providedBy(
getattr(field, 'defaultFactory', None)
):
bound = field.bind(context)
return deepcopy(bound.default)
else:
return deepcopy(field.default)
return _marker


@implementer(IResource, IAttributeAnnotatable)
class Resource(Persistent):

Expand All @@ -243,6 +264,30 @@ def __repr__(self):
path=path,
mem=id(self))

def __getattr__(self, name):
# python basics: __getattr__ is only invoked if the attribute wasn't
# found by __getattribute__
#
# optimization: sometimes we're asked for special attributes
# such as __conform__ that we can disregard (because we
# wouldn't be in here if the class had such an attribute
# defined).
# also handle special dynamic providedBy cache here.
# also handle the get_current_request call
if name.startswith('__') or name == '_v__providedBy__' or name == 'request':
raise AttributeError(name)

# attribute was not found; try to look it up in the schema and return
# a default
value = _default_from_schema(
self,
SCHEMA_CACHE.get(self.portal_type).get('schema'),
name
)
if value is not _marker:
return value
raise AttributeError(name)


@implementer(IItem)
class Item(Resource):
Expand Down
23 changes: 20 additions & 3 deletions src/plone.server/plone/server/json/deserialize_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
from plone.server.interfaces import WRITE_PERMISSIONS_KEY
from plone.server.interfaces import IResource
from plone.server.content import iterSchemata
from zope.interface.exceptions import Invalid
from zope.interface.interfaces import IMethod
from zope.schema.interfaces import IField
from zope.schema.interfaces import SchemaNotFullyImplemented
from plone.server.json.interfaces import IResourceDeserializeFromJson
from plone.server.json.exceptions import DeserializationError
from plone.server.json.interfaces import IResourceFieldDeserializer
Expand All @@ -15,7 +19,6 @@
from zope.interface import implementer
from zope.lifecycleevent import ObjectModifiedEvent
from zope.schema import getFields
from zope.schema import getValidationErrors
from zope.schema.interfaces import ValidationError
from zope.security.interfaces import IPermission
from zope.security import checkPermission
Expand Down Expand Up @@ -70,6 +73,7 @@ def set_schema(
else:
data_value = data[name] if name in data else None

f = schema.get(name)
if data_value is not None:

if not self.check_permission(write_permissions.get(name)):
Expand All @@ -91,16 +95,27 @@ def set_schema(
errors.append({
'message': e.doc(), 'field': name, 'error': e})
else:
f = schema.get(name)
try:
f.validate(value)
except ValidationError as e:
errors.append({
'message': e.doc(), 'field': name, 'error': e})
else:
setattr(obj, name, value)
else:
if f.required and not hasattr(obj, name):
errors.append({
'message': 'Required parameter', 'field': name,
'error': ValueError('Required parameter')})

if validate_all:
validation = getValidationErrors(schema, schema(self.context))
invariant_errors = []
try:
schema.validateInvariants(object, invariant_errors)
except Invalid:
# Just collect errors
pass
validation = [(None, e) for e in invariant_errors]

if len(validation):
for e in validation:
Expand All @@ -123,3 +138,5 @@ def check_permission(self, permission_name):
self.permission_cache[permission_name] = bool(
checkPermission(permission.title, self.context))
return self.permission_cache[permission_name]


0 comments on commit d08e26d

Please sign in to comment.