<commit_before>==============================================
Contexter: :module:`contextlib` for humanoids
==============================================

Contexter is a full replacement of the :module:`contextlib` standard library module. It comes with more features, a nicer API and full support for Python 2.5 up to 3.x from a single source file.

To keep it short: Contexter allows you to nest and stack context managers in an easy and intuitive way. It is basically :module:`contextlib` for humans.

Enough talk, let's see an example::

    ''' Copy the content of one file to another
         and protect everything with a lock. '''

    with Contexter(lock) as ctx:
        in_file  = ctx << open('a.txt')
        out_file = ctx << open('b.txt', 'w')
        out_file.write(in_file.read())

Look at that. It's beautiful, isn't it? Let me explain: You call :class:`Contexter` with any number of context managers as arguments and later attach additional managers with the neat `value = ctx << thing` syntax. That's it. Only one level of indentation, no matter how many managers you need.

Just for comparison::

    # Python 2.5 and 2.6
    with lock:
        with open('a.txt') as in_file:
            with open('b.txt', 'w') as out_file:
                out_file.write(in_file.read())

    # Starting with Python 2.7 and 3.2
    with lock, open('a.txt') as in_file, open('b.txt', 'w') as out_file:
        out_file.write(in_file.read())

    # Deprecated since Python 2.7 and 3.2
    with contextlib.nested(lock, open('a.txt'), open('b.txt', 'w')) as values:
        in_file, out_file = values
        out_file.write(in_file.read())

    # Since Python 3.3 (not backported to 2.7)
    with contextlib.ExitStack() as stack:
        stack.enter_context(lock)
        in_file  = stack.enter_context(open('a.txt'))<commit_msg>Fixed code blocks in README<commit_after>==============================================
Contexter: :module:`contextlib` for humanoids
==============================================

Contexter is a full replacement of the :module:`contextlib` standard library module. It comes with more features, a nicer API and full support for Python 2.5 up to 3.x from a single source file.

To keep it short: Contexter allows you to nest and stack context managers in an easy and intuitive way. It is basically :module:`contextlib` for humans.

Enough talk, let's see an example:

.. code:: python

    ''' Copy the content of one file to another
         and protect everything with a lock. '''

    with Contexter(lock) as ctx:
        in_file  = ctx << open('a.txt')
        out_file = ctx << open('b.txt', 'w')
        out_file.write(in_file.read())

Look at that. It's beautiful, isn't it? Let me explain: You call :class:`Contexter` with any number of context managers as arguments and later attach additional managers with the neat ``value = ctx << thing`` syntax. That's it. Only one level of indentation, no matter how many managers you need.

Just for comparison:

.. code:: python

    # Python 2.5 and 2.6
    with lock:
        with open('a.txt') as in_file:
            with open('b.txt', 'w') as out_file:
                out_file.write(in_file.read())

    # Starting with Python 2.7 and 3.2
    with lock, open('a.txt') as in_file, open('b.txt', 'w') as out_file:
        out_file.write(in_file.read())

    # Deprecated since Python 2.7 and 3.2
    with contextlib.nested(lock, open('a.txt'), open('b.txt', 'w')) as values:
        in_file, out_file = values
        out_file.write(in_file.read())

    # Since Python 3.3 (not backported to 2.7)
    with contextlib.ExitStack() as stack:
        stack.enter_context(lock)
        in_file  = stack.enter_context(open('a.txt'))
{'fraction_non_alphanumeric': 0.15202156334231806, 'fraction_numerical': 0.010242587601078167, 'mean_word_length': 3.2901734104046243, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3976717', 'n_tokens_mistral': 1122, 'n_tokens_neox': 1065, 'n_words': 423}