Exemplo n.º 1
0
    def __new__(cls, context, request, view, manager):
        chain = _get_context_chain(context)
        chain.pop()  # bungeni_app
        top_section = chain.pop()

        if not chain:
            return

        # we require the tree to begin with a container object
        if not IReadContainer.providedBy(chain[-1]):
            return

        # remove any views from navigation tree
        if not (IAlchemistContent.providedBy(chain[0])
                or IAlchemistContainer.providedBy(chain[0])
                or ISection.providedBy(chain[0])):
            chain.pop(0)

        subcontext = chain[-1]
        if (len(chain) > 1 or IReadContainer.providedBy(subcontext)
                and not IAlchemistContainer.providedBy(subcontext)
                and len(subcontext)):
            inst = object.__new__(cls, context, request, view, manager)
            inst.chain = chain
            inst.top_section_url = url.absoluteURL(top_section, request)
            inst.id_prefix = "nav"
            return inst
Exemplo n.º 2
0
 def __new__(cls, context, request, view, manager):
     chain = _get_context_chain(context)
     chain.pop() # bungeni_app
     top_section = chain.pop()
     
     if not chain:
         return
     
     # we require the tree to begin with a container object
     if not IReadContainer.providedBy(chain[-1]):
         return
     
     # remove any views from navigation tree
     if not(IAlchemistContent.providedBy(chain[0]) or 
             IAlchemistContainer.providedBy(chain[0]) or
             ISection.providedBy(chain[0])
         ):
         chain.pop(0)
     
     subcontext = chain[-1]
     if (len(chain) > 1 or
             IReadContainer.providedBy(subcontext) and 
             not IAlchemistContainer.providedBy(subcontext) and 
             len(subcontext)
         ):
         inst = object.__new__(cls, context, request, view, manager)
         inst.chain = chain
         inst.top_section_url = url.absoluteURL(top_section, request)
         inst.id_prefix = "nav"
         return inst
Exemplo n.º 3
0
 def add_container_menu_items(self, context, container):
     request = self.request
     
     _url = url.absoluteURL(container, request)
     
     if IReadContainer.providedBy(container):
         #XXX should be the same in all containers ?
         container=proxy.removeSecurityProxy(container)
         for name, item in container.items():
             if context is None:
                 selected = False
             else:
                 selected = url.same_path_names(context.__name__, name)
             item = proxy.removeSecurityProxy(item)
             if IDCDescriptiveProperties.providedBy(item):
                 title = item.title
             else:
                 props = IDCDescriptiveProperties(item)
                 title = props.title
             # only items with valid title
             if title is not None:
                 self.items.append(url.get_menu_item_descriptor(
                         title, selected, _url, name))
     default_view_name = queryDefaultViewName(container, self.request)
     default_view = component.queryMultiAdapter(
         (container, self.request), name=default_view_name)
     if hasattr(default_view, "title") and default_view.title is not None:
         self.items.insert(0, url.get_menu_item_descriptor(
                 default_view.title, 
                 sameProxiedObjects(container, self.context), 
                 _url))
Exemplo n.º 4
0
 def subItems(self):
     """Collect all tree items for the given context."""
     items = []
     keys = []
     append = items.append
     if IReadContainer.providedBy(self.context):
         try:
             keys = list(self.context.keys())
         except(Unauthorized, Forbidden):
             return items
     else:
         return items
     counter = 1
     for name in keys:
         # Only include items we can traverse to
         subItem = api.traverse(self.context, name, None)
         if subItem is not None:
             append((api.getName(subItem), subItem,
                 self._hasSubItems(subItem)))
         counter += 1
         if counter == self.maxItems:
             # add context which should support a item listing view with 
             # batch
             lenght = len(keys) - self.maxItems
             default = '[%s more items...]' % lenght
             name = zope.i18n.translate(
                 _('[${lenght} more items...]', mapping={'lenght':lenght}),
                 context=self.request, default=default)
             append((name, self.context, False))
             break
     return items
