Metadata-Version: 2.3
Name: prettyisbns
Version: 0.1.0
Summary: Normalize, fix, and format ISBNs
Keywords: isbn
Author: Maxim Stolyarchuk
Author-email: Maxim Stolyarchuk <maxim.stolyarchuk@gmail.com>
License: MIT License
         
         Copyright (c) 2026 Maxim Stolyarchuk
         
         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: Development Status :: 3 - Alpha
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3.12
Requires-Dist: sphinx>=9.0.4 ; extra == 'docs'
Requires-Dist: sphinx-mdinclude>=0.6.2 ; extra == 'docs'
Requires-Dist: defusedxml>=0.7.1 ; extra == 'ranges'
Requires-Python: >=3.12
Project-URL: Documentation, https://prettyisbns.readthedocs.io/en/stable
Project-URL: GitHub, https://github.com/xymaxim/prettyisbns
Provides-Extra: docs
Provides-Extra: ranges
Description-Content-Type: text/markdown

# prettyisbns

[![Tests](https://github.com/xymaxim/prettyisbns/actions/workflows/ci.yml/badge.svg)](https://github.com/xymaxim/prettyisbns/actions/workflows/ci.yml)

A Python package for normalizing, fixing, and formatting ISBNs to make them pretty.

## Installation

The package is available on PyPI:

```bash
pip install prettyisbns
```

## Usage

### Normalize and fix ISBNs

Normalize an ISBN and fix its check digit:

```pycon
>>> from prettyisbns import normalize
>>> canonical = normalize("23-6590-117-X", fix=True)
>>> canonical
CanonicalISBN(9782365901178)
```

The result is a canonical, normalized ISBN-13 string without hyphens.

### Format ISBNs

Format a canonical ISBN with hyphens to split it into elements:

```pycon
>>> canonical.hyphenate()
'978-2-36590-117-8'
```

To normalize, fix, and format in one step, use the `pretty()` shortcut:

```pycon
>>> from prettyisbns import pretty
>>> pretty("23-6590-117-X")
'978-2-36590-117-8'
```

Formatting relies on the registration groups and registrant ranges from the
[International ISBN Agency](https://www.isbn-international.org/), which are
stored in the auto-generated
[prettyisbns.ranges](https://github.com/xymaxim/prettyisbns/blob/main/src/prettyisbns/ranges.py)
module. Ranges can be redefined, which may cause a discrepancy with the
module. In that case, update the package or open an issue.

### Access ISBN elements

Internally, formatting is done by `ISBNLayout`, which splits an ISBN into
bookland, registration group, registrant, publication, and check digit
elements. You can access it through the `layout` property, which supports
slicing for a granular output:

```pycon
# Split the canonical ISBN into its elements
>>> canonical.layout
ISBNLayout(
    bookland='978',
    group='2',
    registrant='36590',
    publication='117',
    check_digit='8',
)

# Get the group prefix
>>> canonical.layout[:2]
'978-2'

# Get the registrant prefix
>>> canonical.layout[:3]
'978-2-36590'
```

### Validate ISBNs

Check an ISBN's check digit, registration group, and registrant range with
`validate()`. It returns a `ValidationResult`, which is truthy only when the
ISBN is valid:

```python
if result := canonical.validate():
    print("valid")
else:
    print(f"invalid: {result.errors}")
```

### Handle errors

Normalizing raises `NotISBNError` if a value is neither ISBN-10 nor ISBN-13,
and formatting raises `InvalidISBNError` if the registration group or
registrant range of an ISBN is not defined. Its `reason` attribute tells what
exactly is wrong:

```python
from prettyisbns import pretty
from prettyisbns.errors import InvalidISBNError, NotISBNError

try:
    prettied = pretty(value)
except NotISBNError:
    # The value is neither ISBN-10 nor ISBN-13
    ...
except InvalidISBNError as error:
    # The ISBN cannot be formatted, see error.reason
    ...
```

## API

See the full [API](https://prettyisbns.readthedocs.io/en/latest/api/index.html)
reference in the documentation.


## License

MIT.
