##############################################################################
#
# Copyright (c) 2008 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""
===========================
Utilities for z3c.testsetup
===========================

The `util` module defines some helper functions of general use.

get_package(pkg_or_dotted_name)
-------------------------------

For most classes in this package, that accept packages as arguments,
these packages can be delivered as real packages or as strings
containing dotted names. To get a package of something, that is either
a string with dotted names or a real package, the `get_package`
function is provided.

Such we can get a package from a dotted name string::

   >>> from z3c.testsetup.util import get_package
   >>> get_package('z3c.testsetup.tests.cave')
   <module 'z3c.testsetup.tests.cave' from '...'>

The dotted name string can be unicode::

   >>> get_package(u'z3c.testsetup.tests.cave')
   <module 'z3c.testsetup.tests.cave' from '...'>

We can indeed pass a package as argument::

   >>> from z3c.testsetup.tests import cave
   >>> get_package(cave)
   <module 'z3c.testsetup.tests.cave' from '...'>


get_keyword_params(class, method_name)
--------------------------------------

The ``get_keyword_params()`` function tries to extract all keyword
parameters of a given method of a class. We want to know, which
keyword parameters are supported by the constructor of the following
class::

   >>> class Club(object):
   ...     def __init__(self, weight, num_of_spikes=0):
   ...         pass

This can be done by::

   >>> from z3c.testsetup.util import get_keyword_params
   >>> kw_list = get_keyword_params(Club, '__init__')
   >>> kw_list.sort()
   >>> kw_list
   ['num_of_spikes']

Okay. Note, that we only get the keyword parameters, i.e. parameters,
that have a default value.

What now, if the class was derived and supports more parameters
than actually shown in the class definition itself? First, let us
create such a class::

   >>> class ColouredClub(Club):
   ...     def __init__(self, weight, color='pink', **kw):
   ...         pass

A coloured club can therefore have a number of spikes and a
color. Will both be found by our helper function?::

   >>> kw_list = get_keyword_params(ColouredClub, '__init__')
   >>> kw_list.sort()
   >>> kw_list
   ['color', 'num_of_spikes']

Fine.

Now we check, wether only really accepted parameters are found. What,
if a derived class does not accept various keywords using ``**kw`` or
similar? We define such a class::

   >>> class ClubSoda(Club):
   ...    def __init__(self, temperature=12, sparkles=True, *args):
   ...        pass

This time, the ``num_of_spikes`` parameter should not appear. The
``weight`` parameter, which is derived from the base class, should
neighter appear::

   >>> kw_list = get_keyword_params(ClubSoda, '__init__')
   >>> kw_list.sort()
   >>> kw_list
   ['sparkles', 'temperature']


"""
