Full Code of trekhleb/learn-python for AI

master 7d36c78b5f8f cached
79 files
189.6 KB
50.2k tokens
96 symbols
1 requests
Download .txt
Showing preview only (208K chars total). Download the full file or copy to clipboard to get everything.
Repository: trekhleb/learn-python
Branch: master
Commit: 7d36c78b5f8f
Files: 79
Total size: 189.6 KB

Directory structure:
gitextract_6lyybz2h/

├── .flake8
├── .gitignore
├── .travis.yml
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.es-ES.md
├── README.md
├── README.pt-BR.md
├── README.zh-TW.md
├── _config.yml
├── pylintrc
├── requirements.txt
└── src/
    ├── additions/
    │   ├── test_generators.py
    │   └── test_pass.py
    ├── classes/
    │   ├── test_class_and_instance_variables.py
    │   ├── test_class_definition.py
    │   ├── test_class_objects.py
    │   ├── test_inheritance.py
    │   ├── test_instance_objects.py
    │   ├── test_method_objects.py
    │   └── test_multiple_inheritance.py
    ├── control_flow/
    │   ├── test_break.py
    │   ├── test_continue.py
    │   ├── test_for.py
    │   ├── test_if.py
    │   ├── test_try.py
    │   └── test_while.py
    ├── data_types/
    │   ├── test_dictionaries.py
    │   ├── test_lists.py
    │   ├── test_numbers.py
    │   ├── test_sets.py
    │   ├── test_strings.py
    │   ├── test_tuples.py
    │   └── test_type_casting.py
    ├── exceptions/
    │   ├── test_handle_exceptions.py
    │   └── test_raise_exceptions.py
    ├── files/
    │   ├── binary_file
    │   ├── multi_line_file.txt
    │   ├── test_file_methods.py
    │   └── test_file_reading.py
    ├── functions/
    │   ├── test_function_annotations.py
    │   ├── test_function_arbitrary_arguments.py
    │   ├── test_function_decorators.py
    │   ├── test_function_default_arguments.py
    │   ├── test_function_definition.py
    │   ├── test_function_documentation_string.py
    │   ├── test_function_keyword_arguments.py
    │   ├── test_function_scopes.py
    │   ├── test_function_unpacking_arguments.py
    │   └── test_lambda_expressions.py
    ├── getting_started/
    │   ├── python_syntax.md
    │   ├── test_variables.py
    │   └── what_is_python.md
    ├── modules/
    │   ├── fibonacci_module.py
    │   ├── sound_package/
    │   │   ├── __init__.py
    │   │   ├── effects/
    │   │   │   ├── __init__.py
    │   │   │   ├── echo.py
    │   │   │   └── reverse.py
    │   │   └── formats/
    │   │       ├── __init__.py
    │   │       ├── aif.py
    │   │       └── wav.py
    │   ├── test_modules.py
    │   └── test_packages.py
    ├── operators/
    │   ├── test_arithmetic.py
    │   ├── test_assigment.py
    │   ├── test_bitwise.py
    │   ├── test_comparison.py
    │   ├── test_identity.py
    │   ├── test_logical.py
    │   └── test_membership.py
    ├── standard_libraries/
    │   ├── glob_files/
    │   │   ├── first_file.txt
    │   │   └── second_file.txt
    │   ├── test_datetime.py
    │   ├── test_glob.py
    │   ├── test_json.py
    │   ├── test_math.py
    │   ├── test_re.py
    │   └── test_zlib.py
    └── user_input/
        └── test_input.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .flake8
================================================
[flake8]
max-line-length = 100


