<commit_before># Contratos - Python contract programming

This module defines some helpful functions for performing
Contract Programming in Python. I know that Contract Programming
was first used in the Eiffel programming language. This module
will not follow everything on it(because I have never programmed
in Eiffel or read Eiffel). Instead this module is my take and implementation
of Contract Programming. It might be exactly the same or completely 
different from it. Hopefully in the future I will be able to 
learn Eiffel and follow it's implementation.

In the mean while. In this module:

A *Contract* is a list of terms that must be satisfied.

A *Term* limits a function's domain or range(input or output) to
values that satisfy a list of conditions.

A *Requirement* is a term that limits a function's domain to
values that satisfy a list of conditions.

An *Ensurance* is a term that limits a function's range to
values that satisfy a list of conditions.

A *Condition* is something that evaluates to true during a contract.

When extended to data structures, a *Contract* can limit the set of
values a property can take.

## Installation

```
git clone https://github.com/wilbertom/contracts
cd ./contratos
make install

```

If running `make` worries you or you don't have it installed in your system,
just run:

```
python setup.py

```

The module has *no requirements*, except running `python 3.4`. Though
everything should work on `2.7`. It is not the targeted version though.

## Usage

So what does this translate to? Above I'm being vague on purpose. Let's use
this module to implement type checking in Python.

```
from contratos.contracts import ensure, require

def is_int(n):
    return isinstance(n, int)

def is_string(s):
    return isinstance(s, str)

@require(is_int, is_string)
@ensure(is_string)
def repeat(string, n_times):
    return string * n_times

print(repeat('Hello ', 3))
'Hello Hello Hello'

print(repeat('Hello', 's'))
Boomsmahsunakskn error is raised

```

A `term` is a decorator function that takes numerous
`conditions`. `conditions` are just functions that return
a truthy(preferably `True` or `False`) value. It applies
each condition function at some point. A function decorated
in `terms` is a `contract`. 

Above our `terms` are `ensure` and `require`. We `require`
that our first parameter `is_string` and the second `is_int`.

We `ensure` that the first(and only in this case) return value
`is_string`.

Besides all the bad methaphors I hope you can see the power
behind this. These `terms` create invariants under which we
can program. 

The second call to repeat above would raise an error
because the second parameter didn't satisfy `is_string`.

Type checking is just one reason to use this, but as we
know having functions that don't need to specify a type
is most of the time good. So here is another example.

```
def not_zero(n):
    return n != 0

def is_num(n):
    return isinstance(n, int) or isinstance(n, float)

@require(is_num, is_num)
@require(None, not_zero)
def divide(n, by):
    return n / by

divide(5, 5) # 1
divide(5, 0) # booomaknsakjda error

```

Above we implement a function that accepts two numbers and
requires that the second parameter is `not_zero`. As opposed
to having all over your source code checks for 
`if n == 0: raise Excep...`, here we define a condition 
that can be used anywhere. Now never again will you write 
`if n == 0: raise Excep...`.

Also as a nice side effect, we get some really nice syntax that
document our functions.

A function can have more that one `ensure` and more than one
`require`. Make sure that the return value and input parameters
match the signature of you `conditions`.

## Built-in Conditions

Since some conditions will be so common, the module defines a
few for convenience, *feel free to propose more*. You can create
an issue it and tag it with the condition label.

Here are some already defined. They can be found under
`contratos.conditions`.

```

# type checking
is_string = partial(instance_of, str)
is_int = partial(instance_of, int)
is_float = partial(instance_of, float)
is_num = lambda n: is_int(n) or is_float(n)
is_bool = partial(instance_of, bool)  # @not-tested
is_tuple = partial(instance_of, tuple)  # @not-tested
is_list = partial(instance_of, list)  # @not-tested
is_iterable = partial(instance_of, Iterable)  # @not-tested

# specific numeric sets
is_positive = lambda n: n > 0  # @not-tested
is_non_negative = lambda n: n >= 0  # @not-tested
is_natural = lambda n: is_int(n) and is_positive(n)  # @not-tested
is_natural_0 = lambda n: is_int(n) and is_non_negative(n)  # @not-tested
is_negative = lambda n: is_num(n) and not is_non_negative(n)  # @not-tested
is_even = lambda n: n % 2 == 0  # @not-tested
is_odd = lambda n: not is_even(n)  # @not-tested
is_zero = lambda n: n == 0  # @not-tested
not_zero = lambda n: not is_zero(n)  # @not-tested

# convenience sets
are_ints

```

To see the updated list take a look inside the `contratos/conditions.py` file.

## Running Tests

I tried developing this project using `TDD`. I broke the practice because it was
my first time. Still some tests still exists and all the source code will be
tested in the future.

```
make tests

```

Or:

```
python -m unittest discover contratos.test_contracts
python -m unittest discover contratos.test_extras

```

As of now it looks like it's running the tests twice. I'm
just figuring how this stuff works.

## Directory Structure

```
├── LICENSE.md - MIT
├── Makefile - Ha ha yes, no C in this directory, I'm just lazy
├── README.md - This file
└── contratos - All the source code
    ├── conditions.py - Some built in conditions
    ├── contracts.py - The most important part. The built in contracts
    ├── helpers.py - Things that help the core. Should not be used outside.
    └── test_contracts.py - TDD. Add a test before sending PR
```<commit_msg>Typos 2<commit_after># Contratos - Python contract programming

