
=============
 Description
=============

The :mod:`grampg` code provides you with a **password generator object**, a bottomless barrel from which you can pull passwords. The difference between this *generator object* and something like ``/dev/random`` or ``''.join([random.choice(letters) for i in range(LEN)])`` is that you get to build that generator with great specificity, to obtain passwords adequate to your needs.

You will first have to build the generator, though. This could be a tedious, and difficult task. Consider the following example::

  how would you tell the builder you want passwords 10 characters long,
  with lower letters but at least 3 numbers, starting with a letter?

:mod:`grampg` provides an easy to use interface, aimed at translating your needs intuitively.

Building the generator object is done in steps, using a **builder** object. At each step you add a *spec* (think of it as a piece of specification). You proceed working on the builder object accumulating *specs*, all of which add up to the requirements your passwords must satisfy. In the case of the example, you could use something like this::

  gen = PasswordGenerator().of().length(10).at_most(10, 'lower_letters')
                                           .at_least(3, 'numbers')
                                           .beginning_with('lower_letters')
                                           .done()

The expression above will yield a generator object ready to produce passwords, exactly as you require them.

.. note:: The order in which *specs* are added is irrelevant. You are encourage to declare your *specs* as they sound more natural in your head; doing so greatly improves maintainability of the code.

Now that you have you generator object, you can use it throughout your own code::

  passwords = [gen.generate() for i in xrange(so_many_passwords)]

And that's what :mod:`grampg` offers: a simple way to specify contrived password schema.

.. note:: In case you're wondering, passwords generated by the resulting generator object are **strong**. You can revise the algorithm later in this docs. XXX add reference to that.


The PasswordGenerator / Generator duality
=================================================

Apart from a small hierarchy of three exceptions to deal with errors, the :mod:`grampg` exposes two classes to the user: the **Generator** and the **PasswordGenerator**. The naming might be confusing, but (as much in the design of this library) it is for the sake of code readability.

Of the two classes, the :class:`grampg.Generator` is the actual password generator. It accumulates and holds you *specs*, generates the passwords and is the object which the user will keep reference to (in most, but not all, use cases). It implements the :meth:`grampg.Generator.generate` method, and that says it all.

The :class:`grampg.PasswordGenerator`, on the other hand, is the *builder* class. It's instances will create and stow away a :class:`grampg.Generator` instance for the user, and will act as its interface as *specs* are added. It relinquishes control of the *generator object* only when the building phase is terminated (when it receives a call to :meth:`~grampg.PasswordGenerator.done`).

This explains the naming choices: the user should never have the need to write ``Generator()`` but ``PasswordGenerator.of()`` (both idioms being equivalent, the second instantiates the generator object internally).


Technical description
=====================

The two classes exposed by the :mod:`grampg` module constitute a *builder* and *product* pair. The *builder* aids the user in specifying an adequate representation of the *product*.

*Generators* are instances of :class:`grampg.Generator`. A generator object is instantiated with the sets of characters to use, and is responsible for accumulating the *specs* through method calls. The user, however, does not need to know any of that. The user never really interacts with a :class:`grampg.Generator` instance directly, but through the builder. For the user, generator objects have one method of interest, :meth:`~grampg.Generator.generate`, which produces a single, independent and strong password string each time it's called, but which can be called only when the specification phase is *done*.

A builder object is an instances of :class:`grampg.PasswordGenerator`, and provides a *fluent interface* to the Generator internal object being specified. The interface leverages *method chaining* and the *builder pattern* to provide a quick and easy specification phase. The :class:`grampg.PasswordGenerator` provides a means of defining non-default character sets (characters to choose from when generating passwords), and passes user *specs* to the generator object being built. The builder object returns the generator object only when a call to :meth:`~grampg.PasswordGenerator.done` succeeds. The generator object returned is ready to receive calls to :meth:`~grampg.Generator.generate`.