================================================
FILE: .gitignore
================================================
.idea
.pytest_cache
venv
**/*.pyc
env
__pycache__
.vscode


================================================
FILE: .travis.yml
================================================
language: python
python:
  - "3.6"

# Install dependencies.
install:
  - pip install -r requirements.txt

# Run linting and tests.
script:
  - pylint ./src
  - flake8 ./src --statistics --count
  - pytest

# Turn email notifications off.
notifications:
  email: false


================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.

## Our Standards

Examples of behavior that contributes to creating a positive environment include:

* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting

## Scope

This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]

[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2018 Oleksii Trekhleb

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.es-ES.md
================================================
# Playground y Cheatsheet para aprender Python

[![Build Status](https://travis-ci.org/trekhleb/learn-python.svg?branch=master)](https://travis-ci.org/trekhleb/learn-python)

> Esta es una colección de scripts de Python divididos en [categorías](#contenido) que contienen
ejemplos de código con sus explicaciones, diferentes usos y links a recursos adicionales.

> _Lee esto en:_ [_Inglés_](README.md), [_Portugués_](README.pt-BR.md), _Traditional Chinese_](README.zh-TW.md).

Es un **playground** ya que puedes cambiar o añadir cosas al código para ver
cómo funciona y [probarlo](#probando-el-código) usando aserciones. También puedes
[revisar el código](#revisando-el-código) que has escrito y averiguar si está acorde con
la guía de estilos de Python. Todo esto, en conjunto, puede hacer que tu proceso de aprendizaje
sea más interactivo y puede ayudarte a mantener la calidad del código muy alta desde el principio.

Es un **cheatsheet** porque puedes regresar y revisar los ejemplos de código para
fortalecer tus conocimientos sobre las [sentencias y contrucciones estándar de Python](#contenido).
Además, ya que el código tiene muchas aserciones, podrás ver el resultado de las funciones/sentencias en el mismo
código sin la necesidad de ejecutarlos.

> _También puede interesarte 🤖 [Interactive Machine Learning Experiments](https://github.com/trekhleb/machine-learning-experiments)_

## Cómo usar este repositorio

Cada script de Python en este repositorio sigue la estructura:

```python
"""Lists  <--- Nombre del tema

# @see: https://www.learnpython.org/en/Lists  <-- Link a recurso adicional

Aquí puede haber una explicación detallada del tema en concreto (ej: información general sobre listas).
"""


def test_list_type():
    """Explicación del sub-tema.
    
    Cada archivo contiene funciones de prueba que muestran sub-temas (ej: tipos de listas, métodos en listas).
    """
    
    # Este es un ejemplo de cómo construir una lista. <-- Estos comentarios explican el procedimiento
    squares = [1, 4, 9, 16, 25]
    
    # Las listas pueden ser indexadas y cortadas. 
    # Al indexar devuelve el item.
    assert squares[0] == 1  # <-- Estas aserciones muestran el resultado.
    # Al cortar devuelve una nueva lista.
    assert squares[-3:] == [9, 16, 25]  # <-- Estas aserciones muestran el resultado.
```

Normalmente, querrás hacer lo siguiente:

- [Encontrar el tema](#contenido) que quieres aprender o revisar.
- Leer los comentarios y/o la documentación que está escrita en cada docstring del script (toma como ejemplo el script de arriba).
- Ver los ejemplos de código y las aserciones para conocer diferentes maneras de usar el código y entender el resultado previsto.
- Cambiar el código o añadir nuevas aserciones para ver cómo funcionan las cosas.
- [Probar](#probando-el-código) y [revisar](#revisando-el-código) el código para ver si funciona y si está escrito
correctamente.

## Contenido

1. **Empezando**
    - [¿Qué es Python?](src/getting_started/what_is_python.md)
    - [Sintaxis de Python](src/getting_started/python_syntax.md)
    - [Variables](src/getting_started/test_variables.py)
2. **Operadores**
    - [Operadores aritméticos](src/operators/test_arithmetic.py) (`+`, `-`, `*`, `/`, `//`, `%`, `**`)
    - [Operadores Bitwise](src/operators/test_bitwise.py) (`&`, `|`, `^`, `>>`, `<<`, `~`)
    - [Operadores de atribución](src/operators/test_assigment.py) (`=`, `+=`, `-=`, `/=`, `//=` etc.)
    - [Operadores de comparación](src/operators/test_comparison.py) (`==`, `!=`, `>`, `<`, `>=`, `<=`)
    - [Operadores lógicos](src/operators/test_logical.py) (`and`, `or`, `not`)
    - [Operadores de identidad](src/operators/test_identity.py) (`is`, `is not`)
    - [Operadores de asociación](src/operators/test_membership.py) (`in`, `not in`)
3. **Tipos de datos**
    - [Números](src/data_types/test_numbers.py) (incluyendo booleans)
    - [Strings](src/data_types/test_strings.py) y sus métodos
    - [Listas](src/data_types/test_lists.py) y sus métodos (incluyendo comprensión de listas)
    - [Tuples](src/data_types/test_tuples.py)
    - [Sets](src/data_types/test_sets.py) y sus métodos
    - [Diccionarios](src/data_types/test_dictionaries.py)
    - [Tipo de casting](src/data_types/test_type_casting.py)
4. **Control de flujo**
    - [La sentencia `if`](src/control_flow/test_if.py)
    - [La sentencia `for`](src/control_flow/test_for.py) (y la función `range()`)
    - [La sentencia `while`](src/control_flow/test_while.py)
    - [La sentencia `try`](src/control_flow/test_try.py)
    - [La sentencia `break`](src/control_flow/test_break.py)
    - [La sentencia `continue`](src/control_flow/test_continue.py)
5. **Funciones**
    - [Definición de función](src/functions/test_function_definition.py) (sentencias `def` y `return`)
    - [Ámbito de variables dentro de funciones](src/functions/test_function_scopes.py) (sentencias `global` y `nonlocal`)
    - [Valores de argumento predeterminados](src/functions/test_function_default_arguments.py)
    - [Argumentos de palabras clave](src/functions/test_function_keyword_arguments.py)
    - [Listas de argumento arbitrario](src/functions/test_function_arbitrary_arguments.py)
    - [Listas de argumentos en funciones](src/functions/test_function_unpacking_arguments.py) (sentencias `*` y `**`)
    - [Expresiones Lambda](src/functions/test_lambda_expressions.py) (sentencia `lambda`)
    - [Strings de documentación](src/functions/test_function_documentation_string.py)
    - [Anotaciones en funciones](src/functions/test_function_annotations.py)
    - [Decoradores de funciones](src/functions/test_function_decorators.py)
6. **Clases**
    - [Definición de clase](src/classes/test_class_definition.py) (sentencia `class`)
    - [Objetos de clase](src/classes/test_class_objects.py)
    - [Objetos de instancia](src/classes/test_instance_objects.py)
    - [Métodos de objetos](src/classes/test_method_objects.py)
    - [Variables de clase y de instancia](src/classes/test_class_and_instance_variables.py)
    - [Herencia](src/classes/test_inheritance.py)
    - [Herencia múltiple](src/classes/test_multiple_inheritance.py)
7. **Módulos**
    - [Módulos](src/modules/test_modules.py) (sentencia `import`)
    - [Paquetes](src/modules/test_packages.py)
8. **Errores y excepciones**
    - [Controlando excepciones](src/exceptions/test_handle_exceptions.py) (sentencia `try`)
    - [Generando excepciones](src/exceptions/test_raise_exceptions.py) (sentencia `raise`) 
9. **Archivos**
    - [Leyendo y escribiendo](src/files/test_file_reading.py) (sentencia `with`)
    - [Métodos de objetos de archivo](src/files/test_file_methods.py)
10. **Adicionales**
    - [La sentencia `pass`](src/additions/test_pass.py)
    - [Generadores](src/additions/test_generators.py) (sentencia `yield`)
11. **Pequeño tour de las librerías estándar**
    - [Serialización](src/standard_libraries/test_json.py) (librería `json`)
    - [Parámetros en archivos](src/standard_libraries/test_glob.py) (librería `glob`)
    - [Expresiones regulares](src/standard_libraries/test_re.py) (librearía `re`)
    - [Matemática](src/standard_libraries/test_math.py) (librerías `math`, `random` y `statistics`)
    - [Fechas y horas](src/standard_libraries/test_datetime.py) (librería `datetime`)
    - [Compresión de datos](src/standard_libraries/test_zlib.py) (librearía `zlib`)

## Pre-requisitos

**Instalando Python**

Asegúrate de que tienes [Python3 instalado](https://realpython.com/installing-python/) en tu sistema.

Podrías utilizar la librería estándar [venv](https://docs.python.org/es/3/library/venv.html) para crear
entornos virtuales y tener Python, pip y todos los paquetes instalados en el directorio de tu
proyecto local para evitar cometer errores con paquetes del sistema y sus versiones.

Dependiendo de la instalación, tendrás acceso a Python3 ejecutando `python` o `python3`. Lo mismo
aplica para el administrador de paquetes pip - puedes tener acceso a él ejecutando `pip` o `pip3`.

Puedes ver tu versión actual de Python ejecutando:

```bash
python --version
```

Ten en cuenta que cuando leas `python` en este repositorio, se asume que es Python **3**.

**Instalando dependencias**

Instala todas las depencias requeridas para el proyecto ejecutando:

```bash
pip install -r requirements.txt
```

## Probando el código

Las pruebas son hechas usando el framework [pytest](https://docs.pytest.org/en/latest/).

Puedes añadir más pruebas por ti mismo añadiendo archivos y funciones con el prefijo `test_`
(ej: `test_topic.py` con la función `def test_sub_topic()` adentro).

Para ejecutar todas las pruebas, por favor escribe el siguiente comando desde el directorio
raíz del proyecto:

```bash
pytest
```

Para ejecutar diferentes pruebas escribe:

```bash
pytest ./path/to/the/test_file.py
```

## Revisando el código

La revisión del código está hecha usando las librerías [pylint](http://pylint.pycqa.org/) y [flake8](http://flake8.pycqa.org/en/latest/).

### PyLint

Para revisar si el código sigue la guía de estilos
[PEP 8](https://www.python.org/dev/peps/pep-0008/), por favor ejecuta:

```bash
pylint ./src/
```

En caso de que linter detecte un error (ej: `missing-docstring`), te recomiendo leer más sobre
el error concreto ejecutando:

```bash
pylint --help-msg=missing-docstring
```

[Más sobre PyLint](http://pylint.pycqa.org/)

### Flake8

Para revisar si el código sigue la guía de estilos
[PEP 8](https://www.python.org/dev/peps/pep-0008/), por favor ejecuta:

```bash
flake8 ./src
```

O, si quieres ver un output más detallado, ejecuta:

```bash
flake8 ./src --statistics --show-source --count
```

[Más sobre Flake8](http://flake8.pycqa.org/en/latest/)

## Apoya al proyecto

Puedes apoyar al proyecto a través de ❤️️ [GitHub](https://github.com/sponsors/trekhleb) o ❤️️ [Patreon](https://www.patreon.com/trekhleb).


================================================
FILE: README.md
================================================
# Playground and Cheatsheet for Learning Python

> 🇺🇦 UKRAINE [IS BEING ATTACKED](https://war.ukraine.ua/) BY RUSSIAN ARMY. CIVILIANS ARE GETTING KILLED. RESIDENTIAL AREAS ARE GETTING BOMBED.
> - Help Ukraine via:
>   - [Serhiy Prytula Charity Foundation](https://prytulafoundation.org/en/)
>   - [Come Back Alive Charity Foundation](https://savelife.in.ua/en/donate-en/)
>   - [National Bank of Ukraine](https://bank.gov.ua/en/news/all/natsionalniy-bank-vidkriv-spetsrahunok-dlya-zboru-koshtiv-na-potrebi-armiyi)
> - More info on [war.ukraine.ua](https://war.ukraine.ua/) and [MFA of Ukraine](https://twitter.com/MFA_Ukraine)

<hr/>

[![Build Status](https://travis-ci.org/trekhleb/learn-python.svg?branch=master)](https://travis-ci.org/trekhleb/learn-python)

> This is a collection of Python scripts that are split by [topics](#table-of-contents) and contain 
code examples with explanations, different use cases and links to further readings.

> _Read this in:_ [_Português_](README.pt-BR.md), [_Español_](README.es-ES.md), [_Traditional Chinese_](README.zh-TW.md).

It is a **playground** because you may change or add the code to see how it works 
and [test it out](#testing-the-code) using assertions. It also allows you 
to [lint the code](#linting-the-code) you've wrote and check if it fits to Python code style guide.
Altogether it might make your learning process to be more interactive and it might help you to keep 
code quality pretty high from very beginning.

It is a **cheatsheet** because you may get back to these code examples once you want to recap the 
syntax of [standard Python statements and constructions](#table-of-contents). Also because the 
code is full of assertions you'll be able to see expected functions/statements output right away
without launching them.

> _You might also be interested in 🤖 [Interactive Machine Learning Experiments](https://github.com/trekhleb/machine-learning-experiments)_

## How to Use This Repository

Each Python script in this repository has the following structure:

```python
"""Lists  <--- Name of the topic here

# @see: https://www.learnpython.org/en/Lists  <-- Link to further readings goes here

Here might go more detailed explanation of the current topic (i.e. general info about Lists).
"""


def test_list_type():
    """Explanation of sub-topic goes here.
    
    Each file contains test functions that illustrate sub-topics (i.e. lists type, lists methods).
    """
    
    # Here is an example of how to build a list.  <-- Comments here explain the action
    squares = [1, 4, 9, 16, 25]
    
    # Lists can be indexed and sliced. 
    # Indexing returns the item.
    assert squares[0] == 1  # <-- Assertions here illustrate the result.
    # Slicing returns a new list.
    assert squares[-3:] == [9, 16, 25]  # <-- Assertions here illustrate the result.
```

So normally you might want to do the following:

- [Find the topic](#table-of-contents) you want to learn or recap.
- Read comments and/or documentation that is linked in each script's docstring (as in example above). 
- Look at code examples and assertions to see usage examples and expected output.
- Change code or add new assertions to see how things work.
- [Run tests](#testing-the-code) and [lint the code](#linting-the-code) to see if it work and is 
written correctly.

## Table of Contents

1. **Getting Started**
    - [What is Python](src/getting_started/what_is_python.md)
    - [Python Syntax](src/getting_started/python_syntax.md)
    - [Variables](src/getting_started/test_variables.py)
2. **Operators**
    - [Arithmetic Operators](src/operators/test_arithmetic.py) (`+`, `-`, `*`, `/`, `//`, `%`, `**`)
    - [Bitwise Operators](src/operators/test_bitwise.py) (`&`, `|`, `^`, `>>`, `<<`, `~`)
    - [Assignment Operators](src/operators/test_assigment.py) (`=`, `+=`, `-=`, `/=`, `//=` etc.)
    - [Comparison Operator](src/operators/test_comparison.py) (`==`, `!=`, `>`, `<`, `>=`, `<=`)
    - [Logical Operators](src/operators/test_logical.py) (`and`, `or`, `not`)
    - [Identity Operators](src/operators/test_identity.py) (`is`, `is not`)
    - [Membership Operators](src/operators/test_membership.py) (`in`, `not in`)
3. **Data Types**
    - [Numbers](src/data_types/test_numbers.py) (including booleans)
    - [Strings](src/data_types/test_strings.py) and their methods
    - [Lists](src/data_types/test_lists.py) and their methods (including list comprehensions)
    - [Tuples](src/data_types/test_tuples.py)
    - [Sets](src/data_types/test_sets.py) and their methods
    - [Dictionaries](src/data_types/test_dictionaries.py)
    - [Type Casting](src/data_types/test_type_casting.py)
4. **Control Flow**
    - [The `if` statement](src/control_flow/test_if.py)
    - [The `for` statement](src/control_flow/test_for.py) (and `range()` function)
    - [The `while` statement](src/control_flow/test_while.py)
    - [The `try` statements](src/control_flow/test_try.py)
    - [The `break` statement](src/control_flow/test_break.py)
    - [The `continue` statement](src/control_flow/test_continue.py)
5. **Functions**
    - [Function Definition](src/functions/test_function_definition.py) (`def` and `return` statements)
    - [Scopes of Variables Inside Functions](src/functions/test_function_scopes.py) (`global` and `nonlocal` statements)
    - [Default Argument Values](src/functions/test_function_default_arguments.py)
    - [Keyword Arguments](src/functions/test_function_keyword_arguments.py)
    - [Arbitrary Argument Lists](src/functions/test_function_arbitrary_arguments.py)
    - [Unpacking Argument Lists](src/functions/test_function_unpacking_arguments.py) (`*` and `**` statements)
    - [Lambda Expressions](src/functions/test_lambda_expressions.py) (`lambda` statement)
    - [Documentation Strings](src/functions/test_function_documentation_string.py)
    - [Function Annotations](src/functions/test_function_annotations.py)
    - [Function Decorators](src/functions/test_function_decorators.py)
6. **Classes**
    - [Class Definition](src/classes/test_class_definition.py) (`class` statement)
    - [Class Objects](src/classes/test_class_objects.py)
    - [Instance Objects](src/classes/test_instance_objects.py)
    - [Method Objects](src/classes/test_method_objects.py)
    - [Class and Instance Variables](src/classes/test_class_and_instance_variables.py)
    - [Inheritance](src/classes/test_inheritance.py)
    - [Multiple Inheritance](src/classes/test_multiple_inheritance.py)
7. **Modules**
    - [Modules](src/modules/test_modules.py) (`import` statement)
    - [Packages](src/modules/test_packages.py)
8. **Errors and Exceptions**
    - [Handling Exceptions](src/exceptions/test_handle_exceptions.py) (`try` statement)
    - [Raising Exceptions](src/exceptions/test_raise_exceptions.py) (`raise` statement)
9. **Files**
    - [Reading and Writing](src/files/test_file_reading.py) (`with` statement)
    - [Methods of File Objects](src/files/test_file_methods.py)
10. **Additions**
    - [The `pass` statement](src/additions/test_pass.py)
    - [Generators](src/additions/test_generators.py) (`yield` statement)
11. **Brief Tour of the Standard Libraries**
    - [Serialization](src/standard_libraries/test_json.py) (`json` library)
    - [File Wildcards](src/standard_libraries/test_glob.py) (`glob` library)
    - [String Pattern Matching](src/standard_libraries/test_re.py) (`re` library)
    - [Mathematics](src/standard_libraries/test_math.py) (`math`, `random`, `statistics` libraries)
    - [Dates and Times](src/standard_libraries/test_datetime.py) (`datetime` library)
    - [Data Compression](src/standard_libraries/test_zlib.py) (`zlib` library)
12. **User input**
    - [Terminal input](src/user_input/test_input.py) (`input` statement)

## Prerequisites

**Installing Python**

Make sure that you have [Python3 installed](https://realpython.com/installing-python/) on your machine.

You might want to use [venv](https://docs.python.org/3/library/venv.html) standard Python library
to create virtual environments and have Python, pip and all dependent packages to be installed and 
served from the local project directory to avoid messing with system wide packages and their 
versions.

Depending on your installation you might have access to Python3 interpreter either by
running `python` or `python3`. The same goes for pip package manager - it may be accessible either
by running `pip` or `pip3`.

You may check your Python version by running:

```bash
python --version
```

Note that in this repository whenever you see `python` it will be assumed that it is Python **3**.

**Installing dependencies**

Install all dependencies that are required for the project by running:

```bash
pip install -r requirements.txt
```

## Testing the Code

Tests are made using [pytest](https://docs.pytest.org/en/latest/) framework.

You may add new tests for yourself by adding files and functions with `test_` prefix
(i.e. `test_topic.py` with `def test_sub_topic()` function inside).

To run all the tests please execute the following command from the project root folder:

```bash
pytest
```

To run specific tests please execute:

```bash
pytest ./path/to/the/test_file.py
```

## Linting the Code

Linting is done using [pylint](http://pylint.pycqa.org/) and [flake8](http://flake8.pycqa.org/en/latest/) libraries.

### PyLint

To check if the code is written with respect
to [PEP 8](https://www.python.org/dev/peps/pep-0008/) style guide please run:

```bash
pylint ./src/
```

In case if linter will detect error (i.e. `missing-docstring`) you may want to read more about 
specific error by running:

```bash
pylint --help-msg=missing-docstring
```

[More about PyLint](http://pylint.pycqa.org/)

### Flake8

To check if the code is written with respect
to [PEP 8](https://www.python.org/dev/peps/pep-0008/) style guide please run:

```bash
flake8 ./src
```

Or if you want to have more detailed output you may run:

```bash
flake8 ./src --statistics --show-source --count
```

[More about Flake8](http://flake8.pycqa.org/en/latest/)

## Author

- [@trekhleb](https://trekhleb.dev)


================================================
FILE: README.pt-BR.md
================================================
# Playground e Cheatsheet Para Aprender Python

[![Build Status](https://travis-ci.org/trekhleb/learn-python.svg?branch=master)](https://travis-ci.org/trekhleb/learn-python)

> Essa é uma coleção de scripts Python dividida em [tópicos](#índice) que contém 
exemplos de código com explicações, diferentes usos e links para outras leituras.

> _Ler em:_ [_English_](README.md), [_Español_](README.es-ES.md), [_Traditional Chinese_](README.zh-TW.md).

É um **playground** porque você pode fazer alterações no código para ver como ele se comporta,
além de [testá-lo](#testando-o-código) usando asserções. Também é possível 
[revisar o código](#revisando-o-código) que você escreveu automaticamente e verificar se ele se encaixa
no guia de estilo de código Python.
Isso tudo pode tornar seu processo de aprendizagem mais interativo e ajudar a manter a qualidade
do código bastante alta desde o início.

É um **cheatsheet** porque você pode voltar a esses exemplos de código quando quiser recapitular a sintaxe das 
[estruturas padrão do Python](#índice). O código está cheio de asserções, então você poderá ver o retorno das funções sem precisar executá-las.

> _Você pode se interessar também por 🤖 [Interactive Machine Learning Experiments](https://github.com/trekhleb/machine-learning-experiments)_

## Como Usar Esse Repositório

Nesse repositório, cada script Python possui a seguinte estrutura:

```python
"""Lists  <--- Nome do tópico

# @see: https://www.learnpython.org/en/Lists  <-- Link para outras leituras.

A seguir, uma explicação mais detalhada do tópico atual (ex, informações gerais sobre listas (Lists)).
"""


def test_list_type():
    """Explicação do subtópico.
    
    Cada arquivo contém funções de teste que ilustram subtópicos (ou seja, tipo de lista, métodos de lista).
    """
    
    # Here is an example of how to build a list.  <-- Comentários em inglês explicam a ação.
    squares = [1, 4, 9, 16, 25]
    
    # Lists can be indexed and sliced. 
    # Indexing returns the item.
    assert squares[0] == 1  # <-- As asserções ilustram o resultado.
    # Slicing returns a new list.
    assert squares[-3:] == [9, 16, 25]  # <-- As asserções ilustram o resultado.
```

Então você pode querer fazer o seguinte:

- [Encontrar o tópico](#índice) que deseja aprender ou recapitular.
- Ler os comentários e/ou a documentação vinculada em cada script (como no exemplo acima).
- Analisar os exemplos e asserções para ver exemplos de uso e saída esperada das funções.
- Alterar o código ou adicionar novas asserções para ver o que acontece.
- [Executar testes](#testando-o-código) e [revisar o código](#revisando-o-código) para ver se ele
funciona e para saber se está escrito corretamente. 

## Índice

1. **Começando**
    - [O que é Python](src/getting_started/what_is_python.md)
    - [Sintaxe Python](src/getting_started/python_syntax.md)
    - [Variáveis](src/getting_started/test_variables.py)
2. **Operadores**
    - [Operadores Aritméticos](src/operators/test_arithmetic.py) (`+`, `-`, `*`, `/`, `//`, `%`, `**`)
    - [Operadores Bitwise](src/operators/test_bitwise.py) (`&`, `|`, `^`, `>>`, `<<`, `~`)
    - [Operadores de Atribuição](src/operators/test_assigment.py) (`=`, `+=`, `-=`, `/=`, `//=` etc.)
    - [Operadores de Comparação](src/operators/test_comparison.py) (`==`, `!=`, `>`, `<`, `>=`, `<=`)
    - [Operadores Lógicos](src/operators/test_logical.py) (`and`, `or`, `not`)
    - [Operadores de Indentidade](src/operators/test_identity.py) (`is`, `is not`)
    - [Operadores de Associação](src/operators/test_membership.py) (`in`, `not in`)
3. **Tipos de Dados**
    - [Números](src/data_types/test_numbers.py) (incluindo boleanos)
    - [Strings](src/data_types/test_strings.py) e seus métodos
    - [Listas](src/data_types/test_lists.py) e seus métodos (incluindo lista de compreensões)
    - [Tuplas](src/data_types/test_tuples.py)
    - [Conjuntos](src/data_types/test_sets.py) e seus métodos
    - [Dicionários](src/data_types/test_dictionaries.py)
    - [Casting de Tipo](src/data_types/test_type_casting.py)
4. **Controles de Fluxo**
    - [A declaração `if`](src/control_flow/test_if.py)
    - [A declaração `for`](src/control_flow/test_for.py) (e a função `range()`)
    - [A declaração `while`](src/control_flow/test_while.py)
    - [A declaração `try`](src/control_flow/test_try.py)
    - [A declaração `break`](src/control_flow/test_break.py)
    - [A declaração `continue`](src/control_flow/test_continue.py)
5. **Funções**
    - [Definição de Função](src/functions/test_function_definition.py) (declaração `def` e `return`)
    - [Variáveis Dentro das Funções](src/functions/test_function_scopes.py) (declaração `global` e `nonlocal`)
    - [Valores Padrão de Argumentos](src/functions/test_function_default_arguments.py)
    - [Argumentos de palavras-chave](src/functions/test_function_keyword_arguments.py)
    - [Listas de Argumento Arbitrárias](src/functions/test_function_arbitrary_arguments.py)
    - [Desfazendo Lista de Argumentos](src/functions/test_function_unpacking_arguments.py) (declaração `*` e `**`)
    - [Expressões Lambda](src/functions/test_lambda_expressions.py) (declaração `lambda`)
    - [Documentação das Strings](src/functions/test_function_documentation_string.py)
    - [Função de Anotações](src/functions/test_function_annotations.py)
    - [Função de Decoradores](src/functions/test_function_decorators.py)
6. **Classes**
    - [Definição de Classe](src/classes/test_class_definition.py) (declaração `class`)
    - [Classes dos Objetos](src/classes/test_class_objects.py)
    - [Instância dos Objetos](src/classes/test_instance_objects.py)
    - [Métodos de Objetos](src/classes/test_method_objects.py)
    - [Variável de Classe e Instância](src/classes/test_class_and_instance_variables.py)
    - [Herança](src/classes/test_inheritance.py)
    - [Herança Múltipla](src/classes/test_multiple_inheritance.py)
7. **Módulos**
    - [Módulos](src/modules/test_modules.py) (declaração `import`)
    - [Pacotes](src/modules/test_packages.py)
8. **Erros e Exceções**
    - [Tratando Exceções](src/exceptions/test_handle_exceptions.py) (declaração `try`)
    - [Levantando Exceções](src/exceptions/test_raise_exceptions.py) (declaração `raise`) 
9. **Arquivos**
    - [Lendo e Escrevendo](src/files/test_file_reading.py) (declaração `with`)
    - [Métodos de Objetos de Arquivos](src/files/test_file_methods.py)
10. **Adicional**
    - [A declaração `pass`](src/additions/test_pass.py)
    - [Geradores](src/additions/test_generators.py) (declaração `yield`)
11. **Algumas Bibliotecas Padrão**
    - [Serialization](src/standard_libraries/test_json.py) (biblioteca `json`)
    - [File Wildcards](src/standard_libraries/test_glob.py) (biblioteca `glob`)
    - [String Pattern Matching](src/standard_libraries/test_re.py) (biblioteca `re`)
    - [Matemática](src/standard_libraries/test_math.py) (bibliotecas `math`, `random` e `statistics`)
    - [Tempo e Datas](src/standard_libraries/test_datetime.py) (biblioteca `datetime`)
    - [Comprimindo Dados](src/standard_libraries/test_zlib.py) (biblioteca `zlib`)

## Pré-requisitos

**Instalando o Python**

Certifique-se de ter o [Python3 instalado](https://realpython.com/installing-python/) em sua máquina.

Você pode usar a biblioteca padrão do Python [venv](https://docs.python.org/3/library/venv.html)
para criar ambientes virtuais e ter o Python, pip e todos os outros pacotes a serem instalados
 a partir do diretório local do projeto para evitar mexer com pacotes externos ou do sistema.

Dependendo da sua instalação, você pode ter acesso ao interpretador Python3 executando `python` ou `python3`. O mesmo vale para o gerenciador de pacotes pip, você pode acessá-lo executando `pip` ou `pip3`.

Você pode ver a versão do seu Python executando:

```bash
python --version
```

Observe que neste repositório sempre que você vê o `python`, será assumido que é o Python **3**.

**Instalando dependências**

Instale todas as dependências necessárias para o projeto executando:

```bash
pip install -r requirements.txt
```

## Testando o Código

Testes são feitos usando o framework [pytest](https://docs.pytest.org/en/latest/).

Você pode adicionar novos testes criando arquivos e funções com o prefixo `test_` 
(ex. `test_topic.py` com a função `def test_sub_topic()` dentro).

Para executar todos os testes, execute o seguinte comando na pasta raiz do projeto:

```bash
pytest
```

Para executar testes específicos, execute:

```bash
pytest ./path/to/the/test_file.py
```

## Revisando o Código

A revisão é feita usando as bibliotecas [pylint](http://pylint.pycqa.org/) e [flake8](http://flake8.pycqa.org/en/latest/).

### PyLint

Para verificar se o código está escrito de acordo com o guia de estilo 
do [PEP 8](https://www.python.org/dev/peps/pep-0008/), execute:

```bash
pylint ./src/
```

Caso o pylint detecte um erro (ex. `missing-docstring`), convém ler mais sobre erros específicos executando:

```bash
pylint --help-msg=missing-docstring
```

[Saber mais sobre PyLint](http://pylint.pycqa.org/)

### Flake8

Para verificar se o código está escrito de acordo com o guia de estilo 
do [PEP 8](https://www.python.org/dev/peps/pep-0008/), execute:

```bash
flake8 ./src
```

Ou, se você quiser uma saída mais detalhada, execute:

```bash
flake8 ./src --statistics --show-source --count
```

[Saber mais sobre Flake8](http://flake8.pycqa.org/en/latest/)

---

Traduzido por [vilmacio22](https://github.com/vilmacio22).


================================================
FILE: README.zh-TW.md
================================================
# 學習 Python 的練習場(Playground)和速查表(Cheatsheet)

[![Build Status](https://travis-ci.org/trekhleb/learn-python.svg?branch=master)](https://travis-ci.org/trekhleb/learn-python)

> 此專案依據 [目錄](#目錄) 分類收集了 Python 腳本,包含了程式碼範例及解釋、不同的使用情境以及衍伸閱讀連結。

> _閱讀英文原始版本:_ [_English_](README.md), [_Português_](README.pt-BR.md), [_Español_](README.es-ES.md).

此專案名稱之所以叫做 **練習場(Playground)**,是因為您可以修改或是新增程式碼至範例中去觀察程式執行流程並使用斷言關鍵字(assert)來 [測試程式](#測試程式)。同時,此專案也使用了業界常用的工具來 [檢查程式碼](#檢查程式碼),確保您所撰寫的程式碼符合官方建議的 Python 程式碼風格規範。

總而言之,此專案會使您的學習過程更具互動性,並幫助您從一開始學習的時候就使用高品質的程式碼。

此專案名稱之所以也包含了 **速查表(Cheatsheet)** 是因為您可以隨時透過此專案中的 [標準 Python 陳述式以及結構](#目錄) 回顧程式碼語法,也因為在此專案中的每個程式碼範例都使用了斷言來說明及教學,故您可以不用執行程式就看到函式/陳述式的預期輸出結果。

> 若對機器學習(Machine Learning)有興趣,可以參考專案原作者的另一個學習專案:🤖 [Interactive Machine Learning Experiments](https://github.com/trekhleb/machine-learning-experiments)

## 如何使用此專案儲存庫

在此專案儲存庫中的每一個 Python 腳本皆為以下結構:

```python
"""串列(Lists) <--- 此為主題名稱

# @詳見: https://www.learnpython.org/en/Lists <-- 此為延伸閱讀連結

此處可能會有針對此主題更多的詳細說明(例如:關於串列的基本使用方法)
"""

def test_list_type():
    """此處為子主題解釋

    每個檔案皆包含說明該子主題的測試函式(例如:串列型態、串列方法)
    """

    # 建立串列之範例 <-- 此行是解釋下一行程式碼動作之註解
    squares = [1, 4, 9, 16, 25]

    # 串列可以被索引(indexed)及切片(sliced)
    # 索引會回傳該索引位置之內容值
    assert squares[0] == 1 # <-- 利用斷言來呈現結果
    # 切片會回傳一個新的串列
    assert squares[-3:] == [9, 16, 25] # <-- 利用斷言來呈現結果
```

故您可以做以下動作:

- 找一個您想要學習或是回顧的 [主題](#目錄)。
- 閱讀註解及/或包含於腳本文件字串(docstring)中的延伸閱讀資料(如上述之程式碼範例)。
- 查看程式碼範例並利用斷言來展示使用範例及預期輸出。
- 修改程式碼或新增新的斷言來了解程式運作流程。
- [執行測試](#測試程式) 及 [檢查程式碼](#檢查程式碼) 來確認程式是否被正確撰寫及是否可以被正確執行。

## 目錄

1. **入門**
    - [Python 是什麼](src/getting_started/what_is_python.md)
    - [Python 語法](src/getting_started/python_syntax.md)
    - [變數](src/getting_started/test_variables.py)
2. **運算子**
    - [數學運算子](src/operators/test_arithmetic.py) (`+`, `-`, `*`, `/`, `//`, `%`, `**`)
    - [位元運算子](src/operators/test_bitwise.py) (`&`, `|`, `^`, `>>`, `<<`, `~`)
    - [指派運算子](src/operators/test_assigment.py) (`=`, `+=`, `-=`, `/=`, `//=` 等 ...)
    - [比較運算子](src/operators/test_comparison.py) (`==`, `!=`, `>`, `<`, `>=`, `<=`)
    - [邏輯運算子](src/operators/test_logical.py) (`and`, `or`, `not`)
    - [恆等運算子](src/operators/test_identity.py) (`is`, `is not`)
    - [成員存取運算子](src/operators/test_membership.py) (`in`, `not in`)
3. **資料類型**
    - [數字](src/data_types/test_numbers.py)(包含布林值)
    - [字串](src/data_types/test_strings.py) 及相關方法
    - [串列](src/data_types/test_lists.py) 及相關方法(包含列表構建)
    - [元組](src/data_types/test_tuples.py)
    - [集合](src/data_types/test_sets.py) 及相關方法
    - [字典](src/data_types/test_dictionaries.py)
    - [類型轉換](src/data_types/test_type_casting.py)
4. **流程控制**
    - [`if` 陳述式](src/control_flow/test_if.py)
    - [`for` 陳述式](src/control_flow/test_for.py) (以及 `range()` 函式)
    - [`while` 陳述式](src/control_flow/test_while.py)
    - [`try` 陳述式](src/control_flow/test_try.py)
    - [`break` 陳述式](src/control_flow/test_break.py)
    - [`continue` 陳述式](src/control_flow/test_continue.py)
5. **函式**
    - [函式定義](src/functions/test_function_definition.py)(`def` 以及 `return` 陳述式)
    - [函式內變數作用範圍](src/functions/test_function_scopes.py)(`global` 以及 `nonlocal` 陳述式)
    - [預設引數](src/functions/test_function_default_arguments.py)
    - [關鍵字引數](src/functions/test_function_keyword_arguments.py)
    - [任意引數串列](src/functions/test_function_arbitrary_arguments.py)
    - [拆解引數串列](src/functions/test_function_unpacking_arguments.py)(`*` 以及 `**` 陳述式)
    - [Lambda 表達式](src/functions/test_lambda_expressions.py) (`lambda` 陳述式)
    - [文件字串](src/functions/test_function_documentation_string.py)
    - [函式註釋](src/functions/test_function_annotations.py)
    - [函式裝飾器](src/functions/test_function_decorators.py)
6. **類別**
    - [類別定義](src/classes/test_class_definition.py) (`class` 陳述式)
    - [類別物件](src/classes/test_class_objects.py)
    - [物件實體](src/classes/test_instance_objects.py)
    - [物件方法](src/classes/test_method_objects.py)
    - [類別及實體變數](src/classes/test_class_and_instance_variables.py)
    - [繼承](src/classes/test_inheritance.py)
    - [多重繼承](src/classes/test_multiple_inheritance.py)
7. **模組**
    - [模組](src/modules/test_modules.py) (`import` 陳述式)
    - [套件](src/modules/test_packages.py)
8. **錯誤和例外**
    - [例外處理](src/exceptions/test_handle_exceptions.py) (`try` 陳述式)
    - [例外引發](src/exceptions/test_raise_exceptions.py) (`raise` 陳述式)
9. **檔案**
    - [讀取和寫入](src/files/test_file_reading.py) (`with` 陳述式)
    - [檔案物件方法](src/files/test_file_methods.py)
10. **附加內容**
    - [`pass` 陳述式](src/additions/test_pass.py)
    - [生成器](src/additions/test_generators.py) (`yield` 陳述式)
11. **標準函式庫簡介**
    - [串列化](src/standard_libraries/test_json.py) (`json` 函式庫)
    - [檔案萬用字元](src/standard_libraries/test_glob.py) (`glob` 函式庫)
    - [字串規則比對](src/standard_libraries/test_re.py) (`re` 函式庫)
    - [數學運算](src/standard_libraries/test_math.py) (`math`, `random`, `statistics` 函式庫)
    - [日期和時間](src/standard_libraries/test_datetime.py) (`datetime` 函式庫)
    - [資料壓縮](src/standard_libraries/test_zlib.py) (`zlib` 函式庫)

## 使用此專案必備條件

**安裝 Python**

確認您已安裝 [Python3](https://realpython.com/installing-python/) 在您的電腦上。

您可能會想要使用標準 Python 函式庫所提供的 [虛擬環境](https://docs.python.org/3/library/venv.html) 功能在專案目錄中建立虛擬環境來佈署 Python 程式、pip 程式以及安裝所有需要的套件,藉此來避免作業系統中 Python 版本及相依性的混亂。

根據您的安裝方法,您可能可以通過以下方式執行 Python 3 直譯器:執行 `python` 或 `python3` 命令。pip 套件管理器執行方式也是如此:執行 `pip` 或 `pip3`。

您可以使用以下命令來確認 Python 版本:

```bash
python --version
```

此專案儲存庫中的所有程式碼皆是基於 Python **3**。

**安裝相依性套件**

透過以下命令安裝此專案需要的相依性套件:

```bash
pip install -r requirements.txt
```

## 測試程式

此專案使用 [pytest](https://docs.pytest.org/en/latest/) 測試框架來執行程式碼測試。

您可以新增以 `test_` 為開頭的檔案/函式來新增測試。(例如:`test_topic.py` 檔案內有 `def test_sub_topic()` 測試函式)

請從專案根目錄下使用以下命令來執行所有測試:

```bash
pytest
```

您也可以使用以下命令執行特定測試:

```bash
pytest ./path/to/the/test_file.py
```

## 檢查程式碼

此專案使用 [pylint](http://pylint.pycqa.org/) 以及 [flake8](http://flake8.pycqa.org/en/latest/) 函式庫來執行程式碼檢查。

### PyLint

檢查撰寫之程式碼是否符合 [PEP 8](https://www.python.org/dev/peps/pep-0008/) 風格規範,請執行以下命令:

```bash
pylint ./src/
```

若此檢查工具偵測到錯誤(例如:`missing-docstring`),您可以使用以下命令查看特定錯誤之詳細說明:

```bash
pylint --help-msg=missing-docstring
```

[更多關於 PyLint](http://pylint.pycqa.org/)

### Flake8

檢查撰寫之程式碼是否符合 [PEP 8](https://www.python.org/dev/peps/pep-0008/) 風格規範,請執行以下命令:

```bash
flake8 . /src
```

若您希望得到更多詳細的輸出,您可以加上以下參數再執行此工具:

```bash
flake8 . /src --statistics --show-source --count
```

[更多關於 Flake8](http://flake8.pycqa.org/en/latest/)

## 支持此專案

您可以透過 ❤️️ [GitHub](https://github.com/sponsors/trekhleb) 或 ❤️️ [Patreon](https://www.patreon.com/trekhleb) 支持原作者專案


================================================
FILE: _config.yml
================================================
theme: jekyll-theme-minimal

================================================
FILE: pylintrc
================================================
[MASTER]

# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code.
extension-pkg-whitelist=

# Add files or directories to the blacklist. They should be base names, not
# paths.
ignore=CVS

# Add files or directories matching the regex patterns to the blacklist. The
# regex matches against base names, not paths.
ignore-patterns=

# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
# @TODO: Figure out how to AVOID HARD-CODING of sys.path in order to make pylint work with relative module imports
init-hook='sys.path.append('./src/modules')'

# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
# number of processors available to use.
jobs=1

# Control the amount of potential inferred values when inferring a single
# object. This can help the performance when dealing with large functions or
# complex, nested conditions.
limit-inference-results=100

# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=

# Pickle collected data for later comparisons.
persistent=yes

# Specify a configuration file.
#rcfile=

# When enabled, pylint would attempt to guess common misconfiguration and emit
# user-friendly hints instead of false-positive error messages.
suggestion-mode=yes

# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no


[MESSAGES CONTROL]

# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED.
confidence=

# Disable the message, report, category or checker with the given id(s). You
# can either give multiple identifiers separated by comma (,) or put this
# option multiple times (only on the command line, not in the configuration
# file where it should appear only once). You can also use "--disable=all" to
# disable everything first and then reenable specific checks. For example, if
# you want to run only the similarities checker, you can use "--disable=all
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use "--disable=all --enable=classes
# --disable=W".
disable=print-statement,
        parameter-unpacking,
        unpacking-in-except,
        old-raise-syntax,
        backtick,
        long-suffix,
        old-ne-operator,
        old-octal-literal,
        import-star-module-level,
        non-ascii-bytes-literal,
        raw-checker-failed,
        bad-inline-option,
        locally-disabled,
        locally-enabled,
        file-ignored,
        suppressed-message,
        useless-suppression,
        deprecated-pragma,
        use-symbolic-message-instead,
        apply-builtin,
        basestring-builtin,
        buffer-builtin,
        cmp-builtin,
        coerce-builtin,
        execfile-builtin,
        file-builtin,
        long-builtin,
        raw_input-builtin,
        reduce-builtin,
        standarderror-builtin,
        unicode-builtin,
        xrange-builtin,
        coerce-method,
        delslice-method,
        getslice-method,
        setslice-method,
        no-absolute-import,
        old-division,
        dict-iter-method,
        dict-view-method,
        next-method-called,
        metaclass-assignment,
        indexing-exception,
        raising-string,
        reload-builtin,
        oct-method,
        hex-method,
        nonzero-method,
        cmp-method,
        input-builtin,
        round-builtin,
        intern-builtin,
        unichr-builtin,
        map-builtin-not-iterating,
        zip-builtin-not-iterating,
        range-builtin-not-iterating,
        filter-builtin-not-iterating,
        using-cmp-argument,
        eq-without-hash,
        div-method,
        idiv-method,
        rdiv-method,
        exception-message-attribute,
        invalid-str-codec,
        sys-max-int,
        bad-python3-import,
        deprecated-string-function,
        deprecated-str-translate-call,
        deprecated-itertools-function,
        deprecated-types-field,
        next-method-defined,
        dict-items-not-iterating,
        dict-keys-not-iterating,
        dict-values-not-iterating,
        deprecated-operator-function,
        deprecated-urllib-function,
        xreadlines-attribute,
        deprecated-sys-function,
        exception-escape,
        comprehension-escape

# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once). See also the "--disable" option for examples.
enable=c-extension-no-member


[REPORTS]

# Python expression which should return a note less than 10 (10 is the highest
# note). You have access to the variables errors warning, statement which
# respectively contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation report
# (RP0004).
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)

# Template used to display messages. This is a python new-style format string
# used to format the message information. See doc for all details.
#msg-template=

# Set the output format. Available formats are text, parseable, colorized, json
# and msvs (visual studio). You can also give a reporter class, e.g.
# mypackage.mymodule.MyReporterClass.
output-format=text

# Tells whether to display a full report or only the messages.
reports=no

# Activate the evaluation score.
score=yes


[REFACTORING]

# Maximum number of nested blocks for function / method body
max-nested-blocks=5

# Complete name of functions that never returns. When checking for
# inconsistent-return-statements if a never returning function is called then
# it will be considered as an explicit return statement and no message will be
# printed.
never-returning-functions=sys.exit


[LOGGING]

# Logging modules to check that the string format arguments are in logging
# function parameter format.
logging-modules=logging


[SPELLING]

# Limits count of emitted suggestions for spelling mistakes.
max-spelling-suggestions=4

# Spelling dictionary name. Available dictionaries: none. To make it working
# install python-enchant package..
spelling-dict=

# List of comma separated words that should not be checked.
spelling-ignore-words=

# A path to a file that contains private dictionary; one word per line.
spelling-private-dict-file=

# Tells whether to store unknown words to indicated private dictionary in
# --spelling-private-dict-file option instead of raising a message.
spelling-store-unknown-words=no


[MISCELLANEOUS]

# List of note tags to take in consideration, separated by a comma.
notes=FIXME,
      XXX,
      TODO


[TYPECHECK]

# List of decorators that produce context managers, such as
# contextlib.contextmanager. Add to this list to register other decorators that
# produce valid context managers.
contextmanager-decorators=contextlib.contextmanager

# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=

# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes

# Tells whether to warn about missing members when the owner of the attribute
# is inferred to be None.
ignore-none=yes

# This flag controls whether pylint should warn about no-member and similar
# checks whenever an opaque object is returned when inferring. The inference
# can return multiple potential results while evaluating a Python object, but
# some branches might not be evaluated, which results in partial inference. In
# that case, it might be useful to still emit no-member and other checks for
# the rest of the inferred objects.
ignore-on-opaque-inference=yes

# List of class names for which member attributes should not be checked (useful
# for classes with dynamically set attributes). This supports the use of
# qualified names.
ignored-classes=optparse.Values,thread._local,_thread._local

# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=

# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
missing-member-hint=yes

# The minimum edit distance a name should have in order to be considered a
# similar match for a missing member name.
missing-member-hint-distance=1

# The total number of similar names that should be taken in consideration when
# showing a hint for a missing member.
missing-member-max-choices=1


[VARIABLES]

# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
additional-builtins=

# Tells whether unused global variables should be treated as a violation.
allow-global-unused-variables=yes

# List of strings which can identify a callback function by name. A callback
# name must start or end with one of those strings.
callbacks=cb_,
          _cb

# A regular expression matching the name of dummy variables (i.e. expected to
# not be used).
dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_

# Argument names that match this expression will be ignored. Default to name
# with leading underscore.
ignored-argument-names=_.*|^ignored_|^unused_

# Tells whether we should check for unused import in __init__ files.
init-import=no

# List of qualified module names which can have objects that can redefine
# builtins.
redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io


[FORMAT]

# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=

# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$

# Number of spaces of indent required inside a hanging  or continued line.
indent-after-paren=4

# String used as indentation unit. This is usually "    " (4 spaces) or "\t" (1
# tab).
indent-string='    '

# Maximum number of characters on a single line.
max-line-length=100

# Maximum number of lines in a module.
max-module-lines=1000

# List of optional constructs for which whitespace checking is disabled. `dict-
# separator` is used to allow tabulation in dicts, etc.: {1  : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
no-space-check=trailing-comma,
               dict-separator

# Allow the body of a class to be on the same line as the declaration if body
# contains single statement.
single-line-class-stmt=no

# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no


[SIMILARITIES]

# Ignore comments when computing similarities.
ignore-comments=yes

# Ignore docstrings when computing similarities.
ignore-docstrings=yes

# Ignore imports when computing similarities.
ignore-imports=no

# Minimum lines number of a similarity.
min-similarity-lines=4


[BASIC]

# Naming style matching correct argument names.
argument-naming-style=snake_case

# Regular expression matching correct argument names. Overrides argument-
# naming-style.
#argument-rgx=

# Naming style matching correct attribute names.
attr-naming-style=snake_case

# Regular expression matching correct attribute names. Overrides attr-naming-
# style.
#attr-rgx=

# Bad variable names which should always be refused, separated by a comma.
bad-names=foo,
          bar,
          baz,
          toto,
          tutu,
          tata

# Naming style matching correct class attribute names.
class-attribute-naming-style=any

# Regular expression matching correct class attribute names. Overrides class-
# attribute-naming-style.
#class-attribute-rgx=

# Naming style matching correct class names.
class-naming-style=PascalCase

# Regular expression matching correct class names. Overrides class-naming-
# style.
#class-rgx=

# Naming style matching correct constant names.
const-naming-style=UPPER_CASE

# Regular expression matching correct constant names. Overrides const-naming-
# style.
#const-rgx=

# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1

# Naming style matching correct function names.
function-naming-style=snake_case

# Regular expression matching correct function names. Overrides function-
# naming-style.
#function-rgx=

# Good variable names which should always be accepted, separated by a comma.
good-names=i,
           j,
           k,
           ex,
           Run,
           _

# Include a hint for the correct naming format with invalid-name.
include-naming-hint=no

# Naming style matching correct inline iteration names.
inlinevar-naming-style=any

# Regular expression matching correct inline iteration names. Overrides
# inlinevar-naming-style.
#inlinevar-rgx=

# Naming style matching correct method names.
method-naming-style=snake_case

# Regular expression matching correct method names. Overrides method-naming-
# style.
#method-rgx=

# Naming style matching correct module names.
module-naming-style=snake_case

# Regular expression matching correct module names. Overrides module-naming-
# style.
#module-rgx=

# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=

# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=^_

# List of decorators that produce properties, such as abc.abstractproperty. Add
# to this list to register other decorators that produce valid properties.
# These decorators are taken in consideration only for invalid-name.
property-classes=abc.abstractproperty

# Naming style matching correct variable names.
variable-naming-style=snake_case

# Regular expression matching correct variable names. Overrides variable-
# naming-style.
#variable-rgx=


[IMPORTS]

# Allow wildcard imports from modules that define __all__.
allow-wildcard-with-all=no

# Analyse import fallback blocks. This can be used to support both Python 2 and
# 3 compatible code, which means that the block might have code that exists
# only in one or another interpreter, leading to false positives when analysed.
analyse-fallback-blocks=no

# Deprecated modules which should not be used, separated by a comma.
deprecated-modules=optparse,tkinter.tix

# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled).
ext-import-graph=

# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled).
import-graph=

# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled).
int-import-graph=

# Force import order to recognize a module as part of the standard
# compatibility libraries.
known-standard-library=

# Force import order to recognize a module as part of a third party library.
known-third-party=enchant


[CLASSES]

# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,
                      __new__,
                      setUp

# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,
                  _fields,
                  _replace,
                  _source,
                  _make

# List of valid names for the first argument in a class method.
valid-classmethod-first-arg=cls

# List of valid names for the first argument in a metaclass class method.
valid-metaclass-classmethod-first-arg=cls


[DESIGN]

# Maximum number of arguments for function / method.
max-args=5

# Maximum number of attributes for a class (see R0902).
max-attributes=7

# Maximum number of boolean expressions in an if statement.
max-bool-expr=5

# Maximum number of branch for function / method body.
max-branches=12

# Maximum number of locals for function / method body.
max-locals=15

# Maximum number of parents for a class (see R0901).
max-parents=7

# Maximum number of public methods for a class (see R0904).
max-public-methods=20

# Maximum number of return / yield for function / method body.
max-returns=6

# Maximum number of statements in function / method body.
max-statements=50

# Minimum number of public methods for a class (see R0903).
min-public-methods=2


[EXCEPTIONS]

# Exceptions that will emit a warning when being caught. Defaults to
# "Exception".
overgeneral-exceptions=Exception


================================================
FILE: requirements.txt
================================================
astroid==2.0.4
atomicwrites==1.1.5
attrs==18.1.0
flake8==3.5.0
isort==4.3.4
lazy-object-proxy==1.3.1
mccabe==0.6.1
more-itertools==4.3.0
pluggy==0.7.1
py==1.5.4
pycodestyle==2.3.1
pyflakes==1.6.0
pylint==2.1.1
pytest==3.7.2
six==1.11.0
wrapt==1.10.11


================================================
FILE: src/additions/test_generators.py
================================================
"""Generators.

@see: https://www.learnpython.org/en/Generators

Generators are used to create iterators, but with a different approach. Generators are simple
functions which return an iterable set of items, one at a time, in a special way.

When an iteration over a set of item starts using the for statement, the generator is run. Once the
generator's function code reaches a "yield" statement, the generator yields its execution back to
the for loop, returning a new value from the set. The generator function can generate as many
values (possibly infinite) as it wants, yielding each one in its turn.
"""

import random


def lottery():
    """Generator function example.

    Here is a simple example of a generator function which returns random integers.
    This function decides how to generate the random numbers on its own, and executes the yield
    statements one at a time, pausing in between to yield execution back to the main for loop.
    """
    # returns first 3 random numbers between 1 and 10
    # pylint: disable=unused-variable
    for _ in range(3):
        yield random.randint(1, 10)

    # returns a 4th number between 10 and 20
    yield random.randint(10, 20)


def test_generators():
    """Yield statement"""
    for number_index, random_number in enumerate(lottery()):
        if number_index < 3:
            assert 0 <= random_number <= 10
        else:
            assert 10 <= random_number <= 20


================================================
FILE: src/additions/test_pass.py
================================================
"""PASS statement

@see: https://docs.python.org/3/tutorial/controlflow.html

The pass statement does nothing. It can be used when a statement is required syntactically but
the program requires no action.
"""


def test_pass_in_function():
    """PASS statement in function

    "Pass" can be used as a place-holder for a function or conditional body when you are working on
    new code, allowing you to keep thinking at a more abstract level.

    The pass statement below is silently ignored but it makes current test_pass() function valid.
    """
    pass


def test_pass_in_loop():
    """PASS in loops.

    "Pass" can be used when a statement is required syntactically but the program requires no
    action. For example:
    """

    # pylint: disable=unused-variable
    for number in range(100):
        # It just don't do anything but for loop is still valid.
        pass

    # Example above is quite useless but it was given just for illustration of the idea.
    # The more useful example might be:
    #
    # while True:
    #   pass  # Busy-wait for keyboard interrupt (Ctrl+C)


# pylint: disable=too-few-public-methods
class MyEmptyClass:
    """PASS statement in class

    "Pass" is commonly used for creating minimal classes like current one.
    """
    pass


================================================
FILE: src/classes/test_class_and_instance_variables.py
================================================
"""Class and Instance Variables.

@see: https://docs.python.org/3/tutorial/classes.html#class-and-instance-variables

Generally speaking, instance variables are for data unique to each instance and class variables are
for attributes and methods shared by all instances of the class.
"""


def test_class_and_instance_variables():
    """Class and Instance Variables."""

    # pylint: disable=too-few-public-methods
    class Dog:
        """Dog class example"""
        kind = 'canine'  # Class variable shared by all instances.

        def __init__(self, name):
            self.name = name  # Instance variable unique to each instance.

    fido = Dog('Fido')
    buddy = Dog('Buddy')

    # Shared by all dogs.
    assert fido.kind == 'canine'
    assert buddy.kind == 'canine'

    # Unique to fido.
    assert fido.name == 'Fido'

    # Unique to buddy.
    assert buddy.name == 'Buddy'

    # Shared data can have possibly surprising effects with involving mutable objects such as lists
    # and dictionaries. For example, the tricks list in the following code should not be used as a
    # class variable because just a single list would be shared by all Dog instances.

    # pylint: disable=too-few-public-methods
    class DogWithSharedTricks:
        """Dog class example with wrong shared variable usage"""
        tricks = []  # Mistaken use of a class variable (see below) for mutable objects.

        def __init__(self, name):
            self.name = name  # Instance variable unique to each instance.

        def add_trick(self, trick):
            """Add trick to the dog

            This function illustrate mistaken use of mutable class variable tricks (see below).
            """
            self.tricks.append(trick)

    fido = DogWithSharedTricks('Fido')
    buddy = DogWithSharedTricks('Buddy')

    fido.add_trick('roll over')
    buddy.add_trick('play dead')

    assert fido.tricks == ['roll over', 'play dead']  # unexpectedly shared by all dogs
    assert buddy.tricks == ['roll over', 'play dead']  # unexpectedly shared by all dogs

    # Correct design of the class should use an instance variable instead:

    # pylint: disable=too-few-public-methods
    class DogWithTricks:
        """Dog class example"""

        def __init__(self, name):
            self.name = name  # Instance variable unique to each instance.
            self.tricks = []  # creates a new empty list for each dog

        def add_trick(self, trick):
            """Add trick to the dog

            This function illustrate a correct use of mutable class variable tricks (see below).
            """
            self.tricks.append(trick)

    fido = DogWithTricks('Fido')
    buddy = DogWithTricks('Buddy')

    fido.add_trick('roll over')
    buddy.add_trick('play dead')

    assert fido.tricks == ['roll over']
    assert buddy.tricks == ['play dead']


================================================
FILE: src/classes/test_class_definition.py
================================================
"""Class Definition Syntax.

@see: https://docs.python.org/3/tutorial/classes.html

Python is an object oriented programming language.
Almost everything in Python is an object, with its properties and methods.
A Class is like an object constructor, or a "blueprint" for creating objects.
"""


def test_class_definition():
    """Class definition."""

    # Class definitions, like function definitions (def statements) must be executed before they
    # have any effect. (You could conceivably place a class definition in a branch of an if
    # statement, or inside a function.)

    class GreetingClass:
        """Example of the class definition

        This class contains two public methods and doesn't contain constructor.
        """
        name = 'user'

        def say_hello(self):
            """Class method."""
            # The self parameter is a reference to the class itself, and is used to access variables
            # that belongs to the class. It does not have to be named self , you can call it
            # whatever you like, but it has to be the first parameter of any function in the class.
            return 'Hello ' + self.name

        def say_goodbye(self):
            """Class method."""
            return 'Goodbye ' + self.name

    # When a class definition is entered, a new namespace is created, and used as the local scope —
    # thus, all assignments to local variables go into this new namespace. In particular, function
    # definitions bind the name of the new function here.

    # Class instantiation uses function notation. Just pretend that the class object is a
    # parameterless function that returns a new instance of the class. For example the following
    # code will creates a new instance of the class and assigns this object to the local variable.
    greeter = GreetingClass()

    assert greeter.say_hello() == 'Hello user'
    assert greeter.say_goodbye() == 'Goodbye user'


================================================
FILE: src/classes/test_class_objects.py
================================================
"""Class Definition Syntax.

@see: https://docs.python.org/3/tutorial/classes.html#class-objects

After defining the class attributes to a class, the class object can be created by assigning the
object to a variable. The created object would have instance attributes associated with it.
"""


def test_class_objects():
    """Class Objects.

    Class objects support two kinds of operations:
    - attribute references
    - instantiation.
    """

    # ATTRIBUTE REFERENCES use the standard syntax used for all attribute references in
    # Python: obj.name. Valid attribute names are all the names that were in the class’s namespace
    # when the class object was created. For class MyCounter the following references are valid
    # attribute references:

    class ComplexNumber:
        """Example of the complex numbers class"""

        real = 0
        imaginary = 0

        def get_real(self):
            """Return real part of complex number."""
            return self.real

        def get_imaginary(self):
            """Return imaginary part of complex number."""
            return self.imaginary

    assert ComplexNumber.real == 0

    # __doc__ is also a valid attribute, returning the docstring belonging to the class
    assert ComplexNumber.__doc__ == 'Example of the complex numbers class'

    # Class attributes can also be assigned to, so you can change the value of
    # ComplexNumber.counter by assignment.
    ComplexNumber.real = 10
    assert ComplexNumber.real == 10

    # CLASS INSTANTIATION uses function notation. Just pretend that the class object is a
    # parameterless function that returns a new instance of the class. For example
    # (assuming the above class):
    complex_number = ComplexNumber()

    assert complex_number.real == 10
    assert complex_number.get_real() == 10

    # Let's change counter default value back.
    ComplexNumber.real = 10
    assert ComplexNumber.real == 10

    # The instantiation operation (“calling” a class object) creates an empty object. Many classes
    # like to create objects with instances customized to a specific initial state. Therefore a
    # class may define a special method named __init__(), like this:

    class ComplexNumberWithConstructor:
        """Example of the class with constructor"""
        def __init__(self, real_part, imaginary_part):
            self.real = real_part
            self.imaginary = imaginary_part

        def get_real(self):
            """Return real part of complex number."""
            return self.real

        def get_imaginary(self):
            """Return imaginary part of complex number."""
            return self.imaginary

    complex_number = ComplexNumberWithConstructor(3.0, -4.5)
    assert complex_number.real, complex_number.imaginary == (3.0, -4.5)


================================================
FILE: src/classes/test_inheritance.py
================================================
"""Inheritance

@see: https://docs.python.org/3/tutorial/classes.html#inheritance

Inheritance is one of the principles of object-oriented programming. Since classes may share a lot
of the same code, inheritance allows a derived class to reuse the same code and modify accordingly
"""


# pylint: disable=too-few-public-methods
class Person:
    """Example of the base class"""
    def __init__(self, name):
        self.name = name

    def get_name(self):
        """Get person name"""
        return self.name


# The syntax for a derived class definition looks like this.
# pylint: disable=too-few-public-methods
class Employee(Person):
    """Example of the derived class

    The Base Class (in our case Person) must be defined in a scope containing the derived class
    definition. In place of a base class name, other arbitrary expressions are also allowed.

    Derived classes may override methods of their base classes. Because methods have no special
    privileges when calling other methods of the same object, a method of a base class that calls
    another method defined in the same base class may end up calling a method of a derived class
    that overrides it.

    An overriding method in a derived class may in fact want to extend rather than simply replace
    the base class method of the same name. There is a simple way to call the base class method
    directly: just call BaseClassName.methodname(self, arguments). This is occasionally useful to
    clients as well. (Note that this only works if the base class is accessible as BaseClassName
    in the global scope.)
    """
    def __init__(self, name, staff_id):
        Person.__init__(self, name)
        # You may also use super() here in order to avoid explicit using of parent class name:
        # >>> super().__init__(name)
        self.staff_id = staff_id

    def get_full_id(self):
        """Get full employee id"""
        return self.get_name() + ', ' + self.staff_id


def test_inheritance():
    """Inheritance."""

    # There’s nothing special about instantiation of derived classes: DerivedClassName() creates a
    # new instance of the class. Method references are resolved as follows: the corresponding class
    # attribute is searched, descending down the chain of base classes if necessary, and the method
    # reference is valid if this yields a function object.
    person = Person('Bill')
    employee = Employee('John', 'A23')

    assert person.get_name() == 'Bill'
    assert employee.get_name() == 'John'
    assert employee.get_full_id() == 'John, A23'

    # Python has two built-in functions that work with inheritance:
    #
    # - Use isinstance() to check an instance’s type: isinstance(obj, int) will be True only if
    # obj.__class__ is int or some class derived from int.
    #
    # - Use issubclass() to check class inheritance: issubclass(bool, int) is True since bool is
    # a subclass of int. However, issubclass(float, int) is False since float is not a subclass
    # of int.

    assert isinstance(employee, Employee)
    assert not isinstance(person, Employee)

    assert isinstance(person, Person)
    assert isinstance(employee, Person)

    assert issubclass(Employee, Person)
    assert not issubclass(Person, Employee)


================================================
FILE: src/classes/test_instance_objects.py
================================================
"""Class Definition Syntax.

@see: https://docs.python.org/3/tutorial/classes.html#instance-objects
"""


def test_instance_objects():
    """Instance Objects.

    Now what can we do with instance objects? The only operations understood by instance objects
    are attribute references. There are two kinds of valid attribute names:
    - data attributes
    - methods.
    """

    # DATA ATTRIBUTES need not be declared; like local variables, they spring into existence when
    # they are first assigned to. For example, if x is the instance of MyCounter created above,
    # the following piece of code will print the value 16, without leaving a trace.

    # pylint: disable=too-few-public-methods
    class DummyClass:
        """Dummy class"""
        pass

    dummy_instance = DummyClass()

    # pylint: disable=attribute-defined-outside-init
    dummy_instance.temporary_attribute = 1
    assert dummy_instance.temporary_attribute == 1
    del dummy_instance.temporary_attribute


================================================
FILE: src/classes/test_method_objects.py
================================================
"""Class Definition Syntax.

@see: https://docs.python.org/3/tutorial/classes.html#method-objects

Classes can have two types of attribute references: data or methods. Class methods are called
by [variable_name].[method_name]([parameters]) as opposed to class data which lacks the ().
"""


class MyCounter:
    """A simple example of the counter class"""
    counter = 10

    def get_counter(self):
        """Return the counter"""
        return self.counter

    def increment_counter(self):
        """Increment the counter"""
        self.counter += 1
        return self.counter


def test_method_objects():
    """Method Objects."""

    # The other kind of instance attribute reference is a method. A method is a function that
    # “belongs to” an object. (In Python, the term method is not unique to class instances: other
    # object types can have methods as well. For example, list objects have methods called append,
    # insert, remove, sort, and so on. However, in the following discussion, we’ll use the term
    # method exclusively to mean methods of class instance objects, unless explicitly stated
    # otherwise.)

    # But be aware that counter.get_counter() is not the same thing as MyCounter.get_counter() —
    # it is a method object, not a function object.

    # Usually, a method is called right after it is bound
    counter = MyCounter()
    assert counter.get_counter() == 10

    # However, it is not necessary to call a method right away: counter.get_counter() is a method
    # object, and can be stored away and called at a later time. For example:
    get_counter = counter.get_counter
    assert get_counter() == 10

    # What exactly happens when a method is called? You may have noticed that counter.get_counter()
    # was called without an argument above, even though the function definition for get_counter()
    # specified an argument (self). What happened to the argument? Surely Python raises an
    # exception when a function that requires an argument is called without any — even if the
    # argument isn’t actually used…

    # Actually, you may have guessed the answer: the special thing about methods is that the
    # instance object is passed as the first argument of the function. In our example, the call
    # counter.get_counter() is exactly equivalent to MyCounter.get_counter(counter). In general,
    # calling a method with a list of n arguments is equivalent to calling the corresponding
    # function with an argument list that is created by inserting the method’s instance object
    # before the first argument.

    assert counter.get_counter() == 10
    assert MyCounter.get_counter(counter) == 10


================================================
FILE: src/classes/test_multiple_inheritance.py
================================================
"""Multiple Inheritance

@see: https://docs.python.org/3/tutorial/classes.html#multiple-inheritance

Some classes may derive from multiple classes. This means that the derived class would have
its attributes, along with the attributes of all the classes that it was derived from.
"""


def test_multiple_inheritance():
    """Multiple Inheritance"""

    # pylint: disable=too-few-public-methods
    class Clock:
        """Clock class"""

        time = '11:23 PM'

        def get_time(self):
            """Get current time

            Method is hardcoded just for multiple inheritance illustration.
            """
            return self.time

    # pylint: disable=too-few-public-methods
    class Calendar:
        """Calendar class"""

        date = '12/08/2018'

        def get_date(self):
            """Get current date

            Method is hardcoded just for multiple inheritance illustration.
            """
            return self.date

    # Python supports a form of multiple inheritance as well. A class definition with multiple
    # base classes looks like this.
    class CalendarClock(Clock, Calendar):
        """Class that uses multiple inheritance.

        For most purposes, in the simplest cases, you can think of the search for attributes
        inherited from a parent class as depth-first, left-to-right, not searching twice in the same
        class where there is an overlap in the hierarchy. Thus, if an attribute is not found in
        CalendarClock, it is searched for in Clock, then (recursively) in the base classes of
        Clock, and if it was not found there, it was searched for in Calendar, and so on.

        In fact, it is slightly more complex than that; the method resolution order changes
        dynamically to support cooperative calls to super(). This approach is known in some other
        multiple-inheritance languages as call-next-method and is more powerful than the super call
        found in single-inheritance languages.

        Dynamic ordering is necessary because all cases of multiple inheritance exhibit one or more
        diamond relationships (where at least one of the parent classes can be accessed through
        multiple paths from the bottommost class). For example, all classes inherit from object,
        so any case of multiple inheritance provides more than one path to reach object. To keep
        the base classes from being accessed more than once, the dynamic algorithm linearizes the
        search order in a way that preserves the left-to-right ordering specified in each class,
        that calls each parent only once, and that is monotonic (meaning that a class can be
        subclassed without affecting the precedence order of its parents).
        """

    calendar_clock = CalendarClock()

    assert calendar_clock.get_date() == '12/08/2018'
    assert calendar_clock.get_time() == '11:23 PM'


================================================
FILE: src/control_flow/test_break.py
================================================
"""BREAK statement

@see: https://docs.python.org/3/tutorial/controlflow.html

The break statement, like in C, breaks out of the innermost enclosing "for" or "while" loop.
"""


def test_break_statement():
    """BREAK statement"""

    # Let's terminate the loop in case if we've found the number we need in a range from 0 to 100.
    number_to_be_found = 42
    # This variable will record how many time we've entered the "for" loop.
    number_of_iterations = 0

    for number in range(100):
        if number == number_to_be_found:
            # Break here and don't continue the loop.
            break
        else:
            number_of_iterations += 1

    # We need to make sure that break statement has terminated the loop once it found the number.
    assert number_of_iterations == 42


================================================
FILE: src/control_flow/test_continue.py
================================================
"""CONTINUE statement

@see: https://docs.python.org/3/tutorial/controlflow.html

The continue statement is borrowed from C, continues with the next iteration of the loop.
"""


def test_continue_statement():
    """CONTINUE statement in FOR loop"""

    # Let's

    # This list will contain only even numbers from the range.
    even_numbers = []
    # This list will contain every other numbers (in this case - ods).
    rest_of_the_numbers = []

    for number in range(0, 10):
        # Check if remainder after division is zero (which would mean that number is even).
        if number % 2 == 0:
            even_numbers.append(number)
            # Stop current loop iteration and go to the next one immediately.
            continue

        rest_of_the_numbers.append(number)

    assert even_numbers == [0, 2, 4, 6, 8]
    assert rest_of_the_numbers == [1, 3, 5, 7, 9]


================================================
FILE: src/control_flow/test_for.py
================================================
"""FOR statement

@see: https://docs.python.org/3/tutorial/controlflow.html

The for statement in Python differs a bit from what you may be used to in C or Pascal.
Rather than always iterating over an arithmetic progression of numbers (like in Pascal), or
giving the user the ability to define both the iteration step and halting condition (as C),
Python’s for statement iterates over the items of any sequence (a list or a string), in the
order that they appear in the sequence. For example (no pun intended):
"""


# pylint: disable=too-many-locals
def test_for_statement():
    """FOR statement"""

    # Measure some strings:
    words = ['cat', 'window', 'defenestrate']
    words_length = 0

    for word in words:
        words_length += len(word)

    # "cat" length is 3
    # "window" length is 6
    # "defenestrate" length is 12
    assert words_length == (3 + 6 + 12)

    # If you need to modify the sequence you are iterating over while inside the loop
    # (for example to duplicate selected items), it is recommended that you first make a copy.
    # Iterating over a sequence does not implicitly make a copy. The slice notation makes this
    # especially convenient:
    for word in words[:]:  # Loop over a slice copy of the entire list.
        if len(word) > 6:
            words.insert(0, word)

    # Otherwise with for w in words:, the example would attempt to create an infinite list,
    # inserting defenestrate over and over again.

    assert words == ['defenestrate', 'cat', 'window', 'defenestrate']

    # If you do need to iterate over a sequence of numbers, the built-in function range() comes in
    # handy. It generates arithmetic progressions:
    iterated_numbers = []

    for number in range(5):
        iterated_numbers.append(number)

    assert iterated_numbers == [0, 1, 2, 3, 4]

    # To iterate over the indices of a sequence, you can combine range() and len() as follows:
    words = ['Mary', 'had', 'a', 'little', 'lamb']
    concatenated_string = ''

    # pylint: disable=consider-using-enumerate
    for word_index in range(len(words)):
        concatenated_string += words[word_index] + ' '

    assert concatenated_string == 'Mary had a little lamb '

    # Or simply use enumerate().
    concatenated_string = ''

    for word_index, word in enumerate(words):
        concatenated_string += word + ' '

    assert concatenated_string == 'Mary had a little lamb '

    # When looping through dictionaries, the key and corresponding value can be retrieved at the
    # same time using the items() method.
    knights_names = []
    knights_properties = []

    knights = {'gallahad': 'the pure', 'robin': 'the brave'}
    for key, value in knights.items():
        knights_names.append(key)
        knights_properties.append(value)

    assert knights_names == ['gallahad', 'robin']
    assert knights_properties == ['the pure', 'the brave']

    # When looping through a sequence, the position index and corresponding value can be retrieved
    # at the same time using the enumerate() function
    indices = []
    values = []
    for index, value in enumerate(['tic', 'tac', 'toe']):
        indices.append(index)
        values.append(value)

    assert indices == [0, 1, 2]
    assert values == ['tic', 'tac', 'toe']

    # To loop over two or more sequences at the same time, the entries can be paired with
    # the zip() function.
    questions = ['name', 'quest', 'favorite color']
    answers = ['lancelot', 'the holy grail', 'blue']
    combinations = []

    for question, answer in zip(questions, answers):
        combinations.append('What is your {0}?  It is {1}.'.format(question, answer))

    assert combinations == [
        'What is your name?  It is lancelot.',
        'What is your quest?  It is the holy grail.',
        'What is your favorite color?  It is blue.',
    ]


def test_range_function():
    """Range function

    If you do need to iterate over a sequence of numbers, the built-in function range() comes in
    handy. It generates arithmetic progressions.

    In many ways the object returned by range() behaves as if it is a list, but in fact it isn’t.
    It is an object which returns the successive items of the desired sequence when you iterate
    over it, but it doesn’t really make the list, thus saving space.

    We say such an object is iterable, that is, suitable as a target for functions and constructs
    that expect something from which they can obtain successive items until the supply is exhausted.
    We have seen that the for statement is such an iterator. The function list() is another; it
    creates lists from iterables:
    """

    assert list(range(5)) == [0, 1, 2, 3, 4]

    # The given end point is never part of the generated sequence; range(10) generates 10 values,
    # the legal indices for items of a sequence of length 10. It is possible to let the range start
    # at another number, or to specify a different increment (even negative; sometimes this is
    # called the ‘step’):

    assert list(range(5, 10)) == [5, 6, 7, 8, 9]
    assert list(range(0, 10, 3)) == [0, 3, 6, 9]
    assert list(range(-10, -100, -30)) == [-10, -40, -70]


================================================
FILE: src/control_flow/test_if.py
================================================
"""IF statement

@see: https://docs.python.org/3/tutorial/controlflow.html

There can be zero or more elif parts, and the else part is optional. The keyword ‘elif’ is
short for ‘else if’, and is useful to avoid excessive indentation.

An if … elif … elif … sequence is a substitute for the switch or case statements found
in other languages.
"""


def test_if_statement():
    """IF statement"""

    number = 15
    conclusion = ''

    if number < 0:
        conclusion = 'Number is less than zero'
    elif number == 0:
        conclusion = 'Number equals to zero'
    elif number < 1:
        conclusion = 'Number is greater than zero but less than one'
    else:
        conclusion = 'Number bigger than or equal to one'

    assert conclusion == 'Number bigger than or equal to one'


================================================
FILE: src/control_flow/test_try.py
================================================
"""TRY statement

@see: https://www.w3schools.com/python/python_try_except.asp

"try" statement is used for exception handling.
When an error occurs, or exception as we call it, Python will normally stop and generate an error
message. These exceptions can be handled using the try statement.

The "try" block lets you test a block of code for errors.
The "except" block lets you handle the error.
The "else" block lets you execute the code if no errors were raised.
The "finally" block lets you execute code, regardless of the result of the try- and except blocks.
"""


def test_try():
    """TRY statement"""

    # The try block will generate an error, because x is not defined:
    exception_has_been_caught = False

    try:
        # pylint: disable=undefined-variable
        print(not_existing_variable)
    except NameError:
        exception_has_been_caught = True

    assert exception_has_been_caught

    # You can define as many exception blocks as you want, e.g. if you want to execute a special
    # block of code for a special kind of error:
    exception_message = ''

    try:
        # pylint: disable=undefined-variable
        print(not_existing_variable)
    except NameError:
        exception_message = 'Variable is not defined'

    assert exception_message == 'Variable is not defined'

    # You can use the else keyword to define a block of code to be executed
    # if no errors were raised.
    message = ''
    # pylint: disable=broad-except
    try:
        message += 'Success.'
    except NameError:
        message += 'Something went wrong.'
    else:
        message += 'Nothing went wrong.'

    assert message == 'Success.Nothing went wrong.'

    # The finally block, if specified, will be executed regardless if the try block raises an
    # error or not.
    message = ''
    try:
        # pylint: undefined-variable
        print(not_existing_variable)  # noqa: F821
    except NameError:
        message += 'Something went wrong.'
    finally:
        message += 'The "try except" is finished.'

    assert message == 'Something went wrong.The "try except" is finished.'


================================================
FILE: src/control_flow/test_while.py
================================================
"""WHILE statement

@see: https://docs.python.org/3/tutorial/controlflow.html
@see: https://docs.python.org/3/reference/compound_stmts.html#the-while-statement

The while loop executes as long as the condition remains true. In Python, like in C, any
non-zero integer value is true; zero is false. The condition may also be a string or list
value, in fact any sequence; anything with a non-zero length is true, empty sequences are
false.

The test used in the example is a simple comparison. The standard comparison operators are
written the same as in C: < (less than), > (greater than), == (equal to), <= (less than or
equal to), >= (greater than or equal to) and != (not equal to).
"""


def test_while_statement():
    """WHILE statement"""

    # Let's raise the number to certain power using while loop.
    number = 2
    power = 5

    result = 1

    while power > 0:
        result *= number
        power -= 1

    # 2^5 = 32
    assert result == 32


================================================
FILE: src/data_types/test_dictionaries.py
================================================
"""Dictionaries.

@see: https://docs.python.org/3/tutorial/datastructures.html#dictionaries
@see: https://www.w3schools.com/python/python_dictionaries.asp

A dictionary is a collection which is unordered, changeable and indexed. In Python dictionaries are
written with curly brackets, and they have keys and values.

Dictionaries are sometimes found in other languages as “associative memories” or “associative
arrays”. Unlike sequences, which are indexed by a range of numbers, dictionaries are indexed by
keys, which can be any immutable type; strings and numbers can always be keys. Tuples can be used
as keys if they contain only strings, numbers, or tuples; if a tuple contains any mutable object
either directly or indirectly, it cannot be used as a key. You can’t use lists as keys, since
lists can be modified in place using index assignments, slice assignments, or methods like append()
and extend().

It is best to think of a dictionary as a set of key: value pairs, with the requirement that the
keys are unique (within one dictionary). A pair of braces creates an empty dictionary: {}.
Placing a comma-separated list of key:value pairs within the braces adds initial key:value pairs
to the dictionary; this is also the way dictionaries are written on output.
"""


def test_dictionary():
    """Dictionary"""

    fruits_dictionary = {
        'cherry': 'red',
        'apple': 'green',
        'banana': 'yellow',
    }

    assert isinstance(fruits_dictionary, dict)

    # You may access set elements by keys.
    assert fruits_dictionary['apple'] == 'green'
    assert fruits_dictionary['banana'] == 'yellow'
    assert fruits_dictionary['cherry'] == 'red'

    # To check whether a single key is in the dictionary, use the in keyword.
    assert 'apple' in fruits_dictionary
    assert 'pineapple' not in fruits_dictionary

    # Change the apple color to "red".
    fruits_dictionary['apple'] = 'red'

    # Add new key/value pair to the dictionary
    fruits_dictionary['pineapple'] = 'yellow'
    assert fruits_dictionary['pineapple'] == 'yellow'

    # Performing list(d) on a dictionary returns a list of all the keys used in the dictionary,
    # in insertion order (if you want it sorted, just use sorted(d) instead).
    assert list(fruits_dictionary) == ['cherry', 'apple', 'banana', 'pineapple']
    assert sorted(fruits_dictionary) == ['apple', 'banana', 'cherry', 'pineapple']

    # It is also possible to delete a key:value pair with del.
    del fruits_dictionary['pineapple']
    assert list(fruits_dictionary) == ['cherry', 'apple', 'banana']

    # The dict() constructor builds dictionaries directly from sequences of key-value pairs.
    dictionary_via_constructor = dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])

    assert dictionary_via_constructor['sape'] == 4139
    assert dictionary_via_constructor['guido'] == 4127
    assert dictionary_via_constructor['jack'] == 4098

    # In addition, dict comprehensions can be used to create dictionaries from arbitrary key
    # and value expressions:
    dictionary_via_expression = {x: x**2 for x in (2, 4, 6)}
    assert dictionary_via_expression[2] == 4
    assert dictionary_via_expression[4] == 16
    assert dictionary_via_expression[6] == 36

    # When the keys are simple strings, it is sometimes easier to specify pairs using
    # keyword arguments.
    dictionary_for_string_keys = dict(sape=4139, guido=4127, jack=4098)
    assert dictionary_for_string_keys['sape'] == 4139
    assert dictionary_for_string_keys['guido'] == 4127
    assert dictionary_for_string_keys['jack'] == 4098


================================================
FILE: src/data_types/test_lists.py
================================================
"""Lists.

# @see: https://www.learnpython.org/en/Lists
# @see: https://docs.python.org/3/tutorial/introduction.html
# @ee: https://docs.python.org/3/tutorial/datastructures.html#more-on-lists

Python knows a number of compound data types, used to group together
other values. The most versatile is the list, which can be written as a
list of comma-separated values (items) between square brackets. Lists
might contain items of different types, but usually the items all have
the same type.
"""

import pytest


def test_list_type():
    """List type."""

    # Lists are very similar to arrays. They can contain any type of variable, and they can contain
    # as many variables as you wish. Lists can also be iterated over in a very simple manner.
    # Here is an example of how to build a list.
    squares = [1, 4, 9, 16, 25]

    assert isinstance(squares, list)

    # Like strings (and all other built-in sequence type), lists can be
    # indexed and sliced:
    assert squares[0] == 1  # indexing returns the item
    assert squares[-1] == 25
    assert squares[-3:] == [9, 16, 25]  # slicing returns a new list

    # All slice operations return a new list containing the requested elements.
    # This means that the following slice returns a new (shallow) copy of
    # the list:
    assert squares[:] == [1, 4, 9, 16, 25]

    # Lists also support operations like concatenation:
    assert squares + [36, 49, 64, 81, 100] == [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

    # Unlike strings, which are immutable, lists are a mutable type, i.e. it
    # is possible to change their content:
    cubes = [1, 8, 27, 65, 125]  # something's wrong here, the cube of 4 is 64!
    cubes[3] = 64  # replace the wrong value
    assert cubes == [1, 8, 27, 64, 125]

    # You can also add new items at the end of the list, by using
    # the append() method
    cubes.append(216)  # add the cube of 6
    cubes.append(7 ** 3)  # and the cube of 7
    assert cubes == [1, 8, 27, 64, 125, 216, 343]

    # Assignment to slices is also possible, and this can even change the size
    # of the list or clear it entirely:
    letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
    letters[2:5] = ['C', 'D', 'E']  # replace some values
    assert letters == ['a', 'b', 'C', 'D', 'E', 'f', 'g']
    letters[2:5] = []  # now remove them
    assert letters == ['a', 'b', 'f', 'g']
    # clear the list by replacing all the elements with an empty list
    letters[:] = []
    assert letters == []

    # The built-in function len() also applies to lists
    letters = ['a', 'b', 'c', 'd']
    assert len(letters) == 4

    # It is possible to nest lists (create lists containing other lists),
    # for example:
    list_of_chars = ['a', 'b', 'c']
    list_of_numbers = [1, 2, 3]
    mixed_list = [list_of_chars, list_of_numbers]
    assert mixed_list == [['a', 'b', 'c'], [1, 2, 3]]
    assert mixed_list[0] == ['a', 'b', 'c']
    assert mixed_list[0][1] == 'b'


def test_list_methods():
    """Test list methods."""

    fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']

    # list.append(x)
    # Add an item to the end of the list.
    # Equivalent to a[len(a):] = [x].
    fruits.append('grape')
    assert fruits == ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana', 'grape']

    # list.remove(x)
    # Remove the first item from the list whose value is equal to x.
    # It raises a ValueError if there is no such item.
    fruits.remove('grape')
    assert fruits == ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']

    with pytest.raises(Exception):
        fruits.remove('not existing element')

    # list.insert(i, x)
    # Insert an item at a given position. The first argument is the index of the element
    # before which to insert, so a.insert(0, x) inserts at the front of the list,
    # and a.insert(len(a), x) is equivalent to a.append(x).
    fruits.insert(0, 'grape')
    assert fruits == ['grape', 'orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']

    # list.index(x[, start[, end]])
    # Return zero-based index in the list of the first item whose value is equal to x.
    # Raises a ValueError if there is no such item.
    # The optional arguments start and end are interpreted as in the slice notation and are used
    # to limit the search to a particular subsequence of the list. The returned index is computed
    # relative to the beginning of the full sequence rather than the start argument.
    assert fruits.index('grape') == 0
    assert fruits.index('orange') == 1
    assert fruits.index('banana') == 4
    assert fruits.index('banana', 5) == 7  # Find next banana starting a position 5

    with pytest.raises(Exception):
        fruits.index('not existing element')

    # list.count(x)
    # Return the number of times x appears in the list.
    assert fruits.count('tangerine') == 0
    assert fruits.count('banana') == 2

    # list.copy()
    # Return a shallow copy of the list. Equivalent to a[:].
    fruits_copy = fruits.copy()
    assert fruits_copy == ['grape', 'orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']

    # list.reverse()
    # Reverse the elements of the list in place.
    fruits_copy.reverse()
    assert fruits_copy == [
        'banana',
        'apple',
        'kiwi',
        'banana',
        'pear',
        'apple',
        'orange',
        'grape',
    ]

    # list.sort(key=None, reverse=False)
    # Sort the items of the list in place (the arguments can be used for sort customization,
    # see sorted() for their explanation).
    fruits_copy.sort()
    assert fruits_copy == [
        'apple',
        'apple',
        'banana',
        'banana',
        'grape',
        'kiwi',
        'orange',
        'pear',
    ]

    # list.pop([i])
    # Remove the item at the given position in the list, and return it. If no index is specified,
    # a.pop() removes and returns the last item in the list. (The square brackets around the i in
    # the method signature denote that the parameter is optional, not that you should type square
    # brackets at that position.)
    assert fruits == ['grape', 'orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
    assert fruits.pop() == 'banana'
    assert fruits == ['grape', 'orange', 'apple', 'pear', 'banana', 'kiwi', 'apple']

    # list.clear()
    # Remove all items from the list. Equivalent to del a[:].
    fruits.clear()
    assert fruits == []


def test_del_statement():
    """The del statement

    There is a way to remove an item from a list given its index instead of its value: the del
    statement. This differs from the pop() method which returns a value. The del statement can also
    be used to remove slices from a list or clear the entire list (which we did earlier by
    assignment of an empty list to the slice).
    """

    numbers = [-1, 1, 66.25, 333, 333, 1234.5]

    del numbers[0]
    assert numbers == [1, 66.25, 333, 333, 1234.5]

    del numbers[2:4]
    assert numbers == [1, 66.25, 1234.5]

    del numbers[:]
    assert numbers == []

    # del can also be used to delete entire variables:
    del numbers
    with pytest.raises(Exception):
        # Referencing the name a hereafter is an error (at least until another
        # value is assigned to it).
        assert numbers == []  # noqa: F821


def test_list_comprehensions():
    """List Comprehensions.

    List comprehensions provide a concise way to create lists. Common applications are to make new
    lists where each element is the result of some operations applied to each member of another
    sequence or iterable, or to create a subsequence of those elements that satisfy a certain
    condition.

    A list comprehension consists of brackets containing an expression followed by a for clause,
    then zero or more for or if clauses. The result will be a new list resulting from evaluating
    the expression in the context of the for and if clauses which follow it.
    """

    # For example, assume we want to create a list of squares, like:
    squares = []
    for number in range(10):
        squares.append(number ** 2)

    assert squares == [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

    # Note that this creates (or overwrites) a variable named "number" that still exists after
    # the loop completes. We can calculate the list of squares without any side effects using:
    squares = list(map(lambda x: x ** 2, range(10)))
    assert squares == [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

    # or, equivalently (which is more concise and readable):
    squares = [x ** 2 for x in range(10)]
    assert squares == [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

    # For example, this listcomp combines the elements of two lists if they are not equal.
    combinations = [(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y]
    assert combinations == [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

    # and it’s equivalent to:
    combinations = []
    for first_number in [1, 2, 3]:
        for second_number in [3, 1, 4]:
            if first_number != second_number:
                combinations.append((first_number, second_number))

    assert combinations == [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

    # Note how the order of the for and if statements is the same in both these snippets.

    # If the expression is a tuple (e.g. the (x, y) in the previous example),
    # it must be parenthesized.

    # Let's see some more examples:

    vector = [-4, -2, 0, 2, 4]

    # Create a new list with the values doubled.
    doubled_vector = [x * 2 for x in vector]
    assert doubled_vector == [-8, -4, 0, 4, 8]

    # Filter the list to exclude negative numbers.
    positive_vector = [x for x in vector if x >= 0]
    assert positive_vector == [0, 2, 4]

    # Apply a function to all the elements.
    abs_vector = [abs(x) for x in vector]
    assert abs_vector == [4, 2, 0, 2, 4]

    # Call a method on each element.
    fresh_fruit = ['  banana', '  loganberry ', 'passion fruit  ']
    clean_fresh_fruit = [weapon.strip() for weapon in fresh_fruit]
    assert clean_fresh_fruit == ['banana', 'loganberry', 'passion fruit']

    # Create a list of 2-tuples like (number, square).
    square_tuples = [(x, x ** 2) for x in range(6)]
    assert square_tuples == [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]

    # Flatten a list using a listcomp with two 'for'.
    vector = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    flatten_vector = [num for elem in vector for num in elem]
    assert flatten_vector == [1, 2, 3, 4, 5, 6, 7, 8, 9]


def test_nested_list_comprehensions():
    """Nested List Comprehensions

    The initial expression in a list comprehension can be any arbitrary expression, including
    another list comprehension.
    """

    # Consider the following example of a 3x4 matrix implemented as a list of 3 lists of length 4:
    matrix = [
        [1, 2, 3, 4],
        [5, 6, 7, 8],
        [9, 10, 11, 12],
    ]

    # The following list comprehension will transpose rows and columns:
    transposed_matrix = [[row[i] for row in matrix] for i in range(4)]
    assert transposed_matrix == [
        [1, 5, 9],
        [2, 6, 10],
        [3, 7, 11],
        [4, 8, 12],
    ]

    # As we saw in the previous section, the nested listcomp is evaluated in the context of the
    # for that follows it, so this example is equivalent to:
    transposed = []
    for i in range(4):
        transposed.append([row[i] for row in matrix])

    assert transposed == [
        [1, 5, 9],
        [2, 6, 10],
        [3, 7, 11],
        [4, 8, 12],
    ]

    # which, in turn, is the same as:
    transposed = []
    for i in range(4):
        # the following 3 lines implement the nested listcomp
        transposed_row = []
        for row in matrix:
            transposed_row.append(row[i])
        transposed.append(transposed_row)

    assert transposed == [
        [1, 5, 9],
        [2, 6, 10],
        [3, 7, 11],
        [4, 8, 12],
    ]

    # In the real world, you should prefer built-in functions to complex flow statements.
    # The zip() function would do a great job for this use case:
    assert list(zip(*matrix)) == [
        (1, 5, 9),
        (2, 6, 10),
        (3, 7, 11),
        (4, 8, 12),
    ]


================================================
FILE: src/data_types/test_numbers.py
================================================
"""Numbers.

@see: https://docs.python.org/3/tutorial/introduction.html
@see: https://www.w3schools.com/python/python_numbers.asp

There are three numeric types in Python:
- int (e.g. 2, 4, 20)
    - bool (e.g. False and True, acting like 0 and 1)
- float (e.g. 5.0, 1.6)
- complex (e.g. 5+6j, 4-3j)
"""


def test_integer_numbers():
    """Integer type

    Int, or integer, is a whole number, positive or negative,
    without decimals, of unlimited length.
    """

    positive_integer = 1
    negative_integer = -3255522
    big_integer = 35656222554887711

    assert isinstance(positive_integer, int)
    assert isinstance(negative_integer, int)
    assert isinstance(big_integer, int)


def test_booleans():
    """Boolean

    Booleans represent the truth values False and True. The two objects representing the values
    False and True are the only Boolean objects. The Boolean type is a subtype of the integer type,
    and Boolean values behave like the values 0 and 1, respectively, in almost all contexts, the
    exception being that when converted to a string, the strings "False" or "True" are returned,
    respectively.
    """

    true_boolean = True
    false_boolean = False

    assert true_boolean
    assert not false_boolean

    assert isinstance(true_boolean, bool)
    assert isinstance(false_boolean, bool)

    # Let's try to cast boolean to string.
    assert str(true_boolean) == "True"
    assert str(false_boolean) == "False"


def test_float_numbers():
    """Float type

    Float, or "floating point number" is a number, positive or negative,
    containing one or more decimals.
    """

    float_number = 7.0
    # Another way of declaring float is using float() function.
    float_number_via_function = float(7)
    float_negative = -35.59

    assert float_number == float_number_via_function
    assert isinstance(float_number, float)
    assert isinstance(float_number_via_function, float)
    assert isinstance(float_negative, float)

    # Float can also be scientific numbers with an "e" to indicate
    # the power of 10.
    float_with_small_e = 35e3
    float_with_big_e = 12E4

    assert float_with_small_e == 35000
    assert float_with_big_e == 120000
    assert isinstance(12E4, float)
    assert isinstance(-87.7e100, float)


def test_complex_numbers():
    """Complex Type"""

    complex_number_1 = 5 + 6j
    complex_number_2 = 3 - 2j

    assert isinstance(complex_number_1, complex)
    assert isinstance(complex_number_2, complex)
    assert complex_number_1 * complex_number_2 == 27 + 8j


def test_number_operators():
    """Basic operations"""

    # Addition.
    assert 2 + 4 == 6

    # Multiplication.
    assert 2 * 4 == 8

    # Division always returns a floating point number.
    assert 12 / 3 == 4.0
    assert 12 / 5 == 2.4
    assert 17 / 3 == 5.666666666666667

    # Modulo operator returns the remainder of the division.
    assert 12 % 3 == 0
    assert 13 % 3 == 1

    # Floor division discards the fractional part.
    assert 17 // 3 == 5

    # Raising the number to specific power.
    assert 5 ** 2 == 25  # 5 squared
    assert 2 ** 7 == 128  # 2 to the power of 7

    # There is full support for floating point; operators with
    # mixed type operands convert the integer operand to floating point.
    assert 4 * 3.75 - 1 == 14.0


================================================
FILE: src/data_types/test_sets.py
================================================
"""Sets.

@see: https://www.w3schools.com/python/python_sets.asp
@see: https://docs.python.org/3.7/tutorial/datastructures.html#sets

A set is a collection which is unordered and unindexed.
In Python sets are written with curly brackets.

Set objects also support mathematical operations like union, intersection, difference, and
symmetric difference.
"""


def test_sets():
    """Sets"""
    fruits_set = {"apple", "banana", "cherry"}

    assert isinstance(fruits_set, set)

    # It is also possible to use the set() constructor to make a set.
    # Note the double round-brackets
    fruits_set_via_constructor = set(("apple", "banana", "cherry"))

    assert isinstance(fruits_set_via_constructor, set)


def test_set_methods():
    """Set methods"""

    fruits_set = {"apple", "banana", "cherry"}

    # You may check if the item is in set by using "in" statement
    assert "apple" in fruits_set
    assert "pineapple" not in fruits_set

    # Use the len() method to return the number of items.
    assert len(fruits_set) == 3

    # You can use the add() object method to add an item.
    fruits_set.add("pineapple")
    assert "pineapple" in fruits_set
    assert len(fruits_set) == 4

    # Use remove() method to remove an item.
    fruits_set.remove("pineapple")
    assert "pineapple" not in fruits_set
    assert len(fruits_set) == 3

    # Demonstrate set operations on unique letters from two word:
    first_char_set = set('abracadabra')
    second_char_set = set('alacazam')

    assert first_char_set == {'a', 'r', 'b', 'c', 'd'}  # unique letters in first word
    assert second_char_set == {'a', 'l', 'c', 'z', 'm'}  # unique letters in second word

    # Letters in first word but not in second.
    assert first_char_set - second_char_set == {'r', 'b', 'd'}

    # Letters in first word or second word or both.
    assert first_char_set | second_char_set == {'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}

    # Common letters in both words.
    assert first_char_set & second_char_set == {'a', 'c'}

    # Letters in first or second word but not both.
    assert first_char_set ^ second_char_set == {'r', 'd', 'b', 'm', 'z', 'l'}

    # Similarly to list comprehensions, set comprehensions are also supported:
    word = {char for char in 'abracadabra' if char not in 'abc'}
    assert word == {'r', 'd'}


================================================
FILE: src/data_types/test_strings.py
================================================
"""Strings.

@see: https://docs.python.org/3/tutorial/introduction.html
@see: https://www.w3schools.com/python/python_strings.asp
@see: https://www.w3schools.com/python/python_ref_string.asp

Besides numbers, Python can also manipulate strings, which can be
expressed in several ways. They can be enclosed in single quotes ('...')
or double quotes ("...") with the same result.
"""

import pytest


def test_string_type():
    """String type"""

    # String with double quotes.
    name_1 = "John"
    # String with single quotes.
    name_2 = 'John'
    # Strings created with different kind of quotes are treated the same.
    assert name_1 == name_2
    assert isinstance(name_1, str)
    assert isinstance(name_2, str)

    # \ can be used to escape quotes.
    # use \' to escape the single quote or use double quotes instead.
    single_quote_string = 'doesn\'t'
    double_quote_string = "doesn't"

    assert single_quote_string == double_quote_string

    # \n means newline.
    multiline_string = 'First line.\nSecond line.'
    # Without print(), \n is included in the output.
    # But with print(), \n produces a new line.
    assert multiline_string == 'First line.\nSecond line.'

    # Strings can be indexed, with the first character having index 0.
    # There is no separate character type; a character is simply a string
    # of size one. Note that since -0 is the same as 0, negative indices
    # start from -1.
    word = 'Python'
    assert word[0] == 'P'  # First character.
    assert word[5] == 'n'  # Fifth character.
    assert word[-1] == 'n'  # Last character.
    assert word[-2] == 'o'  # Second-last character.
    assert word[-6] == 'P'  # Sixth from the end or zeroth from the beginning.

    assert isinstance(word[0], str)

    # In addition to indexing, slicing is also supported. While indexing is
    # used to obtain individual characters, slicing allows you to obtain
    # substring:
    assert word[0:2] == 'Py'  # Characters from position 0 (included) to 2 (excluded).
    assert word[2:5] == 'tho'  # Characters from position 2 (included) to 5 (excluded).

    # Note how the start is always included, and the end always excluded.
    # This makes sure that s[:i] + s[i:] is always equal to s:
    assert word[:2] + word[2:] == 'Python'
    assert word[:4] + word[4:] == 'Python'

    # Slice indices have useful defaults; an omitted first index defaults to
    # zero, an omitted second index defaults to the size of the string being
    # sliced.
    assert word[:2] == 'Py'  # Character from the beginning to position 2 (excluded).
    assert word[4:] == 'on'  # Characters from position 4 (included) to the end.
    assert word[-2:] == 'on'  # Characters from the second-last (included) to the end.

    # One way to remember how slices work is to think of the indices as
    # pointing between characters, with the left edge of the first character
    # numbered 0. Then the right edge of the last character of a string of n
    # characters has index n, for example:
    #
    # +---+---+---+---+---+---+
    #  | P | y | t | h | o | n |
    #  +---+---+---+---+---+---+
    #  0   1   2   3   4   5   6
    # -6  -5  -4  -3  -2  -1

    # Attempting to use an index that is too large will result in an error.
    with pytest.raises(Exception):
        not_existing_character = word[42]
        assert not not_existing_character

    # However, out of range slice indexes are handled gracefully when used
    # for slicing:
    assert word[4:42] == 'on'
    assert word[42:] == ''

    # Python strings cannot be changed — they are immutable. Therefore,
    # assigning to an indexed position in the string
    # results in an error:
    with pytest.raises(Exception):
        # pylint: disable=unsupported-assignment-operation
        word[0] = 'J'

    # If you need a different string, you should create a new one:
    assert 'J' + word[1:] == 'Jython'
    assert word[:2] + 'py' == 'Pypy'

    # The built-in function len() returns the length of a string:
    characters = 'supercalifragilisticexpialidocious'
    assert len(characters) == 34

    # String literals can span multiple lines. One way is using triple-quotes: """..."""
    # or '''...'''. End of lines are automatically included in the string, but it’s possible
    # to prevent this by adding a \ at the end of the line. The following example:
    multi_line_string = '''\
        First line
        Second line
    '''

    assert multi_line_string == '''\
        First line
        Second line
    '''


def test_string_operators():
    """Basic operations

    Strings can be concatenated (glued together) with the + operator,
    and repeated with *: 3 times 'un', followed by 'ium'
    """

    assert 3 * 'un' + 'ium' == 'unununium'

    # 'Py' 'thon'
    python = 'Py' 'thon'
    assert python == 'Python'

    # This feature is particularly useful when you want to break long strings:
    text = (
        'Put several strings within parentheses '
        'to have them joined together.'
    )
    assert text == 'Put several strings within parentheses to have them joined together.'

    # If you want to concatenate variables or a variable and a literal, use +:
    prefix = 'Py'
    assert prefix + 'thon' == 'Python'


def test_string_methods():
    """String methods"""

    hello_world_string = "Hello, World!"

    # The strip() method removes any whitespace from the beginning or the end.
    string_with_whitespaces = " Hello, World! "
    assert string_with_whitespaces.strip() == "Hello, World!"

    # The len() method returns the length of a string.
    assert len(hello_world_string) == 13

    # The lower() method returns the string in lower case.
    assert hello_world_string.lower() == 'hello, world!'

    # The upper() method returns the string in upper case.
    assert hello_world_string.upper() == 'HELLO, WORLD!'

    # The replace() method replaces a string with another string.
    assert hello_world_string.replace('H', 'J') == 'Jello, World!'

    # The split() method splits the string into substrings if it finds instances of the separator.
    assert hello_world_string.split(',') == ['Hello', ' World!']

    # Converts the first character to upper case
    assert 'low letter at the beginning'.capitalize() == 'Low letter at the beginning'

    # Returns the number of times a specified value occurs in a string.
    assert 'low letter at the beginning'.count('t') == 4

    # Searches the string for a specified value and returns the position of where it was found.
    assert 'Hello, welcome to my world'.find('welcome') == 7

    # Converts the first character of each word to upper case
    assert 'Welcome to my world'.title() == 'Welcome To My World'

    # Returns a string where a specified value is replaced with a specified value.
    assert 'I like bananas'.replace('bananas', 'apples') == 'I like apples'

    # Joins the elements of an iterable to the end of the string.
    my_tuple = ('John', 'Peter', 'Vicky')
    assert ', '.join(my_tuple) == 'John, Peter, Vicky'

    # Returns True if all characters in the string are upper case.
    assert 'ABC'.isupper()
    assert not 'AbC'.isupper()

    # Check if all the characters in the text are letters.
    assert 'CompanyX'.isalpha()
    assert not 'Company 23'.isalpha()

    # Returns True if all characters in the string are decimals.
    assert '1234'.isdecimal()
    assert not 'a21453'.isdecimal()


def test_string_formatting():
    """String formatting.

    Often you’ll want more control over the formatting of your output than simply printing
    space-separated values. There are several ways to format output
    """

    # To use formatted string literals, begin a string with f or F before the opening quotation
    # mark or triple quotation mark. Inside this string, you can write a Python expression
    # between { and } characters that can refer to variables or literal values.
    year = 2018
    event = 'conference'

    assert f'Results of the {year} {event}' == 'Results of the 2018 conference'

    # The str.format() method of strings requires more manual effort. You’ll still use { and } to
    # mark where a variable will be substituted and can provide detailed formatting directives,
    # but you’ll also need to provide the information to be formatted.
    yes_votes = 42_572_654  # equivalent of 42572654
    no_votes = 43_132_495   # equivalent of 43132495
    percentage = yes_votes / (yes_votes + no_votes)

    assert '{:-9} YES votes  {:2.2%}'.format(yes_votes, percentage) == ' 42572654 YES votes  49.67%'

    # When you don’t need fancy output but just want a quick display of some variables for debugging
    # purposes, you can convert any value to a string with the repr() or str() functions. The str()
    # function is meant to return representations of values which are fairly human-readable, while
    # repr() is meant to generate representations which can be read by the interpreter (or will
    # force a SyntaxError if there is no equivalent syntax). For objects which don’t have a
    # particular representation for human consumption, str() will return the same value as repr().
    # Many values, such as numbers or structures like lists and dictionaries, have the same
    # representation using either function. Strings, in particular, have two distinct
    # representations.

    greeting = 'Hello, world.'
    first_num = 10 * 3.25
    second_num = 200 * 200

    assert str(greeting) == 'Hello, world.'
    assert repr(greeting) == "'Hello, world.'"
    assert str(1/7) == '0.14285714285714285'

    # The argument to repr() may be any Python object:
    assert repr((first_num, second_num, ('spam', 'eggs'))) == "(32.5, 40000, ('spam', 'eggs'))"

    # Formatted String Literals

    # Formatted string literals (also called f-strings for short) let you include the value of
    # Python expressions inside a string by prefixing the string with f or F and writing
    # expressions as {expression}.

    # An optional format specifier can follow the expression. This allows greater control over how
    # the value is formatted. The following example rounds pi to three places after the decimal.
    pi_value = 3.14159
    assert f'The value of pi is {pi_value:.3f}.' == 'The value of pi is 3.142.'

    # Passing an integer after the ':' will cause that field to be a minimum number of characters
    # wide. This is useful for making columns line up:
    table_data = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
    table_string = ''
    for name, phone in table_data.items():
        table_string += f'{name:7}==>{phone:7d}'

    assert table_string == ('Sjoerd ==>   4127'
                            'Jack   ==>   4098'
                            'Dcab   ==>   7678')

    # The String format() Method

    # Basic usage of the str.format() method looks like this:
    assert 'We are {} who say "{}!"'.format('knights', 'Ni') == 'We are knights who say "Ni!"'

    # The brackets and characters within them (called format fields) are replaced with the objects
    # passed into the str.format() method. A number in the brackets can be used to refer to the
    # position of the object passed into the str.format() method
    assert '{0} and {1}'.format('spam', 'eggs') == 'spam and eggs'
    assert '{1} and {0}'.format('spam', 'eggs') == 'eggs and spam'

    # If keyword arguments are used in the str.format() method, their values are referred to by
    # using the name of the argument.
    formatted_string = 'This {food} is {adjective}.'.format(
        food='spam',
        adjective='absolutely horrible'
    )

    assert formatted_string == 'This spam is absolutely horrible.'

    # Positional and keyword arguments can be arbitrarily combined
    formatted_string = 'The story of {0}, {1}, and {other}.'.format(
        'Bill',
        'Manfred',
        other='Georg'
    )

    assert formatted_string == 'The story of Bill, Manfred, and Georg.'

    # If you have a really long format string that you don’t want to split up, it would be nice if
    # you could reference the variables to be formatted by name instead of by position. This can be
    # done by simply passing the dict and using square brackets '[]' to access the keys

    table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
    formatted_string = 'Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; Dcab: {0[Dcab]:d}'.format(table)

    assert formatted_string == 'Jack: 4098; Sjoerd: 4127; Dcab: 8637678'

    # This could also be done by passing the table as keyword arguments with the ‘**’ notation.
    formatted_string = 'Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table)

    assert formatted_string == 'Jack: 4098; Sjoerd: 4127; Dcab: 8637678'


================================================
FILE: src/data_types/test_tuples.py
================================================
"""Tuples.

@see: https://www.w3schools.com/python/python_tuples.asp
@see: https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences

A tuple is a collection which is ordered and unchangeable. In Python tuples are written with
round brackets.

The Tuples have following properties:
- You cannot change values in a tuple.
- You cannot remove items in a tuple.
"""

import pytest


def test_tuples():
    """Tuples"""
    fruits_tuple = ("apple", "banana", "cherry")

    assert isinstance(fruits_tuple, tuple)
    assert fruits_tuple[0] == "apple"
    assert fruits_tuple[1] == "banana"
    assert fruits_tuple[2] == "cherry"

    # You cannot change values in a tuple.
    with pytest.raises(Exception):
        # pylint: disable=unsupported-assignment-operation
        fruits_tuple[0] = "pineapple"

    # It is also possible to use the tuple() constructor to make a tuple (note the double
    # round-brackets).
    # The len() function returns the length of the tuple.
    fruits_tuple_via_constructor = tuple(("apple", "banana", "cherry"))

    assert isinstance(fruits_tuple_via_constructor, tuple)
    assert len(fruits_tuple_via_constructor) == 3

    # It is also possible to omit brackets when initializing tuples.
    another_tuple = 12345, 54321, 'hello!'
    assert another_tuple == (12345, 54321, 'hello!')

    # Tuples may be nested:
    nested_tuple = another_tuple, (1, 2, 3, 4, 5)
    assert nested_tuple == ((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))

    # As you see, on output tuples are always enclosed in parentheses, so that nested tuples are
    # interpreted correctly; they may be input with or without surrounding parentheses, although
    # often parentheses are necessary anyway (if the tuple is part of a larger expression). It is
    # not possible to assign to the individual items of a tuple, however it is possible to create
    # tuples which contain mutable objects, such as lists.

    # A special problem is the construction of tuples containing 0 or 1 items: the syntax has some
    # extra quirks to accommodate these. Empty tuples are constructed by an empty pair of
    # parentheses; a tuple with one item is constructed by following a value with a comma (it is
    # not sufficient to enclose a single value in parentheses). Ugly, but effective. For example:
    empty_tuple = ()
    # pylint: disable=len-as-condition
    assert len(empty_tuple) == 0

    # pylint: disable=trailing-comma-tuple
    singleton_tuple = 'hello',  # <-- note trailing comma
    assert len(singleton_tuple) == 1
    assert singleton_tuple == ('hello',)

    # The following example is called tuple packing:
    packed_tuple = 12345, 54321, 'hello!'

    # The reverse operation is also possible.
    first_tuple_number, second_tuple_number, third_tuple_string = packed_tuple
    assert first_tuple_number == 12345
    assert second_tuple_number == 54321
    assert third_tuple_string == 'hello!'

    # This is called, appropriately enough, sequence unpacking and works for any sequence on the
    # right-hand side. Sequence unpacking requires that there are as many variables on the left
    # side of the equals sign as there are elements in the sequence. Note that multiple assignment
    # is really just a combination of tuple packing and sequence unpacking.

    # Swapping using tuples.
    # Data can be swapped from one variable to another in python using
    # tuples. This eliminates the need to use a 'temp' variable.
    first_number = 123
    second_number = 456
    first_number, second_number = second_number, first_number

    assert first_number == 456
    assert second_number == 123


================================================
FILE: src/data_types/test_type_casting.py
================================================
"""Type casting.

@see: https://www.w3schools.com/python/python_casting.asp

There may be times when you want to specify a type on to a variable. This can be done with casting.
Python is an object-orientated language, and as such it uses classes to define data types,
including its primitive types.

Casting in python is therefore done using constructor functions:

- int() - constructs an integer number from an integer literal, a float literal (by rounding down
to the previous whole number) literal, or a string literal (providing the string represents a
whole number)

- float() - constructs a float number from an integer literal, a float literal or a string literal
(providing the string represents a float or an integer)

- str() - constructs a string from a wide variety of data types, including strings, integer
literals and float literals
"""


def test_type_casting_to_integer():
    """Type casting to integer"""

    assert int(1) == 1
    assert int(2.8) == 2
    assert int('3') == 3


def test_type_casting_to_float():
    """Type casting to float"""

    assert float(1) == 1.0
    assert float(2.8) == 2.8
    assert float("3") == 3.0
    assert float("4.2") == 4.2


def test_type_casting_to_string():
    """Type casting to string"""

    assert str("s1") == 's1'
    assert str(2) == '2'
    assert str(3.0) == '3.0'


================================================
FILE: src/exceptions/test_handle_exceptions.py
================================================
"""Errors and Exceptions.

@see: https://docs.python.org/3/tutorial/errors.html#errors-and-exceptions

Even if a statement or expression is syntactically correct, it may cause an error when an attempt
is made to execute it. Errors detected during execution are called exceptions and are not
unconditionally fatal.

It is possible to write programs that handle selected exceptions.
"""


def test_handle_exceptions():
    """Handling of exceptions

    The try statement works as follows.

    - First, the try clause (the statement(s) between the try and except keywords) is executed.

    - If no exception occurs, the except clause is skipped and execution of the try statement
    is finished.

    - If an exception occurs during execution of the try clause, the rest of the clause is skipped.
    Then if its type matches the exception named after the except keyword, the except clause is
    executed, and then execution continues after the try statement.

    - If an exception occurs which does not match the exception named in the except clause, it is
    passed on to outer try statements; if no handler is found, it is an unhandled exception and
    execution stops with a message.
    """

    # Let's simulate division by zero exception.
    exception_has_been_handled = False
    try:
        result = 10 * (1 / 0)  # division by zero
        # We should not get here at all.
        assert result
    except ZeroDivisionError:
        # We should get here because of division by zero.
        exception_has_been_handled = True

    assert exception_has_been_handled

    # Let's simulate undefined variable access exception.
    exception_has_been_handled = False
    try:
        # pylint: disable=undefined-variable
        result = 4 + spam * 3  # name 'spam' is not defined
        # We should not get here at all.
        assert result
    except NameError:
        # We should get here because of division by zero.
        exception_has_been_handled = True

    assert exception_has_been_handled

    # A try statement may have more than one except clause, to specify handlers for different
    # exceptions. At most one handler will be executed. Handlers only handle exceptions that occur
    # in the corresponding try clause, not in other handlers of the same try statement. An except
    # clause may name multiple exceptions as a parenthesized tuple, for example:

    exception_has_been_handled = False
    try:
        result = 10 * (1 / 0)  # division by zero
        # We should not get here at all.
        assert result
    except (ZeroDivisionError, NameError):
        # We should get here because of division by zero.
        exception_has_been_handled = True

    assert exception_has_been_handled

    # Exception handlers may be chained.
    exception_has_been_handled = False
    try:
        result = 10 * (1 / 0)  # division by zero
        # We should not get here at all.
        assert result
    except NameError:
        # We should get here because of division by zero.
        exception_has_been_handled = True
    except ZeroDivisionError:
        # We should get here because of division by zero.
        exception_has_been_handled = True

    assert exception_has_been_handled

    # The try … except statement has an optional else clause, which, when present, must follow all
    # except clauses. It is useful for code that must be executed if the try clause does not raise
    # an exception. For example:

    exception_has_been_handled = False
    no_exceptions_has_been_fired = False

    try:
        result = 10
        # We should not get here at all.
        assert result
    except NameError:
        # We should get here because of division by zero.
        exception_has_been_handled = True
    else:
        no_exceptions_has_been_fired = True

    assert not exception_has_been_handled
    assert no_exceptions_has_been_fired


================================================
FILE: src/exceptions/test_raise_exceptions.py
================================================
"""Raising Exceptions.

@see: https://docs.python.org/3/tutorial/errors.html#raising-exceptions

The raise statement allows the programmer to force a specified exception to occur.
"""


def test_raise_exception():
    """Raising Exceptions.

    The raise statement allows the programmer to force a specified exception to occur.
    """
    exception_is_caught = False

    try:
        # The sole argument to raise indicates the exception to be raised. This must be either an
        # exception instance or an exception class (a class that derives from Exception). If an
        # exception class is passed, it will be implicitly instantiated by calling its constructor
        # with no arguments
        raise NameError('HiThere')  # shorthand for 'raise ValueError()'
    except NameError:
        exception_is_caught = True

    assert exception_is_caught


def test_user_defined_exception():
    """User-defined Exceptions"""

    # Programs may name their own exceptions by creating a new exception class. Exceptions should
    # typically be derived from the Exception class, either directly or indirectly.
    # Most exceptions are defined with names that end in “Error,” similar to the naming of the
    # standard exceptions. Many standard modules define their own exceptions to report errors
    # that may occur in functions they define.
    class MyCustomError(Exception):
        """Example of MyCustomError exception."""
        def __init__(self, message):
            super().__init__(message)
            self.message = message

    custom_exception_is_caught = False

    try:
        raise MyCustomError('My custom message')
    except MyCustomError:
        custom_exception_is_caught = True

    assert custom_exception_is_caught


================================================
FILE: src/files/binary_file
================================================
0123456789abcdef

================================================
FILE: src/files/multi_line_file.txt
================================================
first line
second line
third line

================================================
FILE: src/files/test_file_methods.py
================================================
"""Methods of File Objects

@see: https://docs.python.org/3/tutorial/inputoutput.html#methods-of-file-objects

Reading from a file does not always have to be sequential. There are methods to look for
specific locations in the file, much like flipping to a page in a book.
"""


def test_file_methods():
    """Methods of File Objects"""

    multi_line_file = open('src/files/multi_line_file.txt', 'r')
    binary_file = open('src/files/binary_file', 'r')

    # To read a file’s contents, call f.read(size), which reads some quantity of data and returns
    # it as a string (in text mode) or bytes object (in binary mode). size is an optional numeric
    # argument. When size is omitted or negative, the entire contents of the file will be read and
    # returned; it’s your problem if the file is twice as large as your machine’s memory. Otherwise,
    # at most size bytes are read and returned. If the end of the file has been reached, f.read()
    # will return an empty string ('').
    read_data = multi_line_file.read()

    # pylint: disable=duplicate-code
    assert read_data == 'first line\nsecond line\nthird line'

    # To change the file object’s position, use f.seek(offset, from_what). The position is computed
    # from adding offset to a reference point; the reference point is selected by the from_what
    # argument. A from_what value of 0 measures from the beginning of the file, 1 uses the current
    # file position, and 2 uses the end of the file as the reference point. from_what can be omitted
    # and defaults to 0, using the beginning of the file as the reference point.
    assert binary_file.seek(0) == 0  # Go to the 0th byte in the file
    assert binary_file.seek(6) == 6  # Go to the 6th byte in the file

    assert binary_file.read(1) == '6'

    # f.readline() reads a single line from the file; a newline character (\n) is left at the end
    # of the string, and is only omitted on the last line of the file if the file doesn’t end in a
    # newline. This makes the return value unambiguous; if f.readline() returns an empty string,
    # the end of the file has been reached, while a blank line is represented by '\n', a string
    # containing only a single newline.
    multi_line_file.seek(0)

    assert multi_line_file.readline() == 'first line\n'
    assert multi_line_file.readline() == 'second line\n'
    assert multi_line_file.readline() == 'third line'
    assert multi_line_file.readline() == ''

    multi_line_file.close()
    binary_file.close()


================================================
FILE: src/files/test_file_reading.py
================================================
"""Reading and Writing Files

@see: https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files

The process of reading and writing to a file is like finding a book and opening a book.
First, the file is located, opened to the first page, then reading/writing begins until it reaches
the end of the file.
"""


def test_files_open():
    """Open files

    open() returns a file object, and is most commonly used with two arguments:
    open(filename, mode).

    The first argument is a string containing the filename. The second argument is another string
    containing a few characters describing the way in which the file will be used. mode can be:

    - 'r' when the file will only be read,
    - 'w' for only writing (an existing file with the same name will be erased),
    - 'a' opens the file for appending; any data written to the file is automatically added to end.
    - 'r+' opens the file for both reading and writing.

    The mode argument is optional; 'r' will be assumed if it’s omitted.

    Normally, files are opened in text mode, that means, you read and write strings from and to the
    file, which are encoded in a specific encoding. If encoding is not specified, the default is
    platform dependent (see open()). 'b' appended to the mode opens the file in binary mode: now
    the data is read and written in the form of bytes objects. This mode should be used for all
    files that don’t contain text.

    In text mode, the default when reading is to convert platform-specific line endings (\n on
    Unix, \r\n on Windows) to just \n. When writing in text mode, the default is to convert
    occurrences of \n back to platform-specific line endings. This behind-the-scenes modification
    to file data is fine for text files, but will corrupt binary data like that in JPEG or EXE
    files. Be very careful to use binary mode when reading and writing such files.

    It is good practice to use the with keyword when dealing with file objects. The advantage is
    that the file is properly closed after its suite finishes, even if an exception is raised at
    some point. Using with is also much shorter than writing equivalent try-finally blocks:
    """

    # Open files without using 'with' statement.
    file = open('src/files/multi_line_file.txt', 'r')

    assert not file.closed

    read_data = file.read()

    assert read_data == (
        'first line\n'
        'second line\n'
        'third line'
    )

    file.close()

    assert file.closed

    # Open file using with.
    with open('src/files/multi_line_file.txt', 'r') as file:
        read_data = file.read()

        assert read_data == (
            'first line\n'
            'second line\n'
            'third line'
        )

    assert file.closed

    # If you’re not using the with keyword, then you should call f.close() to close the file and
    # immediately free up any system resources used by it. If you don’t explicitly close a file,
    # Python’s garbage collector will eventually destroy the object and close the open file for you,
    # but the file may stay open for a while. Another risk is that different Python implementations
    # will do this clean-up at different times.


================================================
FILE: src/functions/test_function_annotations.py
================================================
"""Function Annotations.

@see: https://docs.python.org/3/tutorial/controlflow.html#function-annotations

Function annotations are completely optional metadata information about the types used
by user-defined functions.

Annotations are stored in the __annotations__ attribute of the function as a dictionary and have no
effect on any other part of the function. Parameter annotations are defined by a colon after the
parameter name, followed by an expression evaluating to the value of the annotation. Return
annotations are defined by a literal ->, followed by an expression, between the parameter list and
the colon denoting the end of the def statement.
"""


def breakfast(ham: str, eggs: str = 'eggs') -> str:
    """Breakfast creator.

    This function has a positional argument, a keyword argument, and the return value annotated.
    """
    return ham + ' and ' + eggs


def test_function_annotations():
    """Function Annotations."""

    assert breakfast.__annotations__ == {'eggs': str, 'ham': str, 'return': str}


================================================
FILE: src/functions/test_function_arbitrary_arguments.py
================================================
"""Arbitrary Argument Lists

@see: https://docs.python.org/3/tutorial/controlflow.html#arbitrary-argument-lists

Function can be called with an arbitrary number of arguments. These arguments will be wrapped up in
a tuple. Before the variable number of arguments, zero or more normal arguments may occur.
"""


def test_function_arbitrary_arguments():
    """Arbitrary Argument Lists"""

    # When a final formal parameter of the form **name is present, it receives a dictionary
    # containing all keyword arguments except for those corresponding to a formal parameter.
    # This may be combined with a formal parameter of the form *name which receives a tuple
    # containing the positional arguments beyond the formal parameter list.
    # (*name must occur before **name.) For example, if we define a function like this:
    def test_function(first_param, *arguments):
        """This function accepts its arguments through "arguments" tuple"""
        assert first_param == 'first param'
        assert arguments == ('second param', 'third param')

    test_function('first param', 'second param', 'third param')

    # Normally, these variadic arguments will be last in the list of formal parameters, because
    # they scoop up all remaining input arguments that are passed to the function. Any formal
    # parameters which occur after the *args parameter are ‘keyword-only’ arguments, meaning that
    # they can only be used as keywords rather than positional arguments.
    def concat(*args, sep='/'):
        return sep.join(args)

    assert concat('earth', 'mars', 'venus') == 'earth/mars/venus'
    assert concat('earth', 'mars', 'venus', sep='.') == 'earth.mars.venus'


================================================
FILE: src/functions/test_function_decorators.py
================================================
"""Function Decorators.

@see: https://www.thecodeship.com/patterns/guide-to-python-function-decorators/

Function decorators are simply wrappers to existing functions. In the context of design patterns,
decorators dynamically alter the functionality of a function, method or class without having to
directly use subclasses. This is ideal when you need to extend the functionality of functions that
you don't want to modify. We can implement the decorator pattern anywhere, but Python facilitates
the implementation by providing much more expressive features and syntax for that.
"""


def test_function_decorators():
    """Function Decorators."""

    # Function decorators are simply wrappers to existing functions. Putting the ideas mentioned
    # above together, we can build a decorator. In this example let's consider a function that
    # wraps the string output of another function by p tags.

    # This is the function that we want to decorate.
    def greeting(name):
        return "Hello, {0}!".format(name)

    # This function decorates another functions output with <p> tag.
    def decorate_with_p(func):
        def function_wrapper(name):
            return "<p>{0}</p>".format(func(name))
        return function_wrapper

    # Now, let's call our decorator and pass the function we want decorate to it.
    my_get_text = decorate_with_p(greeting)

    # Here we go, we've just decorated the function output without changing the function itself.
    assert my_get_text('John') == '<p>Hello, John!</p>'  # With decorator.
    assert greeting('John') == 'Hello, John!'  # Without decorator.

    # Now, Python makes creating and using decorators a bit cleaner and nicer for the programmer
    # through some syntactic sugar  There is a neat shortcut for that, which is to mention the
    # name of the decorating function before the function to be decorated. The name of the
    # decorator should be prepended with an @ symbol.

    @decorate_with_p
    def greeting_with_p(name):
        return "Hello, {0}!".format(name)

    assert greeting_with_p('John') == '<p>Hello, John!</p>'

    # Now let's consider we wanted to decorate our greeting function by one more functions to wrap a
    # div the string output.

    # This will be our second decorator.
    def decorate_with_div(func):
        def function_wrapper(text):
            return "<div>{0}</div>".format(func(text))
        return function_wrapper

    # With the basic approach, decorating get_text would be along the lines of
    # greeting_with_div_p = decorate_with_div(decorate_with_p(greeting_with_p))

    # With Python's decorator syntax, same thing can be achieved with much more expressive power.
    @decorate_with_div
    @decorate_with_p
    def greeting_with_div_p(name):
        return "Hello, {0}!".format(name)

    assert greeting_with_div_p('John') == '<div><p>Hello, John!</p></div>'

    # One important thing to notice here is that the order of setting our decorators matters.
    # If the order was different in the example above, the output would have been different.

    # Passing arguments to decorators.

    # Looking back at the example before, you can notice how redundant the decorators in the
    # example are. 2 decorators(decorate_with_div, decorate_with_p) each with the same
    # functionality but wrapping the string with different tags. We can definitely do much better
    # than that. Why not have a more general implementation for one that takes the tag to wrap
    # with as a string? Yes please!

    def tags(tag_name):
        def tags_decorator(func):
            def func_wrapper(name):
                return "<{0}>{1}</{0}>".format(tag_name, func(name))
            return func_wrapper
        return tags_decorator

    @tags('div')
    @tags('p')
    def greeting_with_tags(name):
        return "Hello, {0}!".format(name)

    assert greeting_with_tags('John') == '<div><p>Hello, John!</p></div>'


================================================
FILE: src/functions/test_function_default_arguments.py
================================================
"""Default Argument Values

@see: https://docs.python.org/3/tutorial/controlflow.html#default-argument-values

The most useful form is to specify a default value for one or more arguments. This creates a
function that can be called with fewer arguments than it is defined to allow.
"""


def power_of(number, power=2):
    """ Raises number to specific power.

    You may notice that by default the function raises number to the power of two.
    """
    return number ** power


def test_default_function_arguments():
    """Test default function arguments"""

    # This function power_of can be called in several ways because it has default value for
    # the second argument. First we may call it omitting the second argument at all.
    assert power_of(3) == 9
    # We may also want to override the second argument by using the following function calls.
    assert power_of(3, 2) == 9
    assert power_of(3, 3) == 27


================================================
FILE: src/functions/test_function_definition.py
================================================
"""Function Definition

@see: https://docs.python.org/3/tutorial/controlflow.html#defining-functions
@see: https://www.thecodeship.com/patterns/guide-to-python-function-decorators/

The keyword def introduces a function definition. It must be followed by the function name and the
parenthesized list of formal parameters. The statements that form the body of the function start at
the next line, and must be indented.
"""


def fibonacci_function_example(number_limit):
    """Generate a Fibonacci series up to number_limit.

    The first statement of the function body can optionally be a string literal; this string
    literal is the function’s documentation string, or docstring. There are tools which use
    docstrings to automatically produce online or printed documentation, or to let the user
    interactively browse through code; it’s good practice to include docstrings in code that you
    write, so make a habit of it.
    """

    # The execution of a function introduces a new symbol table used for the local variables of the
    # function. More precisely, all variable assignments in a function store the value in the local
    # symbol table; whereas variable references first look in the local symbol table, then in the
    # local symbol tables of enclosing functions, then in the global symbol table, and finally in
    # the table of built-in names. Thus, global variables cannot be directly assigned a value
    # within a function (unless named in a global statement), although they may be referenced.
    fibonacci_list = []
    previous_number, current_number = 0, 1
    while previous_number < number_limit:
        # The statement result.append(a) calls a method of the list object result. A method is a
        # function that ‘belongs’ to an object and is named obj.methodname, where obj is some
        # object (this may be an expression), and methodname is the name of a method that is
        # defined by the object’s type. Different types define different methods. Methods of
        # different types may have the same name without causing ambiguity. (It is possible to
        # define your own object types and methods, using classes, see Classes) The method
        # append() shown in the example is defined for list objects; it adds a new element at
        # the end of the list. In this example it is equivalent to result = result + [a], but
        # more efficient.
        fibonacci_list.append(previous_number)
        # This is multiple assignment statement. We make current number to be previous one and the
        # sum of previous and current to be a new current.
        previous_number, current_number = current_number, previous_number + current_number

    # The return statement returns with a value from a function. return without an expression
    # argument returns None. Falling off the end of a function also returns None.
    return fibonacci_list


def test_function_definition():
    """Function Definition"""

    # Now call the function we just defined.
    assert fibonacci_function_example(300) == [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233]

    # A function definition introduces the function name in the current symbol table. The value of
    # the function name has a type that is recognized by the interpreter as a user-defined function.
    # This value can be assigned to another name which can then also be used as a function. This
    # serves as a general renaming mechanism
    fibonacci_function_clone = fibonacci_function_example
    assert fibonacci_function_clone(300) == [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233]

    # In Python, functions are first class citizens, they are objects and that means we can do a
    # lot of useful stuff with them.

    # Assign functions to variables.

    def greet(name):
        return 'Hello, ' + name

    greet_someone = greet

    assert greet_someone('John') == 'Hello, John'

    # Define functions inside other functions.

    def greet_again(name):
        def get_message():
            return 'Hello, '

        result = get_message() + name
        return result

    assert greet_again('John') == 'Hello, John'

    # Functions can be passed as parameters to other functions.

    def greet_one_more(name):
        return 'Hello, ' + name

    def call_func(func):
        other_name = 'John'
        return func(other_name)

    assert call_func(greet_one_more) == 'Hello, John'

    # Functions can return other functions. In other words, functions generating other functions.

    def compose_greet_func():
        def get_message():
            return 'Hello there!'

        return get_message

    greet_function = compose_greet_func()
    assert greet_function() == 'Hello there!'

    # Inner functions have access to the enclosing scope.

    # More commonly known as a closure. A very powerful pattern that we will come across while
    # building decorators. Another thing to note, Python only allows read access to the outer
    # scope and not assignment. Notice how we modified the example above to read a "name" argument
    # from the enclosing scope of the inner function and return the new function.

    def compose_greet_func_with_closure(name):
        def get_message():
            return 'Hello there, ' + name + '!'

        return get_message

    greet_with_closure = compose_greet_func_with_closure('John')

    assert greet_with_closure() == 'Hello there, John!'


================================================
FILE: src/functions/test_function_documentation_string.py
================================================
"""Documentation Strings.

@see: https://docs.python.org/3/tutorial/controlflow.html#documentation-strings

Here are some conventions about the content and formatting of documentation strings.

The first line should always be a short, concise summary of the object’s purpose. For brevity,
it should not explicitly state the object’s name or type, since these are available by other means
(except if the name happens to be a verb describing a function’s operation). This line should begin
with a capital letter and end with a period.

If there are more lines in the documentation string, the second line should be blank, visually
separating the summary from the rest of the description. The following lines should be one or more
paragraphs describing the object’s calling conventions, its side effects, etc.
"""


def do_nothing():
    """Do nothing, but document it.

    No, really, it doesn't do anything.
    """
    pass


def test_function_documentation_string():
    """Test documentation string."""

    # The Python parser does not strip indentation from multi-line string literals in Python, so
    # tools that process documentation have to strip indentation if desired. This is done using the
    # following convention. The first non-blank line after the first line of the string determines
    # the amount of indentation for the entire documentation string. (We can’t use the first line
    # since it is generally adjacent to the string’s opening quotes so its indentation is not
    # apparent in the string literal.) Whitespace “equivalent” to this indentation is then stripped
    # from the start of all lines of the string. Lines that are indented less should not occur, but
    # if they occur all their leading whitespace should be stripped. Equivalence of whitespace
    # should be tested after expansion of tabs (to 8 spaces, normally).

    assert do_nothing.__doc__ == """Do nothing, but document it.

    No, really, it doesn't do anything.
    """


================================================
FILE: src/functions/test_function_keyword_arguments.py
================================================
"""Keyword Arguments

@see: https://docs.python.org/3/tutorial/controlflow.html#keyword-arguments

Functions can be called using keyword arguments of the form kwarg=value.
"""

import pytest


def parrot(voltage, state='a stiff', action='voom', parrot_type='Norwegian Blue'):
    """Example of multi-argument function

    This function accepts one required argument (voltage) and three optional arguments
    (state, action, and type).
    """

    message = 'This parrot wouldn\'t ' + action + ' '
    message += 'if you put ' + str(voltage) + ' volts through it. '
    message += 'Lovely plumage, the ' + parrot_type + '. '
    message += 'It\'s ' + state + '!'

    return message


def test_function_keyword_arguments():
    """Test calling function with specifying keyword arguments"""

    # The parrot function accepts one required argument (voltage) and three optional arguments
    # (state, action, and type). This function can be called in any of the following ways:

    message = (
        "This parrot wouldn't voom if you put 1000 volts through it. "
        "Lovely plumage, the Norwegian Blue. "
        "It's a stiff!"
    )
    # 1 positional argument
    assert parrot(1000) == message
    # 1 keyword argument
    assert parrot(voltage=1000) == message

    message = (
        "This parrot wouldn't VOOOOOM if you put 1000000 volts through it. "
        "Lovely plumage, the Norwegian Blue. "
        "It's a stiff!"
    )
    # 2 keyword arguments
    assert parrot(voltage=1000000, action='VOOOOOM') == message
    # 2 keyword arguments
    assert parrot(action='VOOOOOM', voltage=1000000) == message

    # 3 positional arguments
    message = (
        "This parrot wouldn't jump if you put 1000000 volts through it. "
        "Lovely plumage, the Norwegian Blue. "
        "It's bereft of life!"
    )
    assert parrot(1000000, 'bereft of life', 'jump') == message

    # 1 positional, 1 keyword
    message = (
        "This parrot wouldn't voom if you put 1000 volts through it. "
        "Lovely plumage, the Norwegian Blue. "
        "It's pushing up the daisies!"
    )
    assert parrot(1000, state='pushing up the daisies') == message

    # But all the following calls would be invalid.

    with pytest.raises(Exception):
        # Required argument missing.
        # pylint: disable=no-value-for-parameter
        parrot()

    # Non-keyword argument after a keyword argument.
    # parrot(voltage=5.0, 'dead')

    with pytest.raises(Exception):
        # pylint: disable=redundant-keyword-arg
        parrot(110, voltage=220)

    with pytest.raises(Exception):
        # unknown keyword argument
        # pylint: disable=unexpected-keyword-arg,no-value-for-parameter
        parrot(actor='John Cleese')

    # In a function call, keyword arguments must follow positional arguments. All the keyword
    # arguments passed must match one of the arguments accepted by the function (e.g. actor is not
    # a valid argument for the parrot function), and their order is not important. This also
    # includes non-optional arguments (e.g. parrot(voltage=1000) is valid too). No argument may
    # receive a value more than once. Here’s an example that fails due to this restriction:
    def function_with_one_argument(number):
        return number

    with pytest.raises(Exception):
        # pylint: disable=redundant-keyword-arg
        function_with_one_argument(0, number=0)

    # When a final formal parameter of the form **name is present, it receives a dictionary
    # containing all keyword arguments except for those corresponding to a formal parameter.
    # This may be combined with a formal parameter of the form *name which receives a tuple
    # containing the positional arguments beyond the formal parameter list.
    # (*name must occur before **name.) For example, if we define a function like this:
    def test_function(first_param, *arguments, **keywords):
        """This function accepts its arguments through "arguments" tuple and keywords dictionary."""
        assert first_param == 'first param'
        assert arguments == ('second param', 'third param')
        assert keywords == {
            'fourth_param_name': 'fourth named param',
            'fifth_param_name': 'fifth named param'
        }

    test_function(
        'first param',
        'second param',
        'third param',
        fourth_param_name='fourth named param',
        fifth_param_name='fifth named param',
    )


================================================
FILE: src/functions/test_function_scopes.py
================================================
"""Scopes and Namespaces.

@see: https://docs.python.org/3/tutorial/classes.html#scopes-and-namespaces-example

A NAMESPACE is a mapping from names to objects. Most namespaces are currently implemented as Python
dictionaries, but that’s normally not noticeable in any way (except for performance), and it may
change in the future. Examples of namespaces are: the set of built-in names (containing functions
such as abs(), and built-in exception names); the global names in a module; and the local names
in a function invocation. In a sense the set of attributes of an object also form a namespace.
The important thing to know about namespaces is that there is absolutely no relation between names
in different namespaces; for instance, two different modules may both define a function maximize
without confusion — users of the modules must prefix it with the module name.

By the way, we use the word attribute for any name following a dot — for example, in the expression
z.real, real is an attribute of the object z. Strictly speaking, references to names in modules are
attribute references: in the expression modname.func_name, modname is a module object and func_name
is an attribute of it. In this case there happens to be a straightforward mapping between the
module’s attributes and the global names defined in the module: they share the same namespace!

A SCOPE is a textual region of a Python program where a namespace is directly accessible.
“Directly accessible” here means that an unqualified reference to a name attempts to find the name
in the namespace.

Although scopes are determined statically, they are used dynamically. At any time during execution,
there are at least three nested scopes whose namespaces are directly accessible:
- the innermost scope, which is searched first, contains the local names.
- the scopes of any enclosing functions, which are searched starting with the nearest enclosing
scope, contains non-local, but also non-global names.
- the next-to-last scope contains the current module’s global names.
- the outermost scope (searched last) is the namespace containing built-in names.

BE CAREFUL!!!
-------------
Changing global or nonlocal variables from within an inner function might be a BAD
practice and might lead to harder debugging and to more fragile code! Do this only if you know
what you're doing.
"""

# pylint: disable=invalid-name
test_variable = 'initial global value'


def test_function_scopes():
    """Scopes and Namespaces Example"""

    # This is an example demonstrating how to reference the different scopes and namespaces, and
    # how global and nonlocal affect variable binding:

    # pylint: disable=redefined-outer-name
    test_variable = 'initial value inside test function'

    def do_local():
        # Create variable that is only accessible inside current do_local() function.
        # pylint: disable=redefined-outer-name
        test_variable = 'local value'
        return test_variable

    def do_nonlocal():
        # Address the variable from outer scope and try to change it.
        # pylint: disable=redefined-outer-name
        nonlocal test_variable
        test_variable = 'nonlocal value'
        return test_variable

    def do_global():
        # Address the variable from very global scope and try to change it.
        # pylint: disable=redefined-outer-name,global-statement
        global test_variable
        test_variable = 'global value'
        return test_variable

    # On this level currently we have access to local for test_function_scopes() function variable.
    assert test_variable == 'initial value inside test function'

    # Do local assignment.
    # It doesn't change global variable and variable from test_function_scopes() scope.
    do_local()
    assert test_variable == 'initial value inside test function'

    # Do non local assignment.
    # It doesn't change global variable but it does change variable
    # from test_function_scopes() function scope.
    do_nonlocal()
    assert test_variable == 'nonlocal value'

    # Do global assignment.
    # This one changes global variable but doesn't change variable from
    # test_function_scopes() function scope.
    do_global()
    assert test_variable == 'nonlocal value'


def test_global_variable_access():
    """Testing global variable access from within a function"""

    # Global value of test_variable has been already changed by do_global() function in previous
    # test so let's check that.
    # pylint: disable=global-statement
    global test_variable
    assert test_variable == 'global value'

    # On this example you may see how accessing and changing global variables from within inner
    # functions might make debugging more difficult and code to be less predictable. Since you
    # might have expected that test_variable should still be equal to 'initial global value' but
    # it was changed by "someone" and you need to know about the CONTEXT of who had changed that.
    # So once again access global and non local scope only if you know what you're doing otherwise
    # it might be considered as bad practice.


================================================
FILE: src/functions/test_function_unpacking_arguments.py
================================================
"""Unpacking Argument Lists

@see: https://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists

Unpacking arguments may be executed via * and ** operators. See below for further details.
"""


def test_function_unpacking_arguments():
    """Unpacking Argument Lists"""

    # The situation may occur when the arguments are already in a list or tuple but need to be
    # unpacked for a function call requiring separate positional arguments. For instance, the
    # built-in range() function expects separate start and stop arguments. If they are not
    # available separately, write the function call with the *-operator to unpack the arguments out
    # of a list or tuple:

    # Normal call with separate arguments:
    assert list(range(3, 6)) == [3, 4, 5]

    # Call with arguments unpacked from a list.
    arguments_list = [3, 6]
    assert list(range(*arguments_list)) == [3, 4, 5]

    # In the same fashion, dictionaries can deliver keyword arguments with the **-operator:
    def function_that_receives_names_arguments(first_word, second_word):
        return first_word + ', ' + second_word + '!'

    arguments_dictionary = {'first_word': 'Hello', 'second_word': 'World'}
    assert function_that_receives_names_arguments(**arguments_dictionary) == 'Hello, World!'


================================================
FILE: src/functions/test_lambda_expressions.py
================================================
"""Lambda Expressions

@see: https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions

Small anonymous functions can be created with the lambda keyword. Lambda functions can be used
wherever function objects are required. They are syntactically restricted to a single expression.
Semantically, they are just syntactic sugar for a normal function definition. Like nested function
definitions, lambda functions can reference variables from the containing scope.
"""


def test_lambda_expressions():
    """Lambda Expressions"""

    # This function returns the sum of its two arguments: lambda a, b: a+b
    # Like nested function definitions, lambda functions can reference variables from the
    # containing scope.

    def make_increment_function(delta):
        """This example uses a lambda expression to return a function"""
        return lambda number: number + delta

    increment_function = make_increment_function(42)

    assert increment_function(0) == 42
    assert increment_function(1) == 43
    assert increment_function(2) == 44

    # Another use of lambda is to pass a small function as an argument.
    pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
    # Sort pairs by text key.
    pairs.sort(key=lambda pair: pair[1])

    assert pairs == [(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]


================================================
FILE: src/getting_started/python_syntax.md
================================================
# Python Syntax

**Python Syntax compared to other programming languages**

- Python was designed to for readability, and has some similarities to the English language with influence from mathematics.
- Python uses new lines to complete a command, as opposed to other programming languages which often use semicolons or parentheses.
- Python relies on indentation, using whitespace, to define scope; such as the scope of loops, functions and classes. Other programming languages often use curly-brackets for this purpose.

## Python Indentations

Where in other programming languages the indentation in code is for readability only, in Python the indentation is very important.

Python uses indentation to indicate a block of code.

```python
if 5 > 2:
  print("Five is greater than two!")
```

Python will give you an error if you skip the indentation.

## Comments

Python has commenting capability for the purpose of in-code documentation.

Comments start with a `#`, and Python will render the rest of the line as a comment:

```python
#This is a comment.
print("Hello, World!")
```

## Docstrings

Python also has extended documentation capability, called docstrings.

Docstrings can be one line, or multiline. Docstrings are also comments:

Python uses triple quotes at the beginning and end of the docstring:

```python
"""This is a 
multiline docstring."""
print("Hello, World!")
```

## References

- [w3schools.com](https://www.w3schools.com/python/python_syntax.asp)


================================================
FILE: src/getting_started/test_variables.py
================================================
"""Variables

@see: https://docs.python.org/3/tutorial/introduction.html
@see: https://www.w3schools.com/python/python_variables.asp
@see: https://www.learnpython.org/en/Variables_and_Types

Python is completely object oriented, and not "statically typed".
You do not need to declare variables before using them, or declare
their type. Every variable in Python is an object.

Unlike other programming languages, Python has no command for
declaring a variable. A variable is created the moment you first assign
a value to it.

A variable can have a short name (like x and y) or a more descriptive name
(age, carname, total_volume).

Rules for Python variables:
- A variable name must start with a letter or the underscore character.
- A variable name cannot start with a number.
- A variable name can only contain alpha-numeric characters and underscores (A-z, 0-9, and _ ).
- Variable names are case-sensitive (age, Age and AGE are three different variables).
"""


def test_variables():
    """Test variables"""

    integer_variable = 5
    string_variable = 'John'

    assert integer_variable == 5
    assert string_variable == 'John'

    variable_with_changed_type = 4  # x is of type int
    variable_with_changed_type = 'Sally'  # x is now of type str

    assert variable_with_changed_type == 'Sally'


================================================
FILE: src/getting_started/what_is_python.md
================================================
# What is Python

Python is a popular programming language. It was created in 1991 by Guido van Rossum.

Python is an easy to learn, powerful programming language. It has efficient high-level data structures and a simple but effective approach to object-oriented programming. Python’s elegant syntax and dynamic typing, together with its interpreted nature, make it an ideal language for scripting and rapid application development in many areas on most platforms.

It is used for:

- web development (server-side),
- software development,
- mathematics,
- system scripting.

## What can Python do?

- Python can be used on a server to create web applications.
- Python can be used alongside software to create workflows.
- Python can connect to database systems. It can also read and modify files.
- Python can be used to handle big data and perform complex mathematics.
- Python can be used for rapid prototyping, or for production-ready software development.

## Why Python?

- Python works on different platforms (Windows, Mac, Linux, Raspberry Pi, etc).
- Python has a simple syntax similar to the English language.
- Python has syntax that allows developers to write programs with fewer lines than some other programming languages.
- Python runs on an interpreter system, meaning that code can be executed as soon as it is written. This means that prototyping can be very quick.
- Python can be treated in a procedural way, an object-orientated way or a functional way.

## Good to know

- The most recent major version of Python is Python 3, which we shall be using in this tutorial. However, Python 2, although not being updated with anything other than security updates, is still quite popular.
- In this tutorial Python will be written in a text editor. It is possible to write Python in an Integrated Development Environment, such as Thonny, Pycharm, Netbeans or Eclipse which are particularly useful when managing larger collections of Python files.

## References

- [w3schools.com](https://www.w3schools.com/python/python_intro.asp)

================================================
FILE: src/modules/fibonacci_module.py
================================================
"""Fibonacci numbers module.

@see: https://docs.python.org/3/tutorial/modules.html

A module is a file containing Python definitions and statements. The file name is the module name
with the suffix .py appended. Within a module, the module’s name (as a string) is available as the
value of the global variable __name__.
"""


def fibonacci_at_position(position):
    """Return Fibonacci number at specified position"""
    current_position = 0
    previous_number, current_number = 0, 1
    while current_position < position:
        current_position += 1
        previous_number, current_number = current_number, previous_number + current_number
    return previous_number


def fibonacci_smaller_than(limit):
    """Return Fibonacci series up to limit"""
    result = []
    previous_number, current_number = 0, 1
    while previous_number < limit:
        result.append(previous_number)
        previous_number, current_number = current_number, previous_number + current_number
    return result


# When you run a Python module with:
#
# >>> python fibonacci.py <arguments>
#
# the code in the module will be executed, just as if you imported it, but with
# the __name__ set to "__main__". That means that by adding this code at the end of your module
# you can make the file usable as a script as well as an importable module, because the code that
# parses the command line only runs if the module is executed as the “main” file:
#
# >>> python fibonacci.py 50
if __name__ == '__main__':
    import sys
    print(fibonacci_smaller_than(int(sys.argv[1])))


================================================
FILE: src/modules/sound_package/__init__.py
================================================


================================================
FILE: src/modules/sound_package/effects/__init__.py
================================================


================================================
FILE: src/modules/sound_package/effects/echo.py
================================================
"""Echo effect."""


def echo_function():
    """Echo function mock"""
    return 'Do echo effect'


================================================
FILE: src/modules/sound_package/effects/reverse.py
================================================
"""Reverse effect."""


def reverse_function():
    """Reveres function mock"""
    return 'Do reverse effect'


================================================
FILE: src/modules/sound_package/formats/__init__.py
================================================


================================================
FILE: src/modules/sound_package/formats/aif.py
================================================
"""AIF file support."""


def aif_read():
    """AIF file reading function mock"""
    return 'Read from AIF file'


================================================
FILE: src/modules/sound_package/formats/wav.py
================================================
"""WAV file support."""


def wav_read():
    """WAV file reading function mock"""
    return 'Read from WAV file'


================================================
FILE: src/modules/test_modules.py
================================================
"""Modules.

@see: https://docs.python.org/3/tutorial/modules.html

As your program gets longer, you may want to split it into several files for easier maintenance.
You may also want to use a handy function that you’ve written in several programs without copying
its definition into each program.

To support this, Python has a way to put definitions in a file and use them in a script or in an
interactive instance of the interpreter. Such a file is called a module; definitions from a module
can be imported into other modules or into the main module (the collection of variables that you
have access to in a script executed at the top level and in calculator mode).

A module is a file containing Python definitions and statements. The file name is the module name
with the suffix .py appended. Within a module, the module’s name (as a string) is available as the
value of the global variable __name__.

When the interpreter executes the import statement, it searches for module in a list of
directories assembled from the following sources:

- The directory from which the input script was run or the current directory if the interpreter is
being run interactively
- The list of directories contained in the PYTHONPATH environment variable, if it is set. (The
format for PYTHONPATH is OS-dependent but should mimic the PATH environment variable.)
- An installation-dependent list of directories configured at the time Python is installed

The resulting search path is accessible in the Python variable sys.path, which is obtained from a
module named sys:

>>> import sys
>>> sys.path

@see: https://realpython.com/python-modules-packages/
"""

# This does not enter the names of the functions defined in fibonacci_module directly in the
# current symbol table; it only enters the module name fibonacci_module there.
import fibonacci_module

# There is a variant of the import statement that imports names from a module directly into the
# importing module’s symbol table. For example:

# pylint: disable=reimported
from fibonacci_module import fibonacci_at_position, fibonacci_smaller_than

# There is even a variant to import all names that a module defines. This imports all names except
# those beginning with an underscore (_). In most cases Python programmers do not use this facility
# since it introduces an unknown set of names into the interpreter, possibly hiding some things you
# have already defined.
# >>> from fibonacci_module import *

# If the module name is followed by as, then the name following as is bound directly to the
# imported module:
import fibonacci_module as fibonacci_module_renamed

# It can also be used when utilising from with similar effects:
from fibonacci_module import fibonacci_at_position as fibonacci_at_position_renamed

# When a module named spam is imported, the interpreter first searches for a built-in module with
# that name. If not found, it then searches for a file named spam.py in a list of directories
# given by the variable sys.path. sys.path is initialized from these locations:
#
# - The directory containing the input script (or the current directory when no file is specified).
# - PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).
# - The installation-dependent default.


def test_modules():
    """Modules"""

    assert fibonacci_module.fibonacci_at_position(7) == 13
    assert fibonacci_at_position(7) == 13
    assert fibonacci_module_renamed.fibonacci_at_position(7) == 13
    assert fibonacci_at_position_renamed(7) == 13

    assert fibonacci_module.fibonacci_smaller_than(100) == [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
    assert fibonacci_smaller_than(100) == [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
    assert fibonacci_module_renamed.fibonacci_smaller_than(10) == [0, 1, 1, 2, 3, 5, 8]

    # If you intend to use a function often you can assign it to a local name.
    fibonacci = fibonacci_module.fibonacci_smaller_than
    assert fibonacci(100) == [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

    # The built-in function dir() is used to find out which names a module defines. It returns a
    # sorted list of strings.
    assert dir(fibonacci_module) == [
        '__builtins__',
        '__cached__',
        '__doc__',
        '__file__',
        '__loader__',
        '__name__',
        '__package__',
        '__spec__',
        'fibonacci_at_position',
        'fibonacci_smaller_than',
    ]


================================================
FILE: src/modules/test_packages.py
================================================
"""Packages.

@see: https://docs.python.org/3/tutorial/modules.html#packages

Packages are a way of structuring Python’s module namespace by using “dotted module names”. For
example, the module name A.B designates a submodule named B in a package named A. Just like the
use of modules saves the authors of different modules from having to worry about each other’s
global variable names, the use of dotted module names saves the authors of multi-module packages
like NumPy or Pillow from having to worry about each other’s module names.

The __init__.py files are required to make Python treat the directories as containing packages;
this is done to prevent directories with a common name, such as string, from unintentionally hiding
valid modules that occur later on the module search path. In the simplest case, __init__.py can
just be an empty file, but it can also execute initialization code for the package or set the
__all__ variable, described later.

When the interpreter executes the import statement, it searches for module in a list of
directories assembled from the following sources:

- The directory from which the input script was run or the current directory if the interpreter is
being run interactively
- The list of directories contained in the PYTHONPATH environment variable, if it is set. (The
format for PYTHONPATH is OS-dependent but should mimic the PATH environment variable.)
- An installation-dependent list of directories configured at the time Python is installed

The resulting search path is accessible in the Python variable sys.path, which is obtained from a
module named sys:

>>> import sys
>>> sys.path

@see: https://realpython.com/python-modules-packages/
"""

# Users of the package can import individual modules from the package, for example.
import sound_package.effects.echo

# An alternative way of importing the submodule is:

# pylint: disable=reimported
from sound_package.effects import echo

# Yet another variation is to import the desired function or variable directly:
from sound_package.effects.echo import echo_function

# Note that when using from package import item, the item can be either a submodule (or subpackage)
# of the package, or some other name defined in the package, like a function, class or variable.
# The import statement first tests whether the item is defined in the package; if not, it assumes
# it is a module and attempts to load it. If it fails to find it, an ImportError exception is
# raised.

# Contrarily, when using syntax like import item.subitem.subsubitem, each item except for the last
# must be a package; the last item can be a module or a package but can’t be a class or function or
# variable defined in the previous item.


def test_packages():
    """Packages."""
    assert sound_package.effects.echo.echo_function() == 'Do echo effect'
    assert echo.echo_function() == 'Do echo effect'
    assert echo_function() == 'Do echo effect'


================================================
FILE: src/operators/test_arithmetic.py
================================================
"""Arithmetic operators

@see: https://www.w3schools.com/python/python_operators.asp

Arithmetic operators are used with numeric values to perform common mathematical operations
"""


def test_arithmetic_operators():
    """Arithmetic operators"""

    # Addition.
    assert 5 + 3 == 8

    # Subtraction.
    assert 5 - 3 == 2

    # Multiplication.
    assert 5 * 3 == 15
    assert isinstance(5 * 3, int)

    # Division.
    # Result of division is float number.
    assert 5 / 3 == 1.6666666666666667
    assert 8 / 4 == 2
    assert isinstance(5 / 3, float)
    assert isinstance(8 / 4, float)

    # Modulus.
    assert 5 % 3 == 2

    # Exponentiation.
    assert 5 ** 3 == 125
    assert 2 ** 3 == 8
    assert 2 ** 4 == 16
    assert 2 ** 5 == 32
    assert isinstance(5 ** 3, int)

    # Floor division.
    assert 5 // 3 == 1
    assert 6 // 3 == 2
    assert 7 // 3 == 2
    assert 9 // 3 == 3
    assert isinstance(5 // 3, int)


================================================
FILE: src/operators/test_assigment.py
================================================
"""Assignment operators

@see: https://www.w3schools.com/python/python_operators.asp

Assignment operators are used to assign values to variables
"""


def test_assignment_operator():
    """Assignment operator """

    # Assignment: =
    number = 5
    assert number == 5

    # Multiple assignment.
    # The variables first_variable and second_variable simultaneously get the new values 0 and 1.
    first_variable, second_variable = 0, 1
    assert first_variable == 0
    assert second_variable == 1

    # You may even switch variable values using multiple assignment.
    first_variable, second_variable = second_variable, first_variable
    assert first_variable == 1
    assert second_variable == 0


def test_augmented_assignment_operators():
    """Assignment operator combined with arithmetic and bitwise operators"""

    # Assignment: +=
    number = 5
    number += 3
    assert number == 8

    # Assignment: -=
    number = 5
    number -= 3
    assert number == 2

    # Assignment: *=
    number = 5
    number *= 3
    assert number == 15

    # Assignment: /=
    number = 8
    number /= 4
    assert number == 2

    # Assignment: %=
    number = 8
    number %= 3
    assert number == 2

    # Assignment: %=
    number = 5
    number %= 3
    assert number == 2

    # Assignment: //=
    number = 5
    number //= 3
    assert number == 1

    # Assignment: **=
    number = 5
    number **= 3
    assert number == 125

    # Assignment: &=
    number = 5  # 0b0101
    number &= 3  # 0b0011
    assert number == 1  # 0b0001

    # Assignment: |=
    number = 5  # 0b0101
    number |= 3  # 0b0011
    assert number == 7  # 0b0111

    # Assignment: ^=
    number = 5  # 0b0101
    number ^= 3  # 0b0011
    assert number == 6  # 0b0110

    # Assignment: >>=
    number = 5
    number >>= 3
    assert number == 0  # (((5 // 2) // 2) // 2)

    # Assignment: <<=
    number = 5
    number <<= 3
    assert number == 40  # 5 * 2 * 2 * 2


================================================
FILE: src/operators/test_bitwise.py
================================================
"""Bitwise operators

@see: https://www.w3schools.com/python/python_operators.asp

Bitwise operators manipulate numbers on bit level.
"""


def test_bitwise_operators():
    """Bitwise operators"""

    # AND
    # Sets each bit to 1 if both bits are 1.
    #
    # Example:
    # 5 = 0b0101
    # 3 = 0b0011
    assert 5 & 3 == 1  # 0b0001

    # OR
    # Sets each bit to 1 if one of two bits is 1.
    #
    # Example:
    # 5 = 0b0101
    # 3 = 0b0011
    assert 5 | 3 == 7  # 0b0111

    # NOT
    # Inverts all the bits.
    assert ~5 == -6

    # XOR
    # Sets each bit to 1 if only one of two bits is 1.
    #
    # Example:
    # 5 = 0b0101
    # 3 = 0b0011
    number = 5  # 0b0101
    number ^= 3  # 0b0011
    assert 5 ^ 3 == 6  # 0b0110

    # Signed right shift
    # Shift right by pushing copies of the leftmost bit in from the left, and let the rightmost
    # bits fall off.
    #
    # Example:
    # 5 = 0b0101
    assert 5 >> 1 == 2  # 0b0010
    assert 5 >> 2 == 1  # 0b0001

    # Zero fill left shift
    # Shift left by pushing zeros in from the right and let the leftmost bits fall off.
    #
    # Example:
    # 5 = 0b0101
    assert 5 << 1 == 10  # 0b1010
    assert 5 << 2 == 20  # 0b10100


================================================
FILE: src/operators/test_comparison.py
================================================
"""Comparison operators

@see: https://www.w3schools.com/python/python_operators.asp

Comparison operators are used to compare two values.
"""


def test_comparison_operators():
    """Comparison operators"""

    # Equal.
    number = 5
    assert number == 5

    # Not equal.
    number = 5
    assert number != 3

    # Greater than.
    number = 5
    assert number > 3

    # Less than.
    number = 5
    assert number < 8

    # Greater than or equal to
    number = 5
    assert number >= 5
    assert number >= 4

    # Less than or equal to
    number = 5
    assert number <= 5
    assert number <= 6


================================================
FILE: src/operators/test_identity.py
================================================
"""Identity operators

@see: https://www.w3schools.com/python/python_operators.asp

Identity operators are used to compare the objects, not if they are equal, but if they are actually
the same object, with the same memory location.
"""


def test_identity_operators():
    """Identity operators"""

    # Let's illustrate identity operators based on the following lists.
    first_fruits_list = ["apple", "banana"]
    second_fruits_list = ["apple", "banana"]
    third_fruits_list = first_fruits_list

    # is
    # Returns true if both variables are the same object.

    # Example:
    # first_fruits_list and third_fruits_list are the same objects.
    assert first_fruits_list is third_fruits_list

    # is not
    # Returns true if both variables are not the same object.

    # Example:
    # first_fruits_list and second_fruits_list are not the same objects, even if they have
    # the same content
    assert first_fruits_list is not second_fruits_list

    # To demonstrate the difference between "is" and "==": this comparison returns True because
    # first_fruits_list is equal to second_fruits_list.
    assert first_fruits_list == second_fruits_list


================================================
FILE: src/operators/test_logical.py
================================================
"""Logical operators

@see: https://www.w3schools.com/python/python_operators.asp

Logical operators are used to combine conditional statements.
"""


def test_logical_operators():
    """Logical operators"""

    # Let's work with these number to illustrate logic operators.
    first_number = 5
    second_number = 10

    # and
    # Returns True if both statements are true.
    assert first_number > 0 and second_number < 20

    # or
    # Returns True if one of the statements is true
    assert first_number > 5 or second_number < 20

    # not
    # Reverse the result, returns False if the result is true.
    # pylint: disable=unneeded-not
    assert not first_number == second_number
    assert first_number != second_number


================================================
FILE: src/operators/test_membership.py
================================================
"""Membership operators

@see: https://www.w3schools.com/python/python_operators.asp

Membership operators are used to test if a sequence is presented in an object.
"""


def test_membership_operators():
    """Membership operators"""

    # Let's use the following fruit list to illustrate membership concept.
    fruit_list = ["apple", "banana"]

    # in
    # Returns True if a sequence with the specified value is present in the object.

    # Returns True because a sequence with the value "banana" is in the list
    assert "banana" in fruit_list

    # not in
    # Returns True if a sequence with the specified value is not present in the object

    # Returns True because a sequence with the value "pineapple" is not in the list.
    assert "pineapple" not in fruit_list


================================================
FILE: src/standard_libraries/glob_files/first_file.txt
================================================


================================================
FILE: src/standard_libraries/glob_files/second_file.txt
================================================


================================================
FILE: src/standard_libraries/test_datetime.py
================================================
"""Dates and Times.

@see: https://docs.python.org/3/tutorial/stdlib.html#dates-and-times

The datetime module supplies classes for manipulating dates and times in both simple and complex
ways. While date and time arithmetic is supported, the focus of the implementation is on efficient
member extraction for output formatting and manipulation. The module also supports objects that
are timezone aware.
"""

from datetime import date


def test_datetime():
    """Dates and Times"""

    real_now = date.today()
    assert real_now

    fake_now = date(2018, 8, 29)

    assert fake_now.day == 29
    assert fake_now.month == 8
    assert fake_now.year == 2018
    assert fake_now.ctime() == 'Wed Aug 29 00:00:00 2018'
    assert fake_now.strftime(
        '%m-%d-%y. %d %b %Y is a %A on the %d day of %B.'
    ) == '08-29-18. 29 Aug 2018 is a Wednesday on the 29 day of August.'

    # Dates support calendar arithmetic.
    birthday = date(1964, 7, 31)
    age = fake_now - birthday

    assert age.days == 19752


================================================
FILE: src/standard_libraries/test_glob.py
================================================
"""File Wildcards.

@see: https://docs.python.org/3/tutorial/stdlib.html#file-wildcards

The glob module provides a function for making file lists from directory wildcard searches:
"""

import glob


def test_glob():
    """File Wildcards."""

    # == operator for lists relies on the order of elements in the list.
    # In some cases (like on Linux Mint, python3.6) the glob() function returns list
    # in reverse order then  it might be expected. Thus lets sort both lists before comparison
    # using sorted() built-in function.
    assert sorted(glob.glob('src/standard_libraries/glob_files/*.txt')) == sorted([
        'src/standard_libraries/glob_files/first_file.txt',
        'src/standard_libraries/glob_files/second_file.txt'
    ])


================================================
FILE: src/standard_libraries/test_json.py
================================================
"""Serialization.

@see: https://www.learnpython.org/en/Serialization

Python provides built-in JSON libraries to encode and decode JSON.
"""

import json


def test_json():
    """JSON serialization."""

    # There are two basic formats for JSON data. Either in a string or the object data-structure.
    # The object data-structure, in Python, consists of lists and dictionaries nested inside each
    # other. The object data-structure allows one to use python methods (for lists and dictionaries)
    # to add, list, search and remove elements fr
Download .txt
gitextract_6lyybz2h/

├── .flake8
├── .gitignore
├── .travis.yml
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.es-ES.md
├── README.md
├── README.pt-BR.md
├── README.zh-TW.md
├── _config.yml
├── pylintrc
├── requirements.txt
└── src/
    ├── additions/
    │   ├── test_generators.py
    │   └── test_pass.py
    ├── classes/
    │   ├── test_class_and_instance_variables.py
    │   ├── test_class_definition.py
    │   ├── test_class_objects.py
    │   ├── test_inheritance.py
    │   ├── test_instance_objects.py
    │   ├── test_method_objects.py
    │   └── test_multiple_inheritance.py
    ├── control_flow/
    │   ├── test_break.py
    │   ├── test_continue.py
    │   ├── test_for.py
    │   ├── test_if.py
    │   ├── test_try.py
    │   └── test_while.py
    ├── data_types/
    │   ├── test_dictionaries.py
    │   ├── test_lists.py
    │   ├── test_numbers.py
    │   ├── test_sets.py
    │   ├── test_strings.py
    │   ├── test_tuples.py
    │   └── test_type_casting.py
    ├── exceptions/
    │   ├── test_handle_exceptions.py
    │   └── test_raise_exceptions.py
    ├── files/
    │   ├── binary_file
    │   ├── multi_line_file.txt
    │   ├── test_file_methods.py
    │   └── test_file_reading.py
    ├── functions/
    │   ├── test_function_annotations.py
    │   ├── test_function_arbitrary_arguments.py
    │   ├── test_function_decorators.py
    │   ├── test_function_default_arguments.py
    │   ├── test_function_definition.py
    │   ├── test_function_documentation_string.py
    │   ├── test_function_keyword_arguments.py
    │   ├── test_function_scopes.py
    │   ├── test_function_unpacking_arguments.py
    │   └── test_lambda_expressions.py
    ├── getting_started/
    │   ├── python_syntax.md
    │   ├── test_variables.py
    │   └── what_is_python.md
    ├── modules/
    │   ├── fibonacci_module.py
    │   ├── sound_package/
    │   │   ├── __init__.py
    │   │   ├── effects/
    │   │   │   ├── __init__.py
    │   │   │   ├── echo.py
    │   │   │   └── reverse.py
    │   │   └── formats/
    │   │       ├── __init__.py
    │   │       ├── aif.py
    │   │       └── wav.py
    │   ├── test_modules.py
    │   └── test_packages.py
    ├── operators/
    │   ├── test_arithmetic.py
    │   ├── test_assigment.py
    │   ├── test_bitwise.py
    │   ├── test_comparison.py
    │   ├── test_identity.py
    │   ├── test_logical.py
    │   └── test_membership.py
    ├── standard_libraries/
    │   ├── glob_files/
    │   │   ├── first_file.txt
    │   │   └── second_file.txt
    │   ├── test_datetime.py
    │   ├── test_glob.py
    │   ├── test_json.py
    │   ├── test_math.py
    │   ├── test_re.py
    │   └── test_zlib.py
    └── user_input/
        └── test_input.py
Download .txt
SYMBOL INDEX (96 symbols across 58 files)

FILE: src/additions/test_generators.py
  function lottery (line 17) | def lottery():
  function test_generators (line 33) | def test_generators():

FILE: src/additions/test_pass.py
  function test_pass_in_function (line 10) | def test_pass_in_function():
  function test_pass_in_loop (line 21) | def test_pass_in_loop():
  class MyEmptyClass (line 41) | class MyEmptyClass:

FILE: src/classes/test_class_and_instance_variables.py
  function test_class_and_instance_variables (line 10) | def test_class_and_instance_variables():

FILE: src/classes/test_class_definition.py
  function test_class_definition (line 11) | def test_class_definition():

FILE: src/classes/test_class_objects.py
  function test_class_objects (line 10) | def test_class_objects():

FILE: src/classes/test_inheritance.py
  class Person (line 11) | class Person:
    method __init__ (line 13) | def __init__(self, name):
    method get_name (line 16) | def get_name(self):
  class Employee (line 23) | class Employee(Person):
    method __init__ (line 40) | def __init__(self, name, staff_id):
    method get_full_id (line 46) | def get_full_id(self):
  function test_inheritance (line 51) | def test_inheritance():

FILE: src/classes/test_instance_objects.py
  function test_instance_objects (line 7) | def test_instance_objects():

FILE: src/classes/test_method_objects.py
  class MyCounter (line 10) | class MyCounter:
    method get_counter (line 14) | def get_counter(self):
    method increment_counter (line 18) | def increment_counter(self):
  function test_method_objects (line 24) | def test_method_objects():

FILE: src/classes/test_multiple_inheritance.py
  function test_multiple_inheritance (line 10) | def test_multiple_inheritance():

FILE: src/control_flow/test_break.py
  function test_break_statement (line 9) | def test_break_statement():

FILE: src/control_flow/test_continue.py
  function test_continue_statement (line 9) | def test_continue_statement():

FILE: src/control_flow/test_for.py
  function test_for_statement (line 14) | def test_for_statement():
  function test_range_function (line 109) | def test_range_function():

FILE: src/control_flow/test_if.py
  function test_if_statement (line 13) | def test_if_statement():

FILE: src/control_flow/test_try.py
  function test_try (line 16) | def test_try():

FILE: src/control_flow/test_while.py
  function test_while_statement (line 17) | def test_while_statement():

FILE: src/data_types/test_dictionaries.py
  function test_dictionary (line 24) | def test_dictionary():

FILE: src/data_types/test_lists.py
  function test_list_type (line 17) | def test_list_type():
  function test_list_methods (line 78) | def test_list_methods():
  function test_del_statement (line 173) | def test_del_statement():
  function test_list_comprehensions (line 201) | def test_list_comprehensions():
  function test_nested_list_comprehensions (line 279) | def test_nested_list_comprehensions():

FILE: src/data_types/test_numbers.py
  function test_integer_numbers (line 14) | def test_integer_numbers():
  function test_booleans (line 30) | def test_booleans():
  function test_float_numbers (line 54) | def test_float_numbers():
  function test_complex_numbers (line 82) | def test_complex_numbers():
  function test_number_operators (line 93) | def test_number_operators():

FILE: src/data_types/test_sets.py
  function test_sets (line 14) | def test_sets():
  function test_set_methods (line 27) | def test_set_methods():

FILE: src/data_types/test_strings.py
  function test_string_type (line 15) | def test_string_type():
  function test_string_operators (line 121) | def test_string_operators():
  function test_string_methods (line 146) | def test_string_methods():
  function test_string_formatting (line 202) | def test_string_formatting():

FILE: src/data_types/test_tuples.py
  function test_tuples (line 17) | def test_tuples():

FILE: src/data_types/test_type_casting.py
  function test_type_casting_to_integer (line 23) | def test_type_casting_to_integer():
  function test_type_casting_to_float (line 31) | def test_type_casting_to_float():
  function test_type_casting_to_string (line 40) | def test_type_casting_to_string():

FILE: src/exceptions/test_handle_exceptions.py
  function test_handle_exceptions (line 13) | def test_handle_exceptions():

FILE: src/exceptions/test_raise_exceptions.py
  function test_raise_exception (line 9) | def test_raise_exception():
  function test_user_defined_exception (line 28) | def test_user_defined_exception():

FILE: src/files/test_file_methods.py
  function test_file_methods (line 10) | def test_file_methods():

FILE: src/files/test_file_reading.py
  function test_files_open (line 11) | def test_files_open():

FILE: src/functions/test_function_annotations.py
  function breakfast (line 16) | def breakfast(ham: str, eggs: str = 'eggs') -> str:
  function test_function_annotations (line 24) | def test_function_annotations():

FILE: src/functions/test_function_arbitrary_arguments.py
  function test_function_arbitrary_arguments (line 10) | def test_function_arbitrary_arguments():

FILE: src/functions/test_function_decorators.py
  function test_function_decorators (line 13) | def test_function_decorators():

FILE: src/functions/test_function_default_arguments.py
  function power_of (line 10) | def power_of(number, power=2):
  function test_default_function_arguments (line 18) | def test_default_function_arguments():

FILE: src/functions/test_function_definition.py
  function fibonacci_function_example (line 12) | def fibonacci_function_example(number_limit):
  function test_function_definition (line 50) | def test_function_definition():

FILE: src/functions/test_function_documentation_string.py
  function do_nothing (line 18) | def do_nothing():
  function test_function_documentation_string (line 26) | def test_function_documentation_string():

FILE: src/functions/test_function_keyword_arguments.py
  function parrot (line 11) | def parrot(voltage, state='a stiff', action='voom', parrot_type='Norwegi...
  function test_function_keyword_arguments (line 26) | def test_function_keyword_arguments():

FILE: src/functions/test_function_scopes.py
  function test_function_scopes (line 43) | def test_function_scopes():
  function test_global_variable_access (line 93) | def test_global_variable_access():

FILE: src/functions/test_function_unpacking_arguments.py
  function test_function_unpacking_arguments (line 9) | def test_function_unpacking_arguments():

FILE: src/functions/test_lambda_expressions.py
  function test_lambda_expressions (line 12) | def test_lambda_expressions():

FILE: src/getting_started/test_variables.py
  function test_variables (line 26) | def test_variables():

FILE: src/modules/fibonacci_module.py
  function fibonacci_at_position (line 11) | def fibonacci_at_position(position):
  function fibonacci_smaller_than (line 21) | def fibonacci_smaller_than(limit):

FILE: src/modules/sound_package/effects/echo.py
  function echo_function (line 4) | def echo_function():

FILE: src/modules/sound_package/effects/reverse.py
  function reverse_function (line 4) | def reverse_function():

FILE: src/modules/sound_package/formats/aif.py
  function aif_read (line 4) | def aif_read():

FILE: src/modules/sound_package/formats/wav.py
  function wav_read (line 4) | def wav_read():

FILE: src/modules/test_modules.py
  function test_modules (line 68) | def test_modules():

FILE: src/modules/test_packages.py
  function test_packages (line 57) | def test_packages():

FILE: src/operators/test_arithmetic.py
  function test_arithmetic_operators (line 9) | def test_arithmetic_operators():

FILE: src/operators/test_assigment.py
  function test_assignment_operator (line 9) | def test_assignment_operator():
  function test_augmented_assignment_operators (line 28) | def test_augmented_assignment_operators():

FILE: src/operators/test_bitwise.py
  function test_bitwise_operators (line 9) | def test_bitwise_operators():

FILE: src/operators/test_comparison.py
  function test_comparison_operators (line 9) | def test_comparison_operators():

FILE: src/operators/test_identity.py
  function test_identity_operators (line 10) | def test_identity_operators():

FILE: src/operators/test_logical.py
  function test_logical_operators (line 9) | def test_logical_operators():

FILE: src/operators/test_membership.py
  function test_membership_operators (line 9) | def test_membership_operators():

FILE: src/standard_libraries/test_datetime.py
  function test_datetime (line 14) | def test_datetime():

FILE: src/standard_libraries/test_glob.py
  function test_glob (line 11) | def test_glob():

FILE: src/standard_libraries/test_json.py
  function test_json (line 11) | def test_json():

FILE: src/standard_libraries/test_math.py
  function test_math (line 13) | def test_math():
  function test_random (line 22) | def test_random():
  function test_statistics (line 47) | def test_statistics():

FILE: src/standard_libraries/test_re.py
  function test_re (line 12) | def test_re():

FILE: src/standard_libraries/test_zlib.py
  function test_zlib (line 12) | def test_zlib():

FILE: src/user_input/test_input.py
  function user_input (line 10) | def user_input():
Condensed preview — 79 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (206K chars).
[
  {
    "path": ".flake8",
    "chars": 31,
    "preview": "[flake8]\nmax-line-length = 100\n"
  },
  {
    "path": ".gitignore",
    "chars": 58,
    "preview": ".idea\n.pytest_cache\nvenv\n**/*.pyc\nenv\n__pycache__\n.vscode\n"
  },
  {
    "path": ".travis.yml",
    "chars": 268,
    "preview": "language: python\npython:\n  - \"3.6\"\n\n# Install dependencies.\ninstall:\n  - pip install -r requirements.txt\n\n# Run linting "
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "chars": 1987,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
  },
  {
    "path": "LICENSE",
    "chars": 1073,
    "preview": "MIT License\n\nCopyright (c) 2018 Oleksii Trekhleb\n\nPermission is hereby granted, free of charge, to any person obtaining "
  },
  {
    "path": "README.es-ES.md",
    "chars": 9829,
    "preview": "# Playground y Cheatsheet para aprender Python\n\n[![Build Status](https://travis-ci.org/trekhleb/learn-python.svg?branch="
  },
  {
    "path": "README.md",
    "chars": 10079,
    "preview": "# Playground and Cheatsheet for Learning Python\n\n> 🇺🇦 UKRAINE [IS BEING ATTACKED](https://war.ukraine.ua/) BY RUSSIAN AR"
  },
  {
    "path": "README.pt-BR.md",
    "chars": 9458,
    "preview": "# Playground e Cheatsheet Para Aprender Python\n\n[![Build Status](https://travis-ci.org/trekhleb/learn-python.svg?branch="
  },
  {
    "path": "README.zh-TW.md",
    "chars": 6526,
    "preview": "# 學習 Python 的練習場(Playground)和速查表(Cheatsheet)\n\n[![Build Status](https://travis-ci.org/trekhleb/learn-python.svg?branch=ma"
  },
  {
    "path": "_config.yml",
    "chars": 27,
    "preview": "theme: jekyll-theme-minimal"
  },
  {
    "path": "pylintrc",
    "chars": 17238,
    "preview": "[MASTER]\n\n# A comma-separated list of package or module names from where C extensions may\n# be loaded. Extensions are lo"
  },
  {
    "path": "requirements.txt",
    "chars": 251,
    "preview": "astroid==2.0.4\natomicwrites==1.1.5\nattrs==18.1.0\nflake8==3.5.0\nisort==4.3.4\nlazy-object-proxy==1.3.1\nmccabe==0.6.1\nmore-"
  },
  {
    "path": "src/additions/test_generators.py",
    "chars": 1434,
    "preview": "\"\"\"Generators.\n\n@see: https://www.learnpython.org/en/Generators\n\nGenerators are used to create iterators, but with a dif"
  },
  {
    "path": "src/additions/test_pass.py",
    "chars": 1284,
    "preview": "\"\"\"PASS statement\n\n@see: https://docs.python.org/3/tutorial/controlflow.html\n\nThe pass statement does nothing. It can be"
  },
  {
    "path": "src/classes/test_class_and_instance_variables.py",
    "chars": 2871,
    "preview": "\"\"\"Class and Instance Variables.\n\n@see: https://docs.python.org/3/tutorial/classes.html#class-and-instance-variables\n\nGe"
  },
  {
    "path": "src/classes/test_class_definition.py",
    "chars": 1941,
    "preview": "\"\"\"Class Definition Syntax.\n\n@see: https://docs.python.org/3/tutorial/classes.html\n\nPython is an object oriented program"
  },
  {
    "path": "src/classes/test_class_objects.py",
    "chars": 2806,
    "preview": "\"\"\"Class Definition Syntax.\n\n@see: https://docs.python.org/3/tutorial/classes.html#class-objects\n\nAfter defining the cla"
  },
  {
    "path": "src/classes/test_inheritance.py",
    "chars": 3263,
    "preview": "\"\"\"Inheritance\n\n@see: https://docs.python.org/3/tutorial/classes.html#inheritance\n\nInheritance is one of the principles "
  },
  {
    "path": "src/classes/test_instance_objects.py",
    "chars": 991,
    "preview": "\"\"\"Class Definition Syntax.\n\n@see: https://docs.python.org/3/tutorial/classes.html#instance-objects\n\"\"\"\n\n\ndef test_insta"
  },
  {
    "path": "src/classes/test_method_objects.py",
    "chars": 2676,
    "preview": "\"\"\"Class Definition Syntax.\n\n@see: https://docs.python.org/3/tutorial/classes.html#method-objects\n\nClasses can have two "
  },
  {
    "path": "src/classes/test_multiple_inheritance.py",
    "chars": 2901,
    "preview": "\"\"\"Multiple Inheritance\n\n@see: https://docs.python.org/3/tutorial/classes.html#multiple-inheritance\n\nSome classes may de"
  },
  {
    "path": "src/control_flow/test_break.py",
    "chars": 798,
    "preview": "\"\"\"BREAK statement\n\n@see: https://docs.python.org/3/tutorial/controlflow.html\n\nThe break statement, like in C, breaks ou"
  },
  {
    "path": "src/control_flow/test_continue.py",
    "chars": 879,
    "preview": "\"\"\"CONTINUE statement\n\n@see: https://docs.python.org/3/tutorial/controlflow.html\n\nThe continue statement is borrowed fro"
  },
  {
    "path": "src/control_flow/test_for.py",
    "chars": 5175,
    "preview": "\"\"\"FOR statement\n\n@see: https://docs.python.org/3/tutorial/controlflow.html\n\nThe for statement in Python differs a bit f"
  },
  {
    "path": "src/control_flow/test_if.py",
    "chars": 789,
    "preview": "\"\"\"IF statement\n\n@see: https://docs.python.org/3/tutorial/controlflow.html\n\nThere can be zero or more elif parts, and th"
  },
  {
    "path": "src/control_flow/test_try.py",
    "chars": 2117,
    "preview": "\"\"\"TRY statement\n\n@see: https://www.w3schools.com/python/python_try_except.asp\n\n\"try\" statement is used for exception ha"
  },
  {
    "path": "src/control_flow/test_while.py",
    "chars": 960,
    "preview": "\"\"\"WHILE statement\n\n@see: https://docs.python.org/3/tutorial/controlflow.html\n@see: https://docs.python.org/3/reference/"
  },
  {
    "path": "src/data_types/test_dictionaries.py",
    "chars": 3592,
    "preview": "\"\"\"Dictionaries.\n\n@see: https://docs.python.org/3/tutorial/datastructures.html#dictionaries\n@see: https://www.w3schools."
  },
  {
    "path": "src/data_types/test_lists.py",
    "chars": 12297,
    "preview": "\"\"\"Lists.\n\n# @see: https://www.learnpython.org/en/Lists\n# @see: https://docs.python.org/3/tutorial/introduction.html\n# @"
  },
  {
    "path": "src/data_types/test_numbers.py",
    "chars": 3326,
    "preview": "\"\"\"Numbers.\n\n@see: https://docs.python.org/3/tutorial/introduction.html\n@see: https://www.w3schools.com/python/python_nu"
  },
  {
    "path": "src/data_types/test_sets.py",
    "chars": 2326,
    "preview": "\"\"\"Sets.\n\n@see: https://www.w3schools.com/python/python_sets.asp\n@see: https://docs.python.org/3.7/tutorial/datastructur"
  },
  {
    "path": "src/data_types/test_strings.py",
    "chars": 12747,
    "preview": "\"\"\"Strings.\n\n@see: https://docs.python.org/3/tutorial/introduction.html\n@see: https://www.w3schools.com/python/python_st"
  },
  {
    "path": "src/data_types/test_tuples.py",
    "chars": 3648,
    "preview": "\"\"\"Tuples.\n\n@see: https://www.w3schools.com/python/python_tuples.asp\n@see: https://docs.python.org/3/tutorial/datastruct"
  },
  {
    "path": "src/data_types/test_type_casting.py",
    "chars": 1338,
    "preview": "\"\"\"Type casting.\n\n@see: https://www.w3schools.com/python/python_casting.asp\n\nThere may be times when you want to specify"
  },
  {
    "path": "src/exceptions/test_handle_exceptions.py",
    "chars": 3893,
    "preview": "\"\"\"Errors and Exceptions.\n\n@see: https://docs.python.org/3/tutorial/errors.html#errors-and-exceptions\n\nEven if a stateme"
  },
  {
    "path": "src/exceptions/test_raise_exceptions.py",
    "chars": 1754,
    "preview": "\"\"\"Raising Exceptions.\n\n@see: https://docs.python.org/3/tutorial/errors.html#raising-exceptions\n\nThe raise statement all"
  },
  {
    "path": "src/files/binary_file",
    "chars": 16,
    "preview": "0123456789abcdef"
  },
  {
    "path": "src/files/multi_line_file.txt",
    "chars": 33,
    "preview": "first line\nsecond line\nthird line"
  },
  {
    "path": "src/files/test_file_methods.py",
    "chars": 2511,
    "preview": "\"\"\"Methods of File Objects\n\n@see: https://docs.python.org/3/tutorial/inputoutput.html#methods-of-file-objects\n\nReading f"
  },
  {
    "path": "src/files/test_file_reading.py",
    "chars": 3226,
    "preview": "\"\"\"Reading and Writing Files\n\n@see: https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files\n\nThe p"
  },
  {
    "path": "src/functions/test_function_annotations.py",
    "chars": 1029,
    "preview": "\"\"\"Function Annotations.\n\n@see: https://docs.python.org/3/tutorial/controlflow.html#function-annotations\n\nFunction annot"
  },
  {
    "path": "src/functions/test_function_arbitrary_arguments.py",
    "chars": 1688,
    "preview": "\"\"\"Arbitrary Argument Lists\n\n@see: https://docs.python.org/3/tutorial/controlflow.html#arbitrary-argument-lists\n\nFunctio"
  },
  {
    "path": "src/functions/test_function_decorators.py",
    "chars": 3938,
    "preview": "\"\"\"Function Decorators.\n\n@see: https://www.thecodeship.com/patterns/guide-to-python-function-decorators/\n\nFunction decor"
  },
  {
    "path": "src/functions/test_function_default_arguments.py",
    "chars": 925,
    "preview": "\"\"\"Default Argument Values\n\n@see: https://docs.python.org/3/tutorial/controlflow.html#default-argument-values\n\nThe most "
  },
  {
    "path": "src/functions/test_function_definition.py",
    "chars": 5446,
    "preview": "\"\"\"Function Definition\n\n@see: https://docs.python.org/3/tutorial/controlflow.html#defining-functions\n@see: https://www.t"
  },
  {
    "path": "src/functions/test_function_documentation_string.py",
    "chars": 1977,
    "preview": "\"\"\"Documentation Strings.\n\n@see: https://docs.python.org/3/tutorial/controlflow.html#documentation-strings\n\nHere are som"
  },
  {
    "path": "src/functions/test_function_keyword_arguments.py",
    "chars": 4463,
    "preview": "\"\"\"Keyword Arguments\n\n@see: https://docs.python.org/3/tutorial/controlflow.html#keyword-arguments\n\nFunctions can be call"
  },
  {
    "path": "src/functions/test_function_scopes.py",
    "chars": 5126,
    "preview": "\"\"\"Scopes and Namespaces.\n\n@see: https://docs.python.org/3/tutorial/classes.html#scopes-and-namespaces-example\n\nA NAMESP"
  },
  {
    "path": "src/functions/test_function_unpacking_arguments.py",
    "chars": 1297,
    "preview": "\"\"\"Unpacking Argument Lists\n\n@see: https://docs.python.org/3/tutorial/controlflow.html#unpacking-argument-lists\n\nUnpacki"
  },
  {
    "path": "src/functions/test_lambda_expressions.py",
    "chars": 1342,
    "preview": "\"\"\"Lambda Expressions\n\n@see: https://docs.python.org/3/tutorial/controlflow.html#lambda-expressions\n\nSmall anonymous fun"
  },
  {
    "path": "src/getting_started/python_syntax.md",
    "chars": 1478,
    "preview": "# Python Syntax\n\n**Python Syntax compared to other programming languages**\n\n- Python was designed to for readability, an"
  },
  {
    "path": "src/getting_started/test_variables.py",
    "chars": 1310,
    "preview": "\"\"\"Variables\n\n@see: https://docs.python.org/3/tutorial/introduction.html\n@see: https://www.w3schools.com/python/python_v"
  },
  {
    "path": "src/getting_started/what_is_python.md",
    "chars": 2046,
    "preview": "# What is Python\n\nPython is a popular programming language. It was created in 1991 by Guido van Rossum.\n\nPython is an ea"
  },
  {
    "path": "src/modules/fibonacci_module.py",
    "chars": 1562,
    "preview": "\"\"\"Fibonacci numbers module.\n\n@see: https://docs.python.org/3/tutorial/modules.html\n\nA module is a file containing Pytho"
  },
  {
    "path": "src/modules/sound_package/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/modules/sound_package/effects/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/modules/sound_package/effects/echo.py",
    "chars": 99,
    "preview": "\"\"\"Echo effect.\"\"\"\n\n\ndef echo_function():\n    \"\"\"Echo function mock\"\"\"\n    return 'Do echo effect'\n"
  },
  {
    "path": "src/modules/sound_package/effects/reverse.py",
    "chars": 111,
    "preview": "\"\"\"Reverse effect.\"\"\"\n\n\ndef reverse_function():\n    \"\"\"Reveres function mock\"\"\"\n    return 'Do reverse effect'\n"
  },
  {
    "path": "src/modules/sound_package/formats/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/modules/sound_package/formats/aif.py",
    "chars": 115,
    "preview": "\"\"\"AIF file support.\"\"\"\n\n\ndef aif_read():\n    \"\"\"AIF file reading function mock\"\"\"\n    return 'Read from AIF file'\n"
  },
  {
    "path": "src/modules/sound_package/formats/wav.py",
    "chars": 115,
    "preview": "\"\"\"WAV file support.\"\"\"\n\n\ndef wav_read():\n    \"\"\"WAV file reading function mock\"\"\"\n    return 'Read from WAV file'\n"
  },
  {
    "path": "src/modules/test_modules.py",
    "chars": 4425,
    "preview": "\"\"\"Modules.\n\n@see: https://docs.python.org/3/tutorial/modules.html\n\nAs your program gets longer, you may want to split i"
  },
  {
    "path": "src/modules/test_packages.py",
    "chars": 2931,
    "preview": "\"\"\"Packages.\n\n@see: https://docs.python.org/3/tutorial/modules.html#packages\n\nPackages are a way of structuring Python’s"
  },
  {
    "path": "src/operators/test_arithmetic.py",
    "chars": 943,
    "preview": "\"\"\"Arithmetic operators\n\n@see: https://www.w3schools.com/python/python_operators.asp\n\nArithmetic operators are used with"
  },
  {
    "path": "src/operators/test_assigment.py",
    "chars": 1964,
    "preview": "\"\"\"Assignment operators\n\n@see: https://www.w3schools.com/python/python_operators.asp\n\nAssignment operators are used to a"
  },
  {
    "path": "src/operators/test_bitwise.py",
    "chars": 1221,
    "preview": "\"\"\"Bitwise operators\n\n@see: https://www.w3schools.com/python/python_operators.asp\n\nBitwise operators manipulate numbers "
  },
  {
    "path": "src/operators/test_comparison.py",
    "chars": 613,
    "preview": "\"\"\"Comparison operators\n\n@see: https://www.w3schools.com/python/python_operators.asp\n\nComparison operators are used to c"
  },
  {
    "path": "src/operators/test_identity.py",
    "chars": 1169,
    "preview": "\"\"\"Identity operators\n\n@see: https://www.w3schools.com/python/python_operators.asp\n\nIdentity operators are used to compa"
  },
  {
    "path": "src/operators/test_logical.py",
    "chars": 737,
    "preview": "\"\"\"Logical operators\n\n@see: https://www.w3schools.com/python/python_operators.asp\n\nLogical operators are used to combine"
  },
  {
    "path": "src/operators/test_membership.py",
    "chars": 782,
    "preview": "\"\"\"Membership operators\n\n@see: https://www.w3schools.com/python/python_operators.asp\n\nMembership operators are used to t"
  },
  {
    "path": "src/standard_libraries/glob_files/first_file.txt",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/standard_libraries/glob_files/second_file.txt",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "src/standard_libraries/test_datetime.py",
    "chars": 1015,
    "preview": "\"\"\"Dates and Times.\n\n@see: https://docs.python.org/3/tutorial/stdlib.html#dates-and-times\n\nThe datetime module supplies "
  },
  {
    "path": "src/standard_libraries/test_glob.py",
    "chars": 748,
    "preview": "\"\"\"File Wildcards.\n\n@see: https://docs.python.org/3/tutorial/stdlib.html#file-wildcards\n\nThe glob module provides a func"
  },
  {
    "path": "src/standard_libraries/test_json.py",
    "chars": 1545,
    "preview": "\"\"\"Serialization.\n\n@see: https://www.learnpython.org/en/Serialization\n\nPython provides built-in JSON libraries to encode"
  },
  {
    "path": "src/standard_libraries/test_math.py",
    "chars": 1590,
    "preview": "\"\"\"Math.\n\n@see: https://docs.python.org/3/tutorial/stdlib.html#mathematics\n\nMath module is useful as many math functions"
  },
  {
    "path": "src/standard_libraries/test_re.py",
    "chars": 759,
    "preview": "\"\"\"String Pattern Matching.\n\n@see: https://docs.python.org/3/tutorial/stdlib.html#string-pattern-matching\n\nThe re module"
  },
  {
    "path": "src/standard_libraries/test_zlib.py",
    "chars": 664,
    "preview": "\"\"\"Data Compression.\n\n@see: https://docs.python.org/3/tutorial/stdlib.html#data-compression\n\nCommon data archiving and c"
  },
  {
    "path": "src/user_input/test_input.py",
    "chars": 583,
    "preview": "\"\"\"User input\n\n@see https://docs.python.org/3/library/functions.html#input\n\nUser input prompts are very helpful when it "
  }
]

About this extraction

This page contains the full source code of the trekhleb/learn-python GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 79 files (189.6 KB), approximately 50.2k tokens, and a symbol index with 96 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!