0.0.5-alpha.3.fix.1
This commit is contained in:
164
deltas/0.0.5/alpha.3.fix.1.md
Normal file
164
deltas/0.0.5/alpha.3.fix.1.md
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
<!-- file: deltas/0.0.5/alpha.3.fix.1.md -->
|
||||||
|
<!-- version: 1 -->
|
||||||
|
|
||||||
|
# Delta 0.0.5-alpha.3.fix.1 — couverture des tables dans les exemples Markdown fenced
|
||||||
|
|
||||||
|
## Baseline et version
|
||||||
|
|
||||||
|
Baseline attendue : commit opérateur de `0.0.5-alpha.3`, réalisé après application de `history/0.0.5/alpha.3.md` avec statut `FAIL`.
|
||||||
|
|
||||||
|
Le hash de ce commit n'est pas anticipé.
|
||||||
|
|
||||||
|
Version avant application :
|
||||||
|
|
||||||
|
```text
|
||||||
|
0.0.5-alpha.3
|
||||||
|
```
|
||||||
|
|
||||||
|
Version après application :
|
||||||
|
|
||||||
|
```text
|
||||||
|
0.0.5-alpha.3.fix.1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Objet
|
||||||
|
|
||||||
|
Corriger le faux négatif découvert pendant la gate opérateur de `alpha.3` : `audit_markdown_tables.py` ignorait toutes les tables placées dans des blocs fenced, y compris les exemples explicitement `markdown` du template `004-FILE_FAMILY_CONTRACTS.md`.
|
||||||
|
|
||||||
|
Le fix étend uniquement le contrat de l'audit de tables. Il ne transforme pas l'audit en analyseur général des blocs de code et n'introduit aucun contenu de la tranche Rust `alpha.4`.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
REPLACE :
|
||||||
|
|
||||||
|
```text
|
||||||
|
VERSION
|
||||||
|
scripts/audit_markdown_tables.py
|
||||||
|
docs/templates/004-FILE_FAMILY_CONTRACTS.md
|
||||||
|
docs/validation/001-VALIDATION_MATRIX.md
|
||||||
|
```
|
||||||
|
|
||||||
|
ADD :
|
||||||
|
|
||||||
|
```text
|
||||||
|
tests/test_markdown_tables.py
|
||||||
|
deltas/0.0.5/alpha.3.fix.1.md
|
||||||
|
```
|
||||||
|
|
||||||
|
DELETE : aucun.
|
||||||
|
|
||||||
|
Le history `history/0.0.5/alpha.3.md` appartient au commit baseline du FAIL et n'est pas inclus dans l'archive du fix.
|
||||||
|
|
||||||
|
## Correction
|
||||||
|
|
||||||
|
`scripts/audit_markdown_tables.py` passe en révision interne `2`.
|
||||||
|
|
||||||
|
L'audit continue de contrôler les tables Markdown ordinaires. Dans un bloc fenced :
|
||||||
|
|
||||||
|
- une fence explicitement `markdown` est auditée ;
|
||||||
|
- une fence explicitement `md` est auditée ;
|
||||||
|
- une fence d'un autre langage ou sans langage reste ignorée.
|
||||||
|
|
||||||
|
Cette frontière évite les faux positifs sur les sorties terminal, extraits de code ou tableaux ASCII qui utilisent éventuellement des pipes sans être du Markdown à gouverner.
|
||||||
|
|
||||||
|
`tests/test_markdown_tables.py` verrouille quatre cas :
|
||||||
|
|
||||||
|
1. table ordinaire et table fenced Markdown valides toutes deux comptées ;
|
||||||
|
2. table mal alignée dans une fence `markdown` rejetée ;
|
||||||
|
3. alias `md` audité ;
|
||||||
|
4. fence non Markdown conservée hors scope.
|
||||||
|
|
||||||
|
`docs/templates/004-FILE_FAMILY_CONTRACTS.md` passe en révision `2` et réaligne les deux tables fenced révélées par le nouvel audit.
|
||||||
|
|
||||||
|
`docs/validation/001-VALIDATION_MATRIX.md` passe en révision `10` et explicite la frontière de `PGR-MD-TABLE-001`.
|
||||||
|
|
||||||
|
## Validation opérateur
|
||||||
|
|
||||||
|
Après application du history `FAIL`, commit de `alpha.3`, puis application du présent delta :
|
||||||
|
|
||||||
|
```bash
|
||||||
|
test "$(cat VERSION)" = '0.0.5-alpha.3.fix.1'
|
||||||
|
test -f history/0.0.5/alpha.3.md
|
||||||
|
test -f deltas/0.0.5/alpha.3.md
|
||||||
|
test -f deltas/0.0.5/alpha.3.fix.1.md
|
||||||
|
test -f tests/test_markdown_tables.py
|
||||||
|
test ! -e history/0.0.5/alpha.3.fix.1.md
|
||||||
|
|
||||||
|
grep -A2 '^## Statut$' history/0.0.5/alpha.3.md | grep -Fx 'FAIL'
|
||||||
|
grep -Fx '# version: 2' scripts/audit_markdown_tables.py
|
||||||
|
grep -Fx '<!-- version: 2 -->' docs/templates/004-FILE_FAMILY_CONTRACTS.md
|
||||||
|
grep -Fx '<!-- version: 10 -->' docs/validation/001-VALIDATION_MATRIX.md
|
||||||
|
grep -Fx '# version: 1' tests/test_markdown_tables.py
|
||||||
|
|
||||||
|
python3 -B -m unittest discover -s tests -p 'test_markdown_tables.py' -v
|
||||||
|
python3 -B -m unittest discover -s tests -v
|
||||||
|
|
||||||
|
python3 -B scripts/audit_markdown_headers.py \
|
||||||
|
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
|
||||||
|
python3 -B scripts/audit_markdown_tables.py \
|
||||||
|
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
|
||||||
|
python3 -B scripts/audit_markdown_links.py \
|
||||||
|
README.md RULES.md ROADMAP.md CHANGELOG.md docs deltas history prompts
|
||||||
|
|
||||||
|
python3 -B scripts/audit_markdown_tables.py docs/templates/004-FILE_FAMILY_CONTRACTS.md
|
||||||
|
|
||||||
|
python3 -B - <<'PY'
|
||||||
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
|
||||||
|
history = Path('history/0.0.5/alpha.3.md').read_text(encoding='utf-8')
|
||||||
|
assert re.search(r'## Statut\s+FAIL\s', history)
|
||||||
|
|
||||||
|
script = Path('scripts/audit_markdown_tables.py').read_text(encoding='utf-8')
|
||||||
|
assert '_MARKDOWN_FENCE_LANGUAGES = frozenset({"markdown", "md"})' in script
|
||||||
|
assert 'audit_fenced_markdown' in script
|
||||||
|
|
||||||
|
template = Path('docs/templates/004-FILE_FAMILY_CONTRACTS.md').read_text(encoding='utf-8')
|
||||||
|
assert template.count('```markdown') == 2
|
||||||
|
|
||||||
|
matrix = Path('docs/validation/001-VALIDATION_MATRIX.md').read_text(encoding='utf-8')
|
||||||
|
assert 'fences explicitement `markdown` ou `md`' in matrix
|
||||||
|
assert 'sorties terminal' in matrix
|
||||||
|
|
||||||
|
print('0.0.5 alpha.3.fix.1 fenced Markdown table audit: clean (regression covered, two template examples governed)')
|
||||||
|
PY
|
||||||
|
|
||||||
|
git diff --check
|
||||||
|
|
||||||
|
git add VERSION scripts/audit_markdown_tables.py tests/test_markdown_tables.py \
|
||||||
|
docs/templates/004-FILE_FAMILY_CONTRACTS.md \
|
||||||
|
docs/validation/001-VALIDATION_MATRIX.md \
|
||||||
|
deltas/0.0.5/alpha.3.fix.1.md
|
||||||
|
|
||||||
|
git diff --cached --check
|
||||||
|
git status --short
|
||||||
|
```
|
||||||
|
|
||||||
|
La sortie Git attendue avant ajout du history du fix est exactement :
|
||||||
|
|
||||||
|
```text
|
||||||
|
M VERSION
|
||||||
|
A deltas/0.0.5/alpha.3.fix.1.md
|
||||||
|
M docs/templates/004-FILE_FAMILY_CONTRACTS.md
|
||||||
|
M docs/validation/001-VALIDATION_MATRIX.md
|
||||||
|
M scripts/audit_markdown_tables.py
|
||||||
|
A tests/test_markdown_tables.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Le contrôle ciblé du template doit désormais compter ses deux exemples :
|
||||||
|
|
||||||
|
```text
|
||||||
|
Markdown table audit: clean (2 table(s), 1 file(s))
|
||||||
|
```
|
||||||
|
|
||||||
|
La suite Python doit compter `19` tests si aucun autre test n'est ajouté localement avant exécution.
|
||||||
|
|
||||||
|
## Transition
|
||||||
|
|
||||||
|
### PASS
|
||||||
|
|
||||||
|
Créer et appliquer séparément `history/0.0.5/alpha.3.fix.1.md`, committer et pousser le fix, puis reprendre le plan `0.0.5` à `alpha.4`.
|
||||||
|
|
||||||
|
### FAIL
|
||||||
|
|
||||||
|
Rester dans `0.0.5-alpha.3.fix.M`. Le scope MUST rester limité au contrat de `PGR-MD-TABLE-001` et aux tables révélées par ce contrôle tant qu'aucun défaut plus large ne justifie un REPLAN.
|
||||||
14
docs/templates/004-FILE_FAMILY_CONTRACTS.md
vendored
14
docs/templates/004-FILE_FAMILY_CONTRACTS.md
vendored
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/templates/004-FILE_FAMILY_CONTRACTS.md -->
|
<!-- file: docs/templates/004-FILE_FAMILY_CONTRACTS.md -->
|
||||||
<!-- version: 1 -->
|
<!-- version: 2 -->
|
||||||
|
|
||||||
# Pattern — contrats locaux de fichiers ou familles
|
# Pattern — contrats locaux de fichiers ou familles
|
||||||
|
|
||||||
@@ -43,8 +43,8 @@ validation or synchronization requirement
|
|||||||
Une table Markdown convient aux registres structurés :
|
Une table Markdown convient aux registres structurés :
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
| Fichier ou famille | Responsabilité | Règle de modification |
|
| Fichier ou famille | Responsabilité | Règle de modification |
|
||||||
|--------------------|----------------|------------------------|
|
|---------------------|------------------|----------------------------|
|
||||||
| `<path-or-pattern>` | `<rôle durable>` | `<quand/comment modifier>` |
|
| `<path-or-pattern>` | `<rôle durable>` | `<quand/comment modifier>` |
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -65,10 +65,10 @@ Le registre SHOULD évoluer lorsqu'une responsabilité ou règle de modification
|
|||||||
## Exemple abstrait
|
## Exemple abstrait
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
| Fichier ou famille | Responsabilité | Règle de modification |
|
| Fichier ou famille | Responsabilité | Règle de modification |
|
||||||
|--------------------|----------------|------------------------|
|
|--------------------|---------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------|
|
||||||
| `config/*.example` | Décrire les exemples versionnés de configuration locale. | Mettre à jour lorsqu'une option utilisateur versionnée est ajoutée ou retirée ; ne jamais y placer de secret réel. |
|
| `config/*.example` | Décrire les exemples versionnés de configuration locale. | Mettre à jour lorsqu'une option utilisateur versionnée est ajoutée ou retirée ; ne jamais y placer de secret réel. |
|
||||||
| `generated/**` | Contenir les sorties reconstruisibles produites par la toolchain choisie. | Ne pas modifier manuellement ; régénérer depuis la source de vérité documentée. |
|
| `generated/**` | Contenir les sorties reconstruisibles produites par la toolchain choisie. | Ne pas modifier manuellement ; régénérer depuis la source de vérité documentée. |
|
||||||
```
|
```
|
||||||
|
|
||||||
Cet exemple illustre la forme uniquement. Il ne crée aucune règle universelle sur les chemins `config/` ou `generated/`.
|
Cet exemple illustre la forme uniquement. Il ne crée aucune règle universelle sur les chemins `config/` ou `generated/`.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!-- file: docs/validation/001-VALIDATION_MATRIX.md -->
|
<!-- file: docs/validation/001-VALIDATION_MATRIX.md -->
|
||||||
<!-- version: 9 -->
|
<!-- version: 10 -->
|
||||||
|
|
||||||
# Matrice de validation PGR
|
# Matrice de validation PGR
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ Les catégories et règles de sélection sont définies dans [`../rules/400-VALI
|
|||||||
|
|
||||||
Un contrôle manuel peut rester dans la matrice lorsqu'aucun audit automatisé fiable n'existe encore. PGR SHOULD automatiser uniquement les propriétés stables et objectivement contrôlables.
|
Un contrôle manuel peut rester dans la matrice lorsqu'aucun audit automatisé fiable n'existe encore. PGR SHOULD automatiser uniquement les propriétés stables et objectivement contrôlables.
|
||||||
|
|
||||||
`PGR-MD-TABLE-001` reste volontairement monotâche : il contrôle uniquement la structure et l'alignement source des tableaux Markdown.
|
`PGR-MD-TABLE-001` reste volontairement monotâche : il contrôle uniquement la structure et l'alignement source des tableaux Markdown. Il couvre les tableaux Markdown ordinaires ainsi que les exemples placés dans des fences explicitement `markdown` ou `md`. Les autres blocs fenced restent ignorés afin de ne pas interpréter comme Markdown des sorties terminal, extraits de code ou tableaux ASCII d'un autre langage.
|
||||||
|
|
||||||
`PGR-MD-HEADER-001` contrôle seulement les deux premières lignes des fichiers Markdown sélectionnés : chemin relatif depuis la racine et révision interne positive. La revue `PGR-DOC-001` reste responsable du rôle documentaire et de la pertinence réelle d'un incrément de révision.
|
`PGR-MD-HEADER-001` contrôle seulement les deux premières lignes des fichiers Markdown sélectionnés : chemin relatif depuis la racine et révision interne positive. La revue `PGR-DOC-001` reste responsable du rôle documentaire et de la pertinence réelle d'un incrément de révision.
|
||||||
|
|
||||||
|
|||||||
128
history/0.0.5/alpha.3.fix.1.md
Normal file
128
history/0.0.5/alpha.3.fix.1.md
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
<!-- file: history/0.0.5/alpha.3.fix.1.md -->
|
||||||
|
<!-- version: 1 -->
|
||||||
|
|
||||||
|
# History 0.0.5-alpha.3.fix.1 — couverture des tables dans les exemples Markdown fenced
|
||||||
|
|
||||||
|
## Statut
|
||||||
|
|
||||||
|
PASS
|
||||||
|
|
||||||
|
La gate opérateur de `0.0.5-alpha.3.fix.1` exécutée le `2026-09-24` valide la correction de `PGR-MD-TABLE-001`. Le faux négatif constaté pendant `alpha.3` est couvert par des tests de régression, les deux tables fenced du template `004` sont désormais gouvernées par l'audit et les contrôles documentaires/Git sont propres.
|
||||||
|
|
||||||
|
## Baseline et version
|
||||||
|
|
||||||
|
La tranche part du commit opérateur de `0.0.5-alpha.3`, enregistré après application du history `FAIL`. La sortie Git fournie identifie ce commit sous la forme abrégée :
|
||||||
|
|
||||||
|
```text
|
||||||
|
1b1a709 0.0.5-alpha.3
|
||||||
|
```
|
||||||
|
|
||||||
|
Le push vers `origin/master` a réussi avant l'application de `alpha.3.fix.1`.
|
||||||
|
|
||||||
|
La version contrôlée après application du fix est :
|
||||||
|
|
||||||
|
```text
|
||||||
|
0.0.5-alpha.3.fix.1
|
||||||
|
```
|
||||||
|
|
||||||
|
Les artefacts suivants sont présents pendant la gate :
|
||||||
|
|
||||||
|
```text
|
||||||
|
history/0.0.5/alpha.3.md
|
||||||
|
|
||||||
|
deltas/0.0.5/alpha.3.md
|
||||||
|
deltas/0.0.5/alpha.3.fix.1.md
|
||||||
|
tests/test_markdown_tables.py
|
||||||
|
```
|
||||||
|
|
||||||
|
`history/0.0.5/alpha.3.fix.1.md` est absent pendant la gate, conformément au workflow.
|
||||||
|
|
||||||
|
## Validation opérateur observée
|
||||||
|
|
||||||
|
Les contrôles de statut et de révision ont réussi :
|
||||||
|
|
||||||
|
```text
|
||||||
|
history/0.0.5/alpha.3.md FAIL
|
||||||
|
scripts/audit_markdown_tables.py version 2
|
||||||
|
docs/templates/004-FILE_FAMILY_CONTRACTS.md version 2
|
||||||
|
docs/validation/001-VALIDATION_MATRIX.md version 10
|
||||||
|
tests/test_markdown_tables.py version 1
|
||||||
|
```
|
||||||
|
|
||||||
|
La suite ciblée du nouvel audit a exécuté `4` tests, tous réussis :
|
||||||
|
|
||||||
|
```text
|
||||||
|
Ran 4 tests in 0.093s
|
||||||
|
|
||||||
|
OK
|
||||||
|
```
|
||||||
|
|
||||||
|
Les cas couverts vérifient :
|
||||||
|
|
||||||
|
- le comptage conjoint d'une table ordinaire et d'une table fenced Markdown ;
|
||||||
|
- le rejet d'une table mal alignée dans une fence `markdown` ;
|
||||||
|
- l'audit de l'alias `md` ;
|
||||||
|
- le maintien hors scope des fences non Markdown.
|
||||||
|
|
||||||
|
La suite Python globale a exécuté `19` tests, tous réussis :
|
||||||
|
|
||||||
|
```text
|
||||||
|
Ran 19 tests in 0.311s
|
||||||
|
|
||||||
|
OK
|
||||||
|
```
|
||||||
|
|
||||||
|
Les trois audits documentaires affichent :
|
||||||
|
|
||||||
|
```text
|
||||||
|
Markdown header audit: clean (134 file(s))
|
||||||
|
Markdown table audit: clean (6 table(s), 134 file(s))
|
||||||
|
Markdown link audit: clean (127 local link(s), 134 file(s))
|
||||||
|
```
|
||||||
|
|
||||||
|
Le contrôle ciblé du template affiche désormais :
|
||||||
|
|
||||||
|
```text
|
||||||
|
Markdown table audit: clean (2 table(s), 1 file(s))
|
||||||
|
```
|
||||||
|
|
||||||
|
Le contrôle structurel spécifique affiche :
|
||||||
|
|
||||||
|
```text
|
||||||
|
0.0.5 alpha.3.fix.1 fenced Markdown table audit: clean (regression covered, two template examples governed)
|
||||||
|
```
|
||||||
|
|
||||||
|
Il confirme notamment que l'audit reconnaît uniquement les fences explicites `markdown` ou `md`, que les deux exemples du template sont présents et que la matrice de validation documente l'exclusion volontaire des sorties terminal/non-Markdown.
|
||||||
|
|
||||||
|
`git diff --check` et `git diff --cached --check` n'ont produit aucun diagnostic.
|
||||||
|
|
||||||
|
Le scope Git observé avant ajout du présent history est exactement :
|
||||||
|
|
||||||
|
```text
|
||||||
|
M VERSION
|
||||||
|
A deltas/0.0.5/alpha.3.fix.1.md
|
||||||
|
M docs/templates/004-FILE_FAMILY_CONTRACTS.md
|
||||||
|
M docs/validation/001-VALIDATION_MATRIX.md
|
||||||
|
M scripts/audit_markdown_tables.py
|
||||||
|
A tests/test_markdown_tables.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Résultat
|
||||||
|
|
||||||
|
Le défaut de `alpha.3` est corrigé sans élargir l'audit à des blocs de code qui ne sont pas explicitement du Markdown. `PGR-MD-TABLE-001` couvre maintenant les tables normales ainsi que les exemples fenced Markdown, tout en continuant d'ignorer les fences d'autres langages.
|
||||||
|
|
||||||
|
Aucun nouveau fix de `alpha.3` n'est requis.
|
||||||
|
|
||||||
|
Après la gate, une revue distincte du plan et des historiques de conception PGR a révélé un besoin de gouvernance plus large : le contrat des plans n'assigne pas encore explicitement les responsabilités de clôture/transition et PGR ne définit pas encore de revue d'horizon de roadmap. Ce besoin ne remet pas en cause le présent fix ; il justifie un REPLAN dans la tranche normale suivante.
|
||||||
|
|
||||||
|
## Transition
|
||||||
|
|
||||||
|
Appliquer le présent history puis committer et pousser `0.0.5-alpha.3.fix.1`.
|
||||||
|
|
||||||
|
La tranche suivante devient :
|
||||||
|
|
||||||
|
```text
|
||||||
|
0.0.5-alpha.4
|
||||||
|
```
|
||||||
|
|
||||||
|
avec rôle `REPLAN`. Elle doit traiter uniquement le lifecycle inter-release, le contrat de clôture/transition des plans, la revue d'horizon et les optimisations workflow directement liées. Les anciens travaux prévus à partir de `alpha.4` sont décalés sans être abandonnés.
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# file: scripts/audit_markdown_tables.py
|
# file: scripts/audit_markdown_tables.py
|
||||||
# version: 1
|
# version: 2
|
||||||
|
|
||||||
"""Validate source formatting of Markdown tables in explicitly selected paths."""
|
"""Validate source formatting of Markdown tables in explicitly selected paths."""
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@ import sys
|
|||||||
|
|
||||||
_SEPARATOR = re.compile(r"^:?-{3,}:?$")
|
_SEPARATOR = re.compile(r"^:?-{3,}:?$")
|
||||||
_IGNORED_DIRECTORIES = frozenset({".git", ".idea", ".venv", "__pycache__", "dist", "node_modules", "target"})
|
_IGNORED_DIRECTORIES = frozenset({".git", ".idea", ".venv", "__pycache__", "dist", "node_modules", "target"})
|
||||||
|
_MARKDOWN_FENCE_LANGUAGES = frozenset({"markdown", "md"})
|
||||||
|
|
||||||
|
|
||||||
def _selected_files(raw_paths: list[str]) -> tuple[list[pathlib.Path], list[str]]:
|
def _selected_files(raw_paths: list[str]) -> tuple[list[pathlib.Path], list[str]]:
|
||||||
@@ -130,11 +131,19 @@ def _validate_table(path: pathlib.Path, start_line: int, rows: list[str]) -> lis
|
|||||||
return errors
|
return errors
|
||||||
|
|
||||||
|
|
||||||
|
def _fence_language(stripped: str) -> str | None:
|
||||||
|
info = stripped[3:].strip()
|
||||||
|
if not info:
|
||||||
|
return None
|
||||||
|
return info.split(None, 1)[0].lower()
|
||||||
|
|
||||||
|
|
||||||
def _audit_file(path: pathlib.Path) -> tuple[int, list[str]]:
|
def _audit_file(path: pathlib.Path) -> tuple[int, list[str]]:
|
||||||
lines = path.read_text(encoding="utf-8").splitlines()
|
lines = path.read_text(encoding="utf-8").splitlines()
|
||||||
errors: list[str] = []
|
errors: list[str] = []
|
||||||
tables = 0
|
tables = 0
|
||||||
fence: str | None = None
|
fence: str | None = None
|
||||||
|
audit_fenced_markdown = False
|
||||||
index = 0
|
index = 0
|
||||||
|
|
||||||
while index < len(lines):
|
while index < len(lines):
|
||||||
@@ -143,12 +152,14 @@ def _audit_file(path: pathlib.Path) -> tuple[int, list[str]]:
|
|||||||
marker = stripped[:3]
|
marker = stripped[:3]
|
||||||
if fence is None:
|
if fence is None:
|
||||||
fence = marker
|
fence = marker
|
||||||
|
audit_fenced_markdown = _fence_language(stripped) in _MARKDOWN_FENCE_LANGUAGES
|
||||||
elif fence == marker:
|
elif fence == marker:
|
||||||
fence = None
|
fence = None
|
||||||
|
audit_fenced_markdown = False
|
||||||
index += 1
|
index += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if fence is not None:
|
if fence is not None and not audit_fenced_markdown:
|
||||||
index += 1
|
index += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|||||||
90
tests/test_markdown_tables.py
Normal file
90
tests/test_markdown_tables.py
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
# file: tests/test_markdown_tables.py
|
||||||
|
# version: 1
|
||||||
|
|
||||||
|
"""Exercise Markdown table detection, including explicit Markdown examples."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import pathlib
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tempfile
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
_SCRIPT = pathlib.Path(__file__).resolve().parents[1] / "scripts/audit_markdown_tables.py"
|
||||||
|
|
||||||
|
|
||||||
|
class MarkdownTableAuditTests(unittest.TestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
temporary = tempfile.TemporaryDirectory(prefix="pgr-tables-")
|
||||||
|
self.addCleanup(temporary.cleanup)
|
||||||
|
self.root = pathlib.Path(temporary.name)
|
||||||
|
|
||||||
|
def source(self, contents: str) -> pathlib.Path:
|
||||||
|
path = self.root / "sample.md"
|
||||||
|
path.write_text(contents, encoding="utf-8")
|
||||||
|
return path
|
||||||
|
|
||||||
|
def run_audit(self) -> subprocess.CompletedProcess[str]:
|
||||||
|
return subprocess.run(
|
||||||
|
[sys.executable, "-B", str(_SCRIPT), "sample.md"],
|
||||||
|
cwd=self.root, capture_output=True, text=True, check=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_regular_and_fenced_markdown_tables_are_counted(self) -> None:
|
||||||
|
self.source(
|
||||||
|
"| A | BB |\n"
|
||||||
|
"|---|----|\n"
|
||||||
|
"| x | y |\n"
|
||||||
|
"\n"
|
||||||
|
"```markdown\n"
|
||||||
|
"| C | DD |\n"
|
||||||
|
"|---|----|\n"
|
||||||
|
"| z | q |\n"
|
||||||
|
"```\n"
|
||||||
|
)
|
||||||
|
result = self.run_audit()
|
||||||
|
self.assertEqual(result.returncode, 0, result.stderr)
|
||||||
|
self.assertIn("clean (2 table(s), 1 file(s))", result.stdout)
|
||||||
|
|
||||||
|
def test_misaligned_table_inside_markdown_fence_is_rejected(self) -> None:
|
||||||
|
self.source(
|
||||||
|
"```markdown\n"
|
||||||
|
"| Fichier ou famille | Responsabilité | Règle de modification |\n"
|
||||||
|
"|--------------------|----------------|------------------------|\n"
|
||||||
|
"| `<path-or-pattern>` | `<rôle durable>` | `<quand/comment modifier>` |\n"
|
||||||
|
"```\n"
|
||||||
|
)
|
||||||
|
result = self.run_audit()
|
||||||
|
self.assertEqual(result.returncode, 1)
|
||||||
|
self.assertIn("sample.md:2: column 1 is not vertically aligned", result.stderr)
|
||||||
|
self.assertIn("column 2 is not vertically aligned", result.stderr)
|
||||||
|
self.assertIn("column 3 is not vertically aligned", result.stderr)
|
||||||
|
|
||||||
|
def test_md_fence_is_audited(self) -> None:
|
||||||
|
self.source(
|
||||||
|
"```md\n"
|
||||||
|
"| A | BB |\n"
|
||||||
|
"|---|----|\n"
|
||||||
|
"| x | y |\n"
|
||||||
|
"```\n"
|
||||||
|
)
|
||||||
|
result = self.run_audit()
|
||||||
|
self.assertEqual(result.returncode, 0, result.stderr)
|
||||||
|
self.assertIn("clean (1 table(s), 1 file(s))", result.stdout)
|
||||||
|
|
||||||
|
def test_non_markdown_fence_remains_ignored(self) -> None:
|
||||||
|
self.source(
|
||||||
|
"```text\n"
|
||||||
|
"| Fichier ou famille | Responsabilité |\n"
|
||||||
|
"|--------------------|----------------|\n"
|
||||||
|
"| x | y |\n"
|
||||||
|
"```\n"
|
||||||
|
)
|
||||||
|
result = self.run_audit()
|
||||||
|
self.assertEqual(result.returncode, 0, result.stderr)
|
||||||
|
self.assertIn("clean (0 table(s), 1 file(s))", result.stdout)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
Reference in New Issue
Block a user