Exemplo n.º 5
0
    def publishTraverse(self, request, name):
        subob = self.traverse(name)
        if subob is not None:
            return safely_locate_maybe(subob, self.context, name)

        traversable_dict = traversable.bind().get(self.context)
        if traversable_dict:
            if name in traversable_dict:
                subob = getattr(self.context, traversable_dict[name])
                if callable(subob):
                    subob = subob()
                return safely_locate_maybe(subob, self.context, name)

        # XXX Special logic here to deal with containers.  It would be
        # good if we wouldn't have to do this here. One solution is to
        # rip this out and make you subclass ContainerTraverser if you
        # wanted to override the traversal behaviour of containers.
        if IReadContainer.providedBy(self.context):
            item = self.context.get(name)
            if item is not None:
                return item

        view = component.queryMultiAdapter((self.context, request), name=name)
        if view is not None:
            return view

        raise NotFound(self.context, name, request)
Exemplo n.º 6
0
    def add_container_menu_items(self, context, container):
        request = self.request

        _url = url.absoluteURL(container, request)

        if IReadContainer.providedBy(container):
            #XXX should be the same in all containers ?
            container = proxy.removeSecurityProxy(container)
            for name, item in container.items():
                if context is None:
                    selected = False
                else:
                    selected = url.same_path_names(context.__name__, name)
                item = proxy.removeSecurityProxy(item)
                if IDCDescriptiveProperties.providedBy(item):
                    title = item.title
                else:
                    props = IDCDescriptiveProperties(item)
                    title = props.title
                # only items with valid title
                if title is not None:
                    self.items.append(
                        url.get_menu_item_descriptor(title, selected, _url,
                                                     name))
        default_view_name = queryDefaultViewName(container, self.request)
        default_view = component.queryMultiAdapter((container, self.request),
                                                   name=default_view_name)
        if hasattr(default_view, "title") and default_view.title is not None:
            self.items.insert(
                0,
                url.get_menu_item_descriptor(
                    default_view.title,
                    sameProxiedObjects(container, self.context), _url))
Exemplo n.º 7
0
 def update(self):
     request = self.request
     context = self.context
     chain = _get_context_chain(context)
     length = len(chain)
     self.items = []
     if length < 2:
         # there must be at least: [top-level section, application]
         return # container is None
     else:
         # the penultimate context is the top-level container
         container = chain[-2]
         assert container.__name__ is not None
         if not IReadContainer.providedBy(container):
             return # container has no readable content
     assert container is not None
     
     # add container items
     if length > 2:
         context = chain[-3]
     else:
         context = None
     self.add_container_menu_items(context, container)
     # add any menu items from zcml
     self.add_zcml_menu_items(container)
Exemplo n.º 8
0
    def children_xmldoc(self):
        # If you need custom filter then reimplement this method.
        # Otherwise this implementation is generic and it is correct
        # for standard cases.
        try:
            rc = IReadContainer(self.context)
        except TypeError:
            return XMLDOC % u''
        except Unauthorized:
            return XMLDOC % u''

        specs = [queryMultiAdapter((value, self.request), IXML)
                for value in rc.values()]
        specs = filter(lambda x:x, specs)
        specs.sort(key = lambda x: x.sort_key())
        nodes = [x.to_xml() for x in specs]
        return XMLDOC % u'\n'.join(nodes)
Exemplo n.º 9
0
 def getLengthOf(self, item):
     res = -1
     if IReadContainer.providedBy(item):
         try:
             res = len(item)
         except (Unauthorized, Forbidden):
             pass
     return res
Exemplo n.º 10
0
    def __new__(cls, context, request, view, manager):
        # we have both primary and secondary navigation, so we won't
        # show the navigation tree unless we're at a depth > 2
        chain = _get_context_chain(context)[:-2]
        if not chain:
            return

        # we require the tree to begin with a container object
        if not IReadContainer.providedBy(chain[-1]):
            return

        subcontext = chain[-1]
        if (len(chain) > 1 or
            IReadContainer.providedBy(subcontext) and not
            IAlchemistContainer.providedBy(subcontext) and len(subcontext)):
            inst = object.__new__(cls, context, request, view, manager)
            inst.chain = chain
            return inst
Exemplo n.º 11
0
 def singleBranchTree(self, root=''):
     parent = getParent(self.context)
     while parent is not None:
             if IReadContainer.providedBy(parent):
                 view = queryMultiAdapter(
                     (parent, self.request), name='singleBranchTree.xml')
                 return view()
             else:
                 parent = getParent(parent)
