Metadata-Version: 2.4
Name: hypothesis_sqlalchemy
Version: 1.2.0
Summary: ``hypothesis`` strategies for ``SQLAlchemy`` objects.
Home-page: https://github.com/lycantropos/hypothesis_sqlalchemy/
Download-URL: https://github.com/lycantropos/hypothesis_sqlalchemy/archive/master.zip
Author-email: Azat Ibrakov <azatibrakov@gmail.com>
License: MIT License
        
        Copyright (c) 2017 Ibrakov Azat
        
        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.
        
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: hypothesis<7.0,>=6.66.0
Requires-Dist: sqlalchemy<3.0,>=1.4.46
Provides-Extra: docs
Requires-Dist: Sphinx<9.0,>=7.2.6; extra == "docs"
Requires-Dist: sphinx-rtd-theme<3.0,>=2.0.0; extra == "docs"
Provides-Extra: tests
Requires-Dist: pytest<10.0,>=9.0.1; extra == "tests"
Dynamic: download-url
Dynamic: home-page
Dynamic: license-file

# hypothesis_sqlalchemy

[![Github Actions](https://github.com/lycantropos/hypothesis_sqlalchemy/workflows/CI/badge.svg)](https://github.com/lycantropos/hypothesis_sqlalchemy/actions/workflows/ci.yml "Github Actions")
[![Codecov](https://codecov.io/gh/lycantropos/hypothesis_sqlalchemy/branch/master/graph/badge.svg)](https://codecov.io/gh/lycantropos/hypothesis_sqlalchemy "Codecov")
[![License](https://img.shields.io/github/license/lycantropos/hypothesis_sqlalchemy.svg)](https://github.com/lycantropos/hypothesis_sqlalchemy/blob/master/LICENSE "License")
[![PyPI](https://badge.fury.io/py/hypothesis-sqlalchemy.svg)](https://badge.fury.io/py/hypothesis-sqlalchemy "PyPI")

In what follows `python` is an alias for `python3.10` or `pypy3.10`
or any later version (`python3.11`, `pypy3.11` and so on).

## Installation

### Prerequisites

Install the latest `pip` & `setuptools` packages versions

```bash
python -m pip install --upgrade pip setuptools
```

### User

Download and install the latest stable version from `PyPI` repository

```bash
python -m pip install --upgrade hypothesis_sqlalchemy
```

### Developer

Download the latest version from `GitHub` repository

```bash
git clone https://github.com/lycantropos/hypothesis_sqlalchemy.git
cd hypothesis_sqlalchemy
```

Install

```bash
python -m pip install -e '.'
```

## Usage

With setup

```python
>>> import warnings
>>> from hypothesis.errors import NonInteractiveExampleWarning
>>> # ignore hypothesis warnings caused by `example` method call
... warnings.filterwarnings('ignore', category=NonInteractiveExampleWarning)

```

let's take a look at what can be generated and how.

### Tables

We can write a strategy that produces tables

```python
>>> from hypothesis_sqlalchemy import scheme
>>> from sqlalchemy.engine.default import DefaultDialect
>>> dialect = DefaultDialect()
>>> tables = scheme.tables(dialect,
...                        min_size=3,
...                        max_size=10)
>>> table = tables.example()
>>> from sqlalchemy.schema import Table
>>> isinstance(table, Table)
True
>>> from sqlalchemy.schema import Column
>>> all(isinstance(column, Column) for column in table.columns)
True
>>> 3 <= len(table.columns) <= 10
True

```

### Records

Suppose we have a table

```python
>>> from sqlalchemy.schema import (Column,
...                                MetaData,
...                                Table)
>>> from sqlalchemy.sql.sqltypes import (Integer,
...                                      String)
>>> metadata = MetaData()
>>> user_table = Table('user', metadata,
...                    Column('user_id', Integer,
...                           primary_key=True),
...                    Column('user_name', String(16),
...                           nullable=False),
...                    Column('email_address', String(60)),
...                    Column('password', String(20),
...                           nullable=False))

```

and we can write strategy that

* produces single records (as `tuple`s)

    ```python
    >>> from hypothesis import strategies
    >>> from hypothesis_sqlalchemy.sample import table_records
    >>> records = table_records(user_table,
    ...                         email_address=strategies.emails())
    >>> record = records.example()
    >>> isinstance(record, tuple)
    True
    >>> len(record) == len(user_table.columns)
    True
    >>> all(column.nullable and value is None
    ...     or isinstance(value, column.type.python_type)
    ...     for value, column in zip(record, user_table.columns))
    True

    ```

* produces records `list`s (with configurable `list` size bounds)

    ```python
    >>> from hypothesis_sqlalchemy.sample import table_records_lists
    >>> records_lists = table_records_lists(user_table,
    ...                                     min_size=2,
    ...                                     max_size=5,
    ...                                     email_address=strategies.emails())
    >>> records_list = records_lists.example()
    >>> isinstance(records_list, list)
    True
    >>> 2 <= len(records_list) <= 5
    True
    >>> all(isinstance(record, tuple) for record in records_list)
    True
    >>> all(len(record) == len(user_table.columns) for record in records_list)
    True

    ```

## Development

### Bumping version

#### Prerequisites

Install [bump-my-version](https://github.com/callowayproject/bump-my-version#installation).

#### Release

Choose which version number category to bump following [semver
specification](http://semver.org/).

Test bumping version

```bash
bump-my-version bump --dry-run --verbose $CATEGORY
```

where `$CATEGORY` is the target version number category name, possible
values are `patch`/`minor`/`major`.

Bump version

```bash
bump-my-version bump --verbose $CATEGORY
```

This will set version to `major.minor.patch`.

### Running tests

#### Plain

Install with dependencies

```bash
python -m pip install -e '.[tests]'
```

Run

```bash
pytest
```

#### `Docker` container

Run

* with `CPython`

  ```bash
  docker-compose --file docker-compose.cpython.yml up
  ```

* with `PyPy`

  ```bash
  docker-compose --file docker-compose.pypy.yml up
  ```

#### `Bash` script

Run

* with `CPython`

  ```bash
  ./run-tests.sh
  ```

  or

  ```bash
  ./run-tests.sh cpython
  ```

* with `PyPy`

  ```bash
  ./run-tests.sh pypy
  ```

#### `PowerShell` script

Run

* with `CPython`

  ```powershell
  .\run-tests.ps1
  ```

  or

  ```powershell
  .\run-tests.ps1 cpython
  ```

* with `PyPy`

  ```powershell
  .\run-tests.ps1 pypy
  ```
