Spaces:
Runtime error
Runtime error
Claude Opus 5
feat(recherche): le titre passe devant le corps du texte, et les fautes de frappe passent
893a679 Download tests/test_services/test_article_reference.py from rahim237cm/jurix-api: direct link, hf CLI and curl.
- Browser
- Download file 7.03 kB
-
https://huggingface.co/spaces/rahim237cm/jurix-api/resolve/main/tests/test_services/test_article_reference.py
- Command line
-
hf download hf://spaces/rahim237cm/jurix-api/tests/test_services/test_article_reference.py
-
curl -L -o test_article_reference.py https://huggingface.co/spaces/rahim237cm/jurix-api/resolve/main/tests/test_services/test_article_reference.py
7.03 kB
| """ | |
| « article 35 du code minier » ouvre le bon document sur le bon article. | |
| Trois choses devaient exister ensemble : reconnaitre le numero, reconnaitre le | |
| document, et verifier que l'article s'y trouve. Avant, la premiere seule etait | |
| faite — `_parse_article_reference` extrayait bien `doc_hint`, mais personne ne | |
| s'en servait, et `direct_navigation` etait conditionne a `total == 1`, ce qui ne | |
| se produit presque jamais. | |
| Usage: | |
| pytest tests/test_services/test_article_reference.py -v | |
| """ | |
| from datetime import date | |
| import pytest | |
| from app.models.law import Article, Law | |
| from app.schemas.search import SearchRequest | |
| from app.services.article_reference import ( | |
| ArticleReference, | |
| normalize_number, | |
| parse_reference, | |
| ) | |
| from app.services.search_service import SearchService | |
| from app.services.search_vectors import REINDEX_ARTICLES_SQL, REINDEX_LAWS_SQL | |
| CODE_MINIER = 300 | |
| CODE_TRAVAIL = 301 | |
| async def codes(db_session, category_ids): | |
| from sqlalchemy import text as sql_text | |
| laws = [ | |
| Law(id=CODE_MINIER, reference="LOI-2023-014", | |
| title="Loi N°2023/014 du 19 décembre 2023 portant Code Minier", | |
| content="Code régissant les activités minières au Cameroun.", | |
| type="loi", language="fr", status="published", | |
| category_id=category_ids["Droit de l'Environnement et des Ressources Naturelles"], | |
| publication_date=date(2023, 12, 19)), | |
| Law(id=CODE_TRAVAIL, reference="LOI-1992-007", | |
| title="Loi N°92/007 du 14 août 1992 portant Code du Travail", | |
| content="Code régissant les relations de travail.", | |
| type="loi", language="fr", status="published", | |
| category_id=category_ids["Droit du Travail et Sécurité Sociale"], | |
| publication_date=date(1992, 8, 14)), | |
| ] | |
| db_session.add_all(laws) | |
| await db_session.flush() | |
| articles = [] | |
| for law_id, numbers in ((CODE_MINIER, ("1", "35", "36")), (CODE_TRAVAIL, ("1", "2"))): | |
| for number in numbers: | |
| articles.append(Article( | |
| law_id=law_id, number=number, | |
| content=(f"Dispositions de l'article {number}. " | |
| "La superficie couverte par le permis de recherche est limitée."), | |
| order=int(number), kind="article", embed=True, | |
| )) | |
| db_session.add_all(articles) | |
| await db_session.commit() | |
| await db_session.execute(sql_text(REINDEX_LAWS_SQL)) | |
| await db_session.execute(sql_text(REINDEX_ARTICLES_SQL)) | |
| await db_session.commit() | |
| return laws | |
| def service(db_session): | |
| return SearchService(db_session, use_cache=False) | |
| class TestParsing: | |
| """Le module unique remplace huit motifs « article N » divergents.""" | |
| def test_parses(self, query, number, hint): | |
| reference = parse_reference(query) | |
| assert reference == ArticleReference(number, hint), f"pour {query!r}" | |
| def test_not_a_reference(self, query): | |
| assert parse_reference(query) is None | |
| def test_normalisation(self, raw, expected): | |
| """`articles.number` stocke « 1 » : rendre « PREMIER » ne matcherait rien.""" | |
| assert normalize_number(raw) == expected | |
| class TestDirectNavigation: | |
| async def test_opens_the_right_document_on_the_right_article(self, service, codes): | |
| response = await service.search( | |
| SearchRequest(query="article 35 du code minier", mode="text", limit=10) | |
| ) | |
| assert response.target_law_id == CODE_MINIER | |
| assert response.target_article == "35" | |
| assert response.direct_navigation is True | |
| async def test_the_document_hint_tolerates_a_typo(self, service, codes): | |
| """word_similarity('code miner', 'Loi ... portant Code Minier') = 0,727.""" | |
| response = await service.search( | |
| SearchRequest(query="article 35 du code miner", mode="text", limit=10) | |
| ) | |
| assert response.target_law_id == CODE_MINIER | |
| assert response.direct_navigation is True | |
| async def test_the_hint_selects_between_two_codes(self, service, codes): | |
| response = await service.search( | |
| SearchRequest(query="article 1 du code du travail", mode="text", limit=10) | |
| ) | |
| assert response.target_law_id == CODE_TRAVAIL | |
| async def test_an_absent_article_does_not_navigate(self, service, codes): | |
| """ | |
| Ouvrir un document sur un article qui n'y est pas serait pire que ne pas | |
| l'ouvrir : l'utilisateur croirait avoir lu la reponse. | |
| """ | |
| response = await service.search( | |
| SearchRequest(query="article 999 du code minier", mode="text", limit=10) | |
| ) | |
| assert response.direct_navigation is False | |
| assert response.target_article == "999" | |
| assert response.results, "les resultats de recherche doivent rester" | |
| async def test_article_premier_resolves_to_the_stored_number(self, service, codes): | |
| response = await service.search( | |
| SearchRequest(query="article premier du code minier", mode="text", limit=10) | |
| ) | |
| assert response.target_article == "1" | |
| assert response.target_law_id == CODE_MINIER | |
| async def test_a_plain_query_does_not_navigate(self, service, codes): | |
| response = await service.search( | |
| SearchRequest(query="permis de recherche", mode="text", limit=10) | |
| ) | |
| assert response.direct_navigation is False | |
| assert response.target_article is None | |
| class TestRemovedEndpoint: | |
| async def test_the_dead_article_endpoint_is_gone(self, client, db_session): | |
| """ | |
| Repondait 500 : il appelait `_parse_article_reference` ET | |
| `_estimate_page_number`, aucun des deux defini dans ce module. Aucun | |
| test ne le couvrait — c'est ce qui lui a permis de survivre. | |
| """ | |
| response = await client.get("/api/v1/search/article?q=article%205") | |
| assert response.status_code == 404 | |