Exemplo n.º 12
0
    def children_xmldoc(self):
        # If you need custom filter then reimplement this method.
        # Otherwise this implementation is generic and it is correct
        # for standard cases.
        try:
            rc = IReadContainer(self.context)
        except TypeError:
            return XMLDOC % u''
        except Unauthorized:
            return XMLDOC % u''

        specs = [
            queryMultiAdapter((value, self.request), IXML)
            for value in rc.values()
        ]
        specs = filter(lambda x: x, specs)
        specs.sort(key=lambda x: x.sort_key())
        nodes = [x.to_xml() for x in specs]
        return XMLDOC % u'\n'.join(nodes)
Exemplo n.º 13
0
def getObjectURL(ob, req):
    """Return the URL for the object `ob`.

    If the object is a container and the url doesn't end in slash '/' then
    append a slash to the url.
    """
    url = zope.component.getMultiAdapter((ob, req), IAbsoluteURL)()
    if IReadContainer.providedBy(ob) and url[-1] != "/":
        url += "/"

    return url
Exemplo n.º 14
0
 def _hasSubItems(self, item):
     """This method allows us to decide if a sub item has items from the 
     point of view of the context."""
     res = False
     if IReadContainer.providedBy(item):
         try:
             if len(item) > 0:
                 res = True
         except(Unauthorized, Forbidden):
             pass
     return res
Exemplo n.º 15
0
    def add_container_menu_items(self, context, container):
        request = self.request
        # add a menu item for each user workspace, if we are in an
        # IWorkspaceSectionLayer
        # !+ if user is logged in or if request.layer_data
        if interfaces.IWorkspaceSectionLayer.providedBy(request):
            try:
                workspaces = IAnnotations(request)["layer_data"].get(
                    "workspaces")
            except:
                workspaces = []
            log.info("%s got user workspaces: %s" % (self, workspaces))
            base_url_path = "/workspace"
            for workspace in workspaces:
                log.info("appending menu item for user workspace: %s" %
                         str(workspace))
                self.items.append(
                    url.get_menu_item_descriptor(
                        workspace.full_name,
                        pos_action_in_url(
                            "/workspace/obj-%s" % workspace.group_id,
                            request.getURL()), base_url_path,
                        "obj-%s" % workspace.group_id))

        _url = url.absoluteURL(container, request)

        if IReadContainer.providedBy(container):
            #XXX should be the same in all containers ?
            container = proxy.removeSecurityProxy(container)
            for name, item in container.items():
                if context is None:
                    selected = False
                else:
                    selected = url.same_path_names(context.__name__, name)
                item = proxy.removeSecurityProxy(item)
                if IDCDescriptiveProperties.providedBy(item):
                    title = item.title
                else:
                    props = IDCDescriptiveProperties(item)
                    title = props.title
                # only items with valid title
                if title is not None:
                    self.items.append(
                        url.get_menu_item_descriptor(title, selected, _url,
                                                     name))
        default_view_name = queryDefaultViewName(container, self.request)
        default_view = component.queryMultiAdapter((container, self.request),
                                                   name=default_view_name)
        if hasattr(default_view, "title") and default_view.title is not None:
            self.items.insert(
                0,
                url.get_menu_item_descriptor(
                    default_view.title,
                    sameProxiedObjects(container, self.context), _url))
Exemplo n.º 16
0
    def children_xmldoc(self):
        try:
            rc = IReadContainer(self.context)
        except TypeError:
            return XMLDOC % u''
        except Unauthorized:
            return XMLDOC % u''

        specs = [queryMultiAdapter((value, self.request), IXML)
                for value in rc.values()]
        specs = filter(lambda x:x, specs)
        specs.sort(key = lambda x: x.sort_key())

        nodes = [x.to_xml() for x in specs]

        # add ++etc++site
        sm = self.context.getSiteManager()
        sm_spec = queryMultiAdapter((sm, self.request), IXML)
        nodes.append(sm_spec.to_xml())

        return XMLDOC % u'\n'.join(nodes)
Exemplo n.º 17
0
def _search_helper(id, obj, container, id_filters, object_filters, result):
    # check id filters if we get a match then return immediately
    for id_filter in id_filters:
        if id_filter.matches(id):
            result.append(obj)
            return

    # now check all object filters
    for object_filter in object_filters:
        if object_filter.matches(obj):
            result.append(obj)
            return

    # do we need to check sub containers?
    if not IReadContainer.providedBy(obj):
        return

    for key, value in obj.items():
        _search_helper(key, value, obj, id_filters, object_filters, result)
