from ..auditor import (
    AuditFailure,
    audit_checker,
)
from ..embedding import embed
from ..schema_utils import validate


@audit_checker('item', frame='object')
def audit_item_schema(value, system):
    context = system['context']
    registry = system['registry']
    if not context.schema:
        return

    properties = context.properties.copy()
    current_version = properties.get('schema_version', '')
    target_version = context.schema_version
    if target_version is not None and current_version != target_version:
        migrator = registry['migrator']
        try:
            properties = migrator.upgrade(
                context.item_type, properties, current_version, target_version,
                finalize=False, context=context, registry=registry)
        except RuntimeError:
            raise
        except Exception as e:
            detail = '%r upgrading from %r to %r' % (e, current_version, target_version)
            yield AuditFailure('upgrade failure', detail, level='ERROR')
            return

        properties['schema_version'] = target_version

    properties['uuid'] = str(context.uuid)
    validated, errors = validate(context.schema, properties, properties)
    for error in errors:
        category = 'validation error'
        path = list(error.path)
        if path:
            category += ': ' + '/'.join(path)
        yield AuditFailure(category, error.message, level='ERROR')


STATUS_LEVEL = {
    # standard_status
    'released': 100,
    'deleted': 0,
    'replaced': 0,

    # shared_status
    'current': 100,
    'disabled': 0,

    # file
    'obsolete': 50,

    # antibody_characterization
    'compliant': 100,
    'not compliant': 100,
    'not reviewed': 100,
    'not submitted for review by lab': 100,

    # antibody_lot
    'eligible for new data': 100,
    'not eligible for new data': 100,
    'not pursued': 100,

    # dataset / experiment
    'release ready': 50,
    'revoked': 100,

    # publication
    'published': 100,
}


def aslist(value):
    if isinstance(value, basestring):
        return [value]
    return value


@audit_checker('item', frame='object')
def audit_item_status(value, system):
    if 'status' not in value:
        return

    level = STATUS_LEVEL.get(value['status'], 50)
    if level == 0:
        return

    context = system['context']
    request = system['request']
    linked = set()
    for key in context.schema_links:
        linked.update(aslist(value.get(key, ())))

    for path in linked:
        linked_value = embed(request, path + '@@object')
        if 'status' not in linked_value:
            continue
        linked_level = STATUS_LEVEL.get(linked_value['status'], 50)
        if linked_level == 0:
            detail = '{} {} has {} subobject {}'.format(
                value['status'], value['@id'], linked_value['status'], linked_value['@id'])
            yield AuditFailure('status mismatch', detail, level='ERROR')
        if linked_level < level:
            detail = '{} {} has {} subobject {}'.format(
                value['status'], value['@id'], linked_value['status'], linked_value['@id'])
            yield AuditFailure('status mismatch', detail, level='DCC_ACTION')

@@ -997,37 +997,42 @@
  detail, level='
-ERROR
+DCC_ACTION
 ')%0A            r
@@ -1363,24 +1363,110 @@
 .join(path)%0A
+        detail = 'Object %7B%7D has schema error %7B%7D'.format(value%5B'uuid'%5D, error.message)%0A
         yiel
@@ -1494,35 +1494,33 @@
 ry, 
-error.message, level='ERROR
+detail, level='DCC_ACTION
 ')%0A%0A

Update item.py