Metadata-Version: 2.1
Name: pyarcjon
Version: 0.0.1
Summary: DSL de validation de données et de formulaires pour Python.
Home-page: https://github.com/inicode/pyarc-utilities
Author: INICODE
Author-email: contact.inicode@gmail.com
License: MIT
Keywords: python,jon,schema,validation,forms,inicode,pyarcjon
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Utilities
Description-Content-Type: text/markdown
Requires-Dist: pytz (>=2022.1)
Requires-Dist: pyarcscripts

# pyarcjon

**DSL de validation de données et de formulaires** pour Python.

`pyarcjon` propose une API fluide (chaînage de méthodes) pour construire des
schémas de validation, valider des valeurs, et récupérer une valeur nettoyée
ou une erreur. Il supporte les chaînes, nombres, booléens, dates, objets,
tableaux, énumérations et types conditionnels.

Conçu et maintenu par **INICODE**.

---

## Table des matières

1. [Installation](#installation)
2. [Démarrage rapide](#démarrage-rapide)
3. [Types de validation](#types-de-validation)
4. [API commune à tous les schémas](#api-commune-à-tous-les-schémas)
5. [Exemples par type](#exemples-par-type)
6. [Règles personnalisées](#règles-personnalisées)
7. [Résultat de validation](#résultat-de-validation)
8. [Architecture](#architecture)
9. [Auteur](#auteur)

---

## Installation

```bash
pip install pyarcjon
```

### Installation en mode développeur

```bash
git clone https://github.com/inicode/pyarc-utilities.git
cd pyarc-utilities
python cmd.py --build --only pyarcjon
pip install dist/pyarcjon-*.whl
```

---

## Démarrage rapide

```python
import pyarcjon as JON

# Chaîne requise, format email
schema = JON.String('fr').label('email').required().email()
res = schema.validate('test@example.com')
print(res['valid'])   # True
print(res['data'])    # 'test@example.com'

# Nombre contraint
schema = JON.Number('fr').label('age').required().min(18).max(120)
res = schema.validate(25)
print(res['valid'])   # True
```

---

## Types de validation

| Classe | Description |
|--------|-------------|
| `String` | Chaînes de caractères. |
| `Number` | Nombres entiers / décimaux. |
| `Boolean` | Booléens. |
| `Date` | Dates / datetimes. |
| `Object` | Objets / dictionnaires structurés. |
| `Array` | Listes / tableaux typés. |
| `Enum` | Valeur parmi un ensemble. |
| `NotEnum` | Valeur exclue d'un ensemble. |
| `ChosenType` | Union de plusieurs schémas. |
| `AnyType` | Accepte toute valeur. |

---

## API commune à tous les schémas

```python
schema.validate(value)   # -> {'valid': bool, 'data': any, 'error': any}
schema.isValid(value)    # -> bool
schema.error(value)      # -> erreur
schema.sanitize(value)   # -> valeur nettoyée

# Configuration
schema.label('nom')
schema.default(valeur)
schema.lang('fr' | 'en')
schema.required()
schema.enum(*choix)
schema.enumNot(*choix)
schema.defaultError('msg' | {'fr': ..., 'en': ...})

# Mapping / règles personnalisées
schema.applyApp(rule=fn, sanitize=fn, exception=...)
schema.applyMapping(fn)
schema.applyPreMapping(fn)
schema.initMapError(fn)
```

---

## Exemples par type

### `String`

```python
import pyarcjon as JON

# Chaîne simple
schema = JON.String('fr').label('nom').required().min(2).max(50)
res = schema.validate("Alice")

# Email
email = JON.String('fr').label('email').required().email()
print(email.validate("alice@example.com")['valid'])  # True

# Regex
code = JON.String('fr').label('code').required().regexp(r'^[A-Z]{3}-\d{4}$')
print(code.validate("ABC-1234")['valid'])  # True

# Formats spéciaux
url = JON.String('fr').url()
ip = JON.String('fr').IPAddress('v4')
guid = JON.String('fr').guid()
hexa = JON.String('fr').hexa()
card = JON.String('fr').creditCard()
```

Options de `String` : `min`, `max`, `less`, `greater`, `length`, `regexp`,
`alphanum`, `base64`, `lowercase`, `uppercase`, `capitalize`, `ucFirst`,
`creditCard`, `dataUri`, `domain`, `url`, `hostname`, `email`, `guid`,
`hexa`, `binary`, `identifier`, `enum`, `notEnum`.

### `Number`

```python
import pyarcjon as JON

age = JON.Number('fr').label('age').required().min(0).max(120)
print(age.validate(30)['valid'])  # True

port = JON.Number('fr').label('port').required().TCPPort()
print(port.validate(8080)['valid'])  # True

integer = JON.Number('fr').integer()
positive = JON.Number('fr').positive()
multiple = JON.Number('fr').multiple(5)
```

### `Boolean`

```python
import pyarcjon as JON

actif = JON.Boolean('fr').label('actif').default(False)
print(actif.validate('true')['data'])   # True
print(actif.validate('non')['data'])    # False
```

### `Date`

```python
import pyarcjon as JON

naissance = JON.Date('fr').label('naissance').changeFormat('%Y/%m/%d').toDate()
res = naissance.validate('1990/05/15')
print(res['valid'])   # True
```

### `Object`

```python
import pyarcjon as JON

utilisateur = JON.Object('fr').label('utilisateur').required().struct({
    'nom': JON.String('fr').required().min(2),
    'age': JON.Number('fr').required().greater(0),
    'email': JON.String('fr').required().email(),
})

res = utilisateur.validate({
    'nom': 'Alice',
    'age': 30,
    'email': 'alice@example.com'
})
print(res['valid'])   # True
```

### `Array`

```python
import pyarcjon as JON

tags = JON.Array('fr').label('tags').types(
    JON.String('fr').required()
).min(1).max(5)

res = tags.validate(['python', 'validation'])
print(res['valid'])   # True
```

### `Enum` / `NotEnum`

```python
import pyarcjon as JON

statut = JON.Enum('fr').label('statut').choices('actif', 'inactif', 'en_attente')
print(statut.validate('actif')['valid'])  # True

pays_interdit = JON.NotEnum('fr').label('pays').choices('X', 'Y')
```

### `ChosenType` (union)

```python
import pyarcjon as JON

valeur = JON.ChosenType('fr').label('valeur').choices(
    JON.Number('fr'),
    JON.String('fr').min(1)
)

print(valeur.validate(42)['valid'])       # True
print(valeur.validate('texte')['valid'])  # True
```

---

## Règles personnalisées

```python
import pyarcjon as JON

score = JON.Number('fr').label('score').min(0).max(100).applyApp(
    rule=lambda v: v > 50,
    sanitize=lambda v: v * 2
)

res = score.validate(60)
print(res['data'])    # 120
```

Jusqu'à 50 règles personnalisées sont gérées en interne (`CUSTOM01` à
`CUSTOM50`).

---

## Résultat de validation

Toutes les méthodes `validate` retournent un dictionnaire :

```python
{
    'valid': bool,
    'data': any,      # valeur nettoyée / transformée
    'error': any      # None si valide, sinon Exception ou str
}
```

---

## Architecture

```text
pyarcjon/
├── __init__.py        # API publique
├── JON.py             # Assemblage des classes
├── JON_default.py     # Classe de base JONDefaultSchema
├── JON_sup.py         # Types String, Number, Boolean, Date, Object, Array, Enum, ...
├── JON_hybrid.py      # Helpers hybrides
├── JON_simplify.py    # Simplification / réallocation de validateurs
└── JON_sup.py         # Suppléments
```

---

## Auteur

Développé avec passion par **INICODE** — `contact.inicode@gmail.com`.

Licence : MIT.