This module defines some helpful functions for performing
Contract Programming in Python. I know that Contract Programming
was first used in the Eiffel programming language. This module
will not follow everything on it(because I have never programmed
in Eiffel or read Eiffel). Instead this module is my take and implementation
of Contract Programming. It might be exactly the same or completely 
different from it. Hopefully in the future I will be able to 
learn Eiffel and follow it's implementation.

Meanwhile, in this module:

A *Contract* is a list of terms that must be satisfied.

A *Term* limits a function's domain or range(input or output) to
values that satisfy a list of conditions.

A *Requirement* is a term that limits a function's domain to
values that satisfy a list of conditions.

An *Ensurance* is a term that limits a function's range to
values that satisfy a list of conditions.

A *Condition* is something that evaluates to true during a contract.

When extended to data structures, a *Contract* can limit the set of
values a property can take.

## Installation

```
git clone https://github.com/wilbertom/contracts
cd ./contratos
make install
```

If running `make` worries you or you don't have it installed in your system,
just run:

```
python setup.py install
```

The module has *no requirements*, except running `python 3.4`. Everything
should work on `2.7`, but it is not the targeted version.

## Usage

So what does this translate to? Above I'm being vague on purpose. Let's use
this module to implement type checking in Python.

```
from contratos.contracts import ensure, require

def is_int(n):
    return isinstance(n, int)

def is_string(s):
    return isinstance(s, str)

@require(is_string, is_int)
@ensure(is_string)
def repeat(string, n_times):
    return string * n_times

print(repeat('Hello ', 3)) # 'Hello Hello Hello'

print(repeat('Hello', 's')) # Boomsmahsunakskn error is raised

```

A `term` is a decorator function that takes numerous
`conditions`. `conditions` are just functions that return
a truthy(preferably `True` or `False`) value. It applies
each condition function at some point. A function decorated
in `terms` is a `contract`. 

Above our `terms` are `ensure` and `require`. We `require`
that our first parameter `is_string` and the second `is_int`.
So our conditions are `is_string` and `is_int`.

We `ensure` that the first(and only in this case) return value
`is_string`.

Besides all the bad methaphors I hope you can see the power
behind this. These `terms` create invariants under which we
can program. 

The second call to repeat above would raise an error
because the second parameter didn't satisfy `is_string`.

Type checking is just one reason to use this, but as we
know having functions that don't need to specify a type
is most of the time good. So here is another example.

```
from contratos.contracts import require

def not_zero(n):
    return n != 0

def is_num(n):
    return isinstance(n, int) or isinstance(n, float)

@require(is_num, is_num)
@require(None, not_zero)
def divide(n, by):
    return n / by

print(divide(5, 5)) # 1.0
divide(5, 0) # booomaknsakjda error

```

Above we implement a function that accepts two numbers and
requires that the second parameter is `not_zero`. As opposed
to having all over your source code checks for 
`if n == 0: raise Excep...`, here we define a condition 
that can be used anywhere. Now never again will you write 
`if n == 0: raise Excep...`.

Also as a side effect, we get some really nice syntax that
documents our functions.

A function can have more that one `ensure` and more than one
`require`. Make sure that the return value and input parameters
match the signature of your `conditions`.

## Built-in Conditions

Since some conditions will be so common, the module defines a
few for convenience, *feel free to propose more*. You can create
an issue it and tag it with the condition label.

Here are some already defined. They can be found under
`contratos.conditions`.

```

# type checking
is_string = partial(instance_of, str)
is_int = partial(instance_of, int)
is_float = partial(instance_of, float)
is_num = lambda n: is_int(n) or is_float(n)
is_bool = partial(instance_of, bool)  # @not-tested
is_tuple = partial(instance_of, tuple)  # @not-tested
is_list = partial(instance_of, list)  # @not-tested
is_iterable = partial(instance_of, Iterable)  # @not-tested

# specific numeric sets
is_positive = lambda n: n > 0  # @not-tested
is_non_negative = lambda n: n >= 0  # @not-tested
is_natural = lambda n: is_int(n) and is_positive(n)  # @not-tested
is_natural_0 = lambda n: is_int(n) and is_non_negative(n)  # @not-tested
is_negative = lambda n: is_num(n) and not is_non_negative(n)  # @not-tested
is_even = lambda n: n % 2 == 0  # @not-tested
is_odd = lambda n: not is_even(n)  # @not-tested
is_zero = lambda n: n == 0  # @not-tested
not_zero = lambda n: not is_zero(n)  # @not-tested

# convenience sets
are_ints

```

To see the updated list take a look inside the `contratos/conditions.py` file.

## Running Tests

I tried developing this project using `TDD`. I broke the practice because it was
my first time. Still some tests exists and all the source code will be
tested in the future.

```
make tests
```

Or:

```
python -m unittest discover contratos.test_contracts
python -m unittest discover contratos.test_extras
```

As of now it looks like it's running the tests twice. I'm
just figuring how this stuff works.

## Directory Structure

```
├── LICENSE.md - MIT
├── Makefile - Ha ha yes, no C in this directory, I'm just lazy
├── README.md - This file
└── contratos - All the source code
    ├── conditions.py - Some built in conditions
    ├── contracts.py - The most important part. The built in contracts
    ├── helpers.py - Things that help the core. Should not be used outside.
    └── test_contracts.py - TDD. Add a test before sending PR
```
{'fraction_non_alphanumeric': 0.08301727770754319, 'fraction_numerical': 0.00337126000842815, 'mean_word_length': 4.181659388646288, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 2, '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': '999811', 'n_tokens_mistral': 3645, 'n_tokens_neox': 3479, 'n_words': 1697}