Course Containers
*****************

.. module:: waeup.kofa.university.coursescontainer

Containers for courses.

.. :doctest:
.. :layer: waeup.kofa.testing.KofaUnitTestLayer


Content Classes (models and containers)
=======================================

:class:`CoursesContainer`
-------------------------

.. class:: CoursesContainer()

   Create a course container instance.

   .. attribute:: grok.implements(ICoursesContainer)

   :class:`CoursesContainer` instances are instances of
   :class:`grok.Container` that hold and manage instances of
   :class:`waeup.kofa.university.course.Course`.

     >>> from waeup.kofa.university.coursescontainer import CoursesContainer
     >>> mycontainer = CoursesContainer()
     >>> mycontainer
     <waeup.kofa.university.coursescontainer.CoursesContainer object at 0x...>

   Course containers provide `ICoursesContainer`:

     >>> from waeup.kofa.university.interfaces import ICoursesContainer
     >>> ICoursesContainer.providedBy(mycontainer)
     True

   We can be sure, that the full interface is supported by the
   CoursesContainer class:

     >>> from zope.interface.verify import verifyClass
     >>> verifyClass(ICoursesContainer, CoursesContainer)
     True

   As normal ``grok.Container``, :class:`CoursesContainer` instances
   can be used like dicts:

     >>> list(mycontainer.keys())
     []

   .. method:: addCourse(course)

      Add a course.

      *course* must be an instance of
      :class:`waeup.kofa.university.course.Course`:

        >>> from waeup.kofa.university.coursescontainer import CoursesContainer
        >>> mycontainer = CoursesContainer()
        >>> mycontainer.addCourse('blah')
        Traceback (most recent call last):
        ...
        TypeError: CoursesContainers contain only ICourse instances

      The key of added items is the ``code`` attribute:

        >>> from waeup.kofa.university.course import Course
        >>> mycourse = Course(code='COURSE1')
        >>> mycontainer.addCourse(mycourse)
        >>> list(mycontainer.keys())
        [u'COURSE1']

   .. method:: clear()

      Remove all contained courses:

        >>> len(mycontainer.items())
        1

        >>> mycontainer.clear()
        >>> len(mycontainer.items())
        0

Utilities
=========

:class:`CoursesContainerFactory`
--------------------------------

.. class:: CoursesContainerFactory()

   .. attribute:: grok.name(u'waeup.CoursesContainer')

   .. attribute:: grok.implements(IFactory)

   A named utility to deliver new instances of :class:`CoursesContainer`
   without the need to import the implementation before:

     >>> from zope.component import createObject
     >>> mycoursescontainer = createObject(u'waeup.CoursesContainer')
     >>> mycoursescontainer
     <waeup.kofa.university.coursescontainer.CoursesContainer object at 0x...>

   The factory complies with the specifications from the
   :class:`IFactory` insterface:

     >>> from zope.interface.verify import verifyClass
     >>> from zope.component.interfaces import IFactory
     >>> from waeup.kofa.university.coursescontainer import CoursesContainerFactory
     >>> verifyClass(IFactory, CoursesContainerFactory)
     True

   This means also, that we can get the interfaces of the created
   object from the factory:

     >>> coursescontainer_factory = CoursesContainerFactory()
     >>> coursescontainer_factory.getInterfaces()
     <implementedBy waeup.kofa.university.coursescontainer.CoursesContainer>


Examples
========

Getting a course container
--------------------------

We can easily create `CoursesContainers`:

    >>> from waeup.kofa.university.coursescontainer import CoursesContainer
    >>> mycontainer = CoursesContainer()


Another way to get a course container -- without importing the class
-- is via factories. We registered a factory for course containers
under the name ``waeup.CoursesContainer``. Now we can ask for an object
by calling the appropriate factory:

    >>> from zope.component import createObject
    >>> createObject(u'waeup.CoursesContainer')
    <waeup.kofa.university.coursescontainer.CoursesContainer object at 0x...>

This way we get a thing that implements ICoursesContainer without
imports or similar.