Exemplo n.º 18
0
 def expand(self, chain, include_siblings=True):
     if len(chain) == 0:
         return ()
     context = chain.pop()
     items = []
     if IApplication.providedBy(context):
         items.extend(self.expand(chain))
     elif IAlchemistContent.providedBy(context):
         _url = url.absoluteURL(context, self.request)
         selected = len(chain) == 0
         
         if chain:
             nodes = self.expand(chain)
         else:
             containers = utils.get_managed_containers(context)
             nodes = []
             self.expand_containers(nodes, containers, _url, chain, None)
         
         items.append({
                 "id": self.get_nav_entry_id(_url),
                 "label": IDCDescriptiveProperties(context).title,
                 "url": _url,
                 "current": True,
                 "selected": selected,
                 "kind": "content",
                 "nodes": nodes,
             })
     elif IAlchemistContainer.providedBy(context):
         # loop through all managed containers of the parent
         # object, and include the present container as the
         # "current" node.
         parent = context.__parent__
         assert parent is not None
         _url = url.absoluteURL(parent, self.request)
         
         # append managed containers as child nodes            
         if include_siblings is True:
             if IApplication.providedBy(parent):
                 containers = [ (name, parent[name])
                     for name in 
                         location.model_to_container_name_mapping.values()
                     if name in parent ]
             elif IReadContainer.providedBy(parent):
                 containers = list(parent.items())
             else:
                 containers = utils.get_managed_containers(parent)
         else:
             containers = [(context.__name__, context)]
         self.expand_containers(items, containers, _url, chain, context)
     elif ILocation.providedBy(context):
         # e.g. bungeni.core.content.Section, DisplayForm
         _url = url.absoluteURL(context, self.request)
         selected = len(chain) == 0
         if selected and IReadContainer.providedBy(context):
             nodes = []
             try:
                 self.expand_containers(
                     nodes, context.items(), _url, chain, context)
             except:
                 pass
         else:
             nodes = self.expand(chain)
         _title = getattr(context, "title", None) or \
             getattr(context, "page_title", "!+BungeniBrowserView.title")
         items.append({
                 "id": self.get_nav_entry_id(_url),
                 # !+BungeniBrowserView.title
                 "label": _title, #IDCDescriptiveProperties(context).title,
                 "url": _url,
                 "current": True,
                 "selected": selected,
                 "kind": "location",
                 "nodes": nodes,
             })
     elif IReadContainer.providedBy(context):
         #!+NavigationTreeViewlet-EXPAND-IReadContainer(mr, oct-2012) does this ever execute?!
         raise Exception("!+NavigationTreeViewlet-EXPAND-IReadContainer [%s]" % context)
         items.extend(self.expand(chain))
     return items
Exemplo n.º 19
0
    def singleBranchTree(self, root=''):
        """Return an XML document with the siblings and parents of an object.

        There is only one branch expanded, in other words, the tree is
        filled with the object, its siblings and its parents with
        their respective siblings.

        """
        result = 'selected'
        oldItem = self.context

        vh = self.request.getVirtualHostRoot()
        if vh:
            vhrootView = getMultiAdapter(
                    (vh, self.request), name='absolute_url')
            baseURL = vhrootView() + '/'
            try:
                rootName = '[' + vh.__name__ + ']'
            except:
                # we got the containment root itself as the virtual host
                # and there is no name.
                rootName = _('[top]')
            parents = getParentsFromContextToObject(self.context, vh)
        else:
            rootName = _('[top]')
            baseURL = self.request.getApplicationURL() + '/'
            parents = getParents(self.context)

        rootName = translate(rootName, context=self.request, default=rootName)

        for item in parents:
            # skip skin if present
            #if item == oldItem:
            #        continue
            subItems = []
            if IReadContainer.providedBy(item):
                keys = list(item.keys())
                if len(keys) >= 1000:
                    keys = []
            else:
                keys = []

            # include the site manager
            keys.append(u'++etc++site')

            for name in keys:
                # Only include items we can traverse to
                subItem = traverse(item, name, None)
                iconUrl = self.getIconUrl(subItem)
                subitem_len = self.getLengthOf(subItem)
                if subitem_len >= 0:
                    # the test below seems to be broken
                    # with the ++etc++site case
                    if subItem == oldItem:
                        subItems.append(xmlEscapeWithCData(
                            u'<collection name=%s length=%s '
                            u'icon_url=%s>%s</collection>', 
                            name, subitem_len, iconUrl, result))
                    else:
                        subItems.append(xmlEscape(
                            u'<collection name=%s length=%s '
                            u'icon_url=%s/>',
                            name, subitem_len, iconUrl))
                else:
                    subItems.append(xmlEscape(
                        u'<item name=%s icon_url=%s />', name, iconUrl))

            result = u' '.join(subItems)
            oldItem = item

        # do not forget root folder
        iconUrl = self.getIconUrl(oldItem)
        result = xmlEscapeWithCData(
                  u'<collection name=%s baseURL=%s length=%s '
                  u'icon_url=%s isroot="">%s</collection>',
                  rootName, baseURL, len(oldItem), iconUrl, result)

        self.request.response.setHeader('Content-Type', 'text/xml')
        setNoCacheHeaders(self.request.response)
        title = translate(titleTemplate,
                          context=self.request, default=titleTemplate)
        loading = translate(loadingMsg,
                          context=self.request, default=loadingMsg)
        return xmlEscapeWithCData(
                u'<?xml version="1.0" ?>'
                u'<children title_tpl=%s loading_msg=%s>%s</children>',
                title, loading, result)
Exemplo n.º 20
0
 def is_container(self):
     # I recommend reimplement this and return IS_CONTAINER
     # or empty string directly
     return IReadContainer.providedBy(self.context) or u''
Exemplo n.º 21
0
    def expand(self, chain, include_siblings=True):
        if len(chain) == 0:
            return ()

        context = chain.pop()
        items = []

        if IApplication.providedBy(context):
            items.extend(self.expand(chain))

        elif IAlchemistContent.providedBy(context):
            _url = url.absoluteURL(context, self.request)
            if IDCDescriptiveProperties.providedBy(context):
                title = context.title
            else:
                props = IDCDescriptiveProperties(context, None)
                if props is not None:
                    title = props.title
                else:
                    title = context.short_name

            selected = len(chain) == 0
            
            if chain:
                nodes = self.expand(chain)
            else:
                kls = context.__class__
                containers = [
                    (key, getattr(context, key))
                    for key, value in kls.__dict__.items()
                    if isinstance(value, ManagedContainerDescriptor)]
                nodes = []
                self.expand_containers(nodes, containers, _url, chain, None)

            items.append(
                {'title': title,
                 'url': _url,
                 'current': True,
                 'selected': selected,
                 'kind': 'content',
                 'nodes': nodes,
                 })

        elif IAlchemistContainer.providedBy(context):
            # loop through all managed containers of the parent
            # object, and include the present container as the
            # 'current' node.
            parent = context.__parent__
            assert parent is not None
            _url = url.absoluteURL(parent, self.request)

            # append managed containers as child nodes
            kls = type(proxy.removeSecurityProxy(parent))

            if include_siblings is True:
                if IApplication.providedBy(parent):
                    containers = [
                        (name, parent[name])
                        for name in 
                            location.model_to_container_name_mapping.values()
                        if name in parent
                    ]
                elif IReadContainer.providedBy(parent):
                    containers = list(parent.items())
                else:
                    containers = [
                        (key, getattr(parent, key))
                        for key, value in kls.__dict__.items()
                        if isinstance(value, ManagedContainerDescriptor)]
            else:
                containers = [(context.__name__, context)]
                
            self.expand_containers(items, containers, _url, chain, context)

        elif ILocation.providedBy(context):
            _url = url.absoluteURL(context, self.request)
            #props = IDCDescriptiveProperties.providedBy(context) and \
            #    context or IDCDescriptiveProperties(context)
            if IDCDescriptiveProperties.providedBy(context):
                props = IDCDescriptiveProperties(context)
            else:
                props = context
            props = proxy.removeSecurityProxy(props)

            selected = len(chain) == 0
            if selected and IReadContainer.providedBy(context):
                nodes = []
                try:
                    self.expand_containers(
                        nodes, context.items(), _url, chain, context)
                except:
                    pass
            else:
                nodes = self.expand(chain)
            i_id = getattr(props, 'id','N/A')
            items.append(
                {'title': getattr(props, 'title', i_id),
                 'url': _url,
                 'current': True,
                 'selected': selected,
                 'kind': 'location',
                 'nodes': nodes,
                 })

        elif IReadContainer.providedBy(context):
            items.extend(self.expand(chain))

        return items
Exemplo n.º 22
0
 def matches(self, object):
     if not IReadContainer.providedBy(object):
         raise AssertionError("Expecting container")
     return len(object) == self._count
Exemplo n.º 23
0
 def __new__(cls, context, request, view, manager):
     inst = NavigationTreeViewlet.__new__(cls, context, request, view,
                                          manager)
     # we require the tree to begin with a container object
     if not IReadContainer.providedBy(inst.chain[-1]):
         return
Exemplo n.º 24
0
    def expand(self, chain, include_siblings=True):
        if len(chain) == 0:
            return ()
        context = chain.pop()
        items = []
        if IApplication.providedBy(context):
            items.extend(self.expand(chain))
        elif IAlchemistContent.providedBy(context):
            _url = url.absoluteURL(context, self.request)
            selected = len(chain) == 0

            if chain:
                nodes = self.expand(chain)
            else:
                containers = utils.get_managed_containers(context)
                nodes = []
                self.expand_containers(nodes, containers, _url, chain, None)

            items.append({
                "id": self.get_nav_entry_id(_url),
                "label": IDCDescriptiveProperties(context).title,
                "url": _url,
                "current": True,
                "selected": selected,
                "kind": "content",
                "nodes": nodes,
            })
        elif IAlchemistContainer.providedBy(context):
            # loop through all managed containers of the parent
            # object, and include the present container as the
            # "current" node.
            parent = context.__parent__
            assert parent is not None
            _url = url.absoluteURL(parent, self.request)

            # append managed containers as child nodes
            if include_siblings is True:
                if IApplication.providedBy(parent):
                    containers = [
                        (name, parent[name]) for name in
                        location.model_to_container_name_mapping.values()
                        if name in parent
                    ]
                elif IReadContainer.providedBy(parent):
                    containers = list(parent.items())
                else:
                    containers = utils.get_managed_containers(parent)
            else:
                containers = [(context.__name__, context)]
            self.expand_containers(items, containers, _url, chain, context)
        elif ILocation.providedBy(context):
            # e.g. bungeni.core.content.Section, DisplayForm
            _url = url.absoluteURL(context, self.request)
            selected = len(chain) == 0
            if selected and IReadContainer.providedBy(context):
                nodes = []
                try:
                    self.expand_containers(nodes, context.items(), _url, chain,
                                           context)
                except:
                    pass
            else:
                nodes = self.expand(chain)
            _title = getattr(context, "title", None) or \
                getattr(context, "page_title", "!+BungeniBrowserView.title")
            items.append({
                "id": self.get_nav_entry_id(_url),
                # !+BungeniBrowserView.title
                "label": _title,  #IDCDescriptiveProperties(context).title,
                "url": _url,
                "current": True,
                "selected": selected,
                "kind": "location",
                "nodes": nodes,
            })
        elif IReadContainer.providedBy(context):
            #!+NavigationTreeViewlet-EXPAND-IReadContainer(mr, oct-2012) does this ever execute?!
            raise Exception(
                "!+NavigationTreeViewlet-EXPAND-IReadContainer [%s]" % context)
            items.extend(self.expand(chain))
        return items
Exemplo n.º 25
0
 def matches(self, object):
     if IReadContainer.providedBy(object):
         return len(object) == self._count
     else:
         return False
Exemplo n.º 26
0
 def __new__(cls, context, request, view, manager):
     inst = NavigationTreeViewlet.__new__(cls, context, request, view, manager)
     # we require the tree to begin with a container object
     if not IReadContainer.providedBy(inst.chain[-1]):
         return
Exemplo n.º 27
0
 def is_container(self):
     # I recommend reimplement this and return IS_CONTAINER
     # or empty string directly
     return IReadContainer.providedBy(self.context) or u''
Exemplo n.º 28
0
 def matches(self, object):
     if IReadContainer.providedBy(object):
         return len(object) == self._count
     else:
         return False
Exemplo n.º 29
0
 def matches(self, object):
     if not IReadContainer.providedBy(object):
         raise AssertionError("Expecting container")
     return len(object) == self._count