legilibre / legi.py Goto Github PK
View Code? Open in Web Editor NEWOutils de manipulation des archives LEGI (lois françaises)
Outils de manipulation des archives LEGI (lois françaises)
Re-bonjour/bonsoir,
Toujours en parcourant le code la sécurité sociale, j'ai vu que la section 3 du chapitre II du livre II est vide dans la version sur Archeolex mais elle existe bien sur Légifrance.
En éspérant que ca aide
L'archive LEGI_20190829-213629.tar.gz
contient un dossier nommé 20190822-214645/legi/global/eli/decret/2019/8/20/2019-851/jo/article_préliminaire/
. L'accent est encodé en ISO-8859-1, pas en UTF-8, du coup le décodage et le découpage du chemin échouent.
Traceback (most recent call last):
...
File "/home/changaco/projets/legilibre/legi.py-clean/legi/tar2sqlite.py", line 558, in <module>
main()
File "/home/changaco/projets/legilibre/legi.py-clean/legi/tar2sqlite.py", line 532, in main
process_archive(db, args.directory + '/' + archive_name, not args.skip_links)
File "/home/changaco/projets/legilibre/legi.py-clean/legi/tar2sqlite.py", line 201, in process_archive
parts = path.split('/')
TypeError: a bytes-like object is required, not 'str'
Bonjour,
Je rencontre des problèmes avec libarchive sur mac silicon M1, j'obtiens l"erreur suivante, des idées ?
Traceback (most recent call last):
File "/Users/perso/opt/anaconda3/lib/python3.9/site-packages/libarchive/ffi.py", line 55, in
libarchive = ctypes.cdll.LoadLibrary(libarchive_path)
File "/Users/perso/opt/anaconda3/lib/python3.9/ctypes/init.py", line 460, in LoadLibrary
return self._dlltype(name)
File "/Users/perso/opt/anaconda3/lib/python3.9/ctypes/init.py", line 382, in init
self._handle = _dlopen(self._name, mode)
OSError: dlopen(/opt/homebrew/Cellar/libarchive/3.6.0/lib/libarchive.13.dylib, 0x0006): tried: '/opt/homebrew/Cellar/libarchive/3.6.0/lib/libarchive.13.dylib' (mach-o file, but is an incompatible architecture (have 'arm64', need 'x86_64')), '/usr/local/lib/libarchive.13.dylib' (no such file), '/usr/lib/libarchive.13.dylib' (no such file)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/perso/opt/anaconda3/lib/python3.9/runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/Users/perso/opt/anaconda3/lib/python3.9/runpy.py", line 87, in _run_code
exec(code, run_globals)
File "/Users/perso/Desktop/Personal Projects/Law/legi.py/legi/tar2sqlite.py", line 12, in
import libarchive
File "/Users/perso/opt/anaconda3/lib/python3.9/site-packages/libarchive/init.py", line 1, in
from .entry import ArchiveEntry
File "/Users/perso/opt/anaconda3/lib/python3.9/site-packages/libarchive/entry.py", line 6, in
from . import ffi
File "/Users/perso/opt/anaconda3/lib/python3.9/site-packages/libarchive/ffi.py", line 57, in
raise ImportError("Failed to load libarchive library from %s - are any dependencies missing?"
ImportError: Failed to load libarchive library from %s - are any dependencies missing?Is your environment activated?
Merci pour le travail,
Charles
Une des caractéristiques de Legifrance est que les références entre textes ne sont pas transformées en liens hypertextes dans le corps des articles. J'ai du vieux code qui traîne dans un coin pour la détection des liens vers d'autres articles, il faudrait que je l'intègre dans legi.py.
(Ticket similaire : Legilibre/Archeo-Lex#2.)
Bonjour tout le monde, en travaillant sur le code de la sécurité sociale, j'ai découvert deux mini-bugs de formatage:
Le premier, la section 9 du chapitre 1er du titre 9 du livre 3, "Personnes retenues dans un centre socio-médico-judiciaire de sûreté".
J'ai vu un bug similaire dans l'article D221-29
d'ailleurs.
Bon, le bug n’apparaît pas dans la version HTML, du coup c'est quand même très mineur.
A priori, le bug est sur legi.py
, même si je l'ai découvert en allant sur Archeolex.
Ca rapelle La Fabrique, on avait décidé d'enlever tout les doubles-espaces si je me rappel bien.
Ma solution serait surement de rajouter une regex ici:
Du style texte = re.sub( r'\s+', ' ', texte )
.
Bonjour,
J'explore depuis assez récemment les données LEGI et je constate une sorte anomalie mais je ne suis pas sûr que cela en soit une.
Je constate que LEGITEXT000019376991 est défini dans le répertoire
TNC_en_vigueur/JORF/TEXT/00/00/17/76/49/JORFTEXT000017764938/texte/struct/LEGITEXT000019376991.xml
alors qu'avec la morphologie du nom du fichier (LEGI-TEXT-00-00-19-37-69), il aurait été logique qu'il se trouve plutôt dans TNC_en_vigueur/JORF/TEXT/00/00/19/37/69/JORFTEXT000017764938/texte/struct/LEGITEXT000019376991.xml
A moins qu'il y ait une explication ?
merci
Bonjour,
Je rencontre un bug en suivant les instructions du readme:
$ python -m legi.tar2sqlite legi.sqlite ./tarballs
....
Traceback (most recent call last):
File "/usr/lib/python3.5/runpy.py", line 184, in _run_module_as_main
"__main__", mod_spec)
File "/usr/lib/python3.5/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/home/barth/strapdata/legi.py/legi/tar2sqlite.py", line 510, in <module>
main()
File "/home/barth/strapdata/legi.py/legi/tar2sqlite.py", line 505, in main
factorize(db)
TypeError: main() takes 0 positional arguments but 1 was given
J'utilise Python 3.5.2 et la version master de legi.py.
Le problème est simple, factorize.main
est appelé avec db
en paramètre depuis tar2sqlite.main
, alors que db
est une variable globale dans factorize.py
. Il semblerait avoir été introduit par bc2e734, en février... pourquoi pas programmer l'ajout de tests fonctionnels dans la roadmap ? :)
Super boulot en tout cas ! Je vais me servir de cette librairie :)
Bonjour,
Déjà un grand merci pour le travail phénoménal effectué sur ce projet 💪
Je signale juste un petit souci, quand un fichier s'est mal téléchargé, apparemment le script n'arrive pas à reprendre :
265 remote files, 244 common files (1 invalid), 21 missing files
Continuing the download of the file legi_20180202-195135.tar.gz
Traceback (most recent call last):
File "/usr/local/lib/python3.6/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/local/lib/python3.6/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/usr/src/app/legi.py/legi/download.py", line 70, in <module>
download_legi(args.directory)
File "/usr/src/app/legi.py/legi/download.py", line 56, in download_legi
rest=local_files[filename]['size']
File "/usr/local/lib/python3.6/ftplib.py", line 442, in retrbinary
with self.transfercmd(cmd, rest) as conn:
File "/usr/local/lib/python3.6/ftplib.py", line 399, in transfercmd
return self.ntransfercmd(cmd, rest)[0]
File "/usr/local/lib/python3.6/ftplib.py", line 359, in ntransfercmd
host, port = self.makepasv()
File "/usr/local/lib/python3.6/ftplib.py", line 337, in makepasv
host, port = parse227(self.sendcmd('PASV'))
File "/usr/local/lib/python3.6/ftplib.py", line 273, in sendcmd
return self.getresp()
File "/usr/local/lib/python3.6/ftplib.py", line 236, in getresp
resp = self.getmultiline()
File "/usr/local/lib/python3.6/ftplib.py", line 222, in getmultiline
line = self.getline()
File "/usr/local/lib/python3.6/ftplib.py", line 210, in getline
raise EOFError
EOFError
En supprimant le fichier en question et en relançant la commande, ca marche bien 👌
legi.py a un problème avec l'archive 20170630-204118 :
=> Starting tar2sqlite...
> last_update is 20170629-205629
> Skipped 129 old archives
> Processing legi_20170630-204118.tar.gz...
duplicate_files
('id', 'LEGITEXT000033583880')
('sous_dossier', 'texte/struct')
('cid', 'JORFTEXT000033578386')
('dossier', 'TNC_en_vigueur')
('mtime', 1498762615)
('data', '{"textes_structs": {"id": "LEGITEXT000033583880", "versions": "<VERSION etat=\\"\\"><LIEN_TXT debut=\\"2999-01-01\\" fin=\\"2999-01-01\\" id=\\"JORFTEXT000033578386\\" num=\\"\\"/></VERSION><VERSION etat=\\"ABROGE_DIFF\\"><LIEN_TXT debut=\\"2017-07-01\\" fin=\\"2017-07-01\\" id=\\"LEGITEXT000033583880\\" num=\\"\\"/></VERSION>", "dossier": "TNC_en_vigueur", "cid": "JORFTEXT000033578386", "mtime": 1498762615}, "liens": [{"src_id": "LEGITEXT000033583880", "dst_cid": "JORFTEXT000023413027", "dst_id": "JORFTEXT000023413027", "dst_titre": "D\\u00e9cret n\\u00b02011-45 du 11 janvier 2011", "typelien": "CITATION", "_reversed": 0}, {"src_id": "LEGIARTI000035046587", "dst_cid": "", "dst_id": "LEGITEXT000033583880", "dst_titre": "", "typelien": "ABROGATION", "_reversed": 1}], "sommaires": [{"cid": "JORFTEXT000033578386", "parent": null, "element": "LEGIARTI000033583882", "debut": "2999-01-01", "fin": "2999-01-01", "etat": "", "num": null, "position": 0, "_source": "struct/LEGITEXT000033583880"}, {"cid": "JORFTEXT000033578386", "parent": null, "element": "LEGIARTI000033583884", "debut": "2999-01-01", "fin": "2999-01-01", "etat": "", "num": null, "position": 1, "_source": "struct/LEGITEXT000033583880"}, {"cid": "JORFTEXT000033578386", "parent": null, "element": "LEGIARTI000033583886", "debut": "2017-07-01", "fin": "2017-07-01", "etat": "ABROGE_DIFF", "num": null, "position": 2, "_source": "struct/LEGITEXT000033583880"}, {"cid": "JORFTEXT000033578386", "parent": null, "element": "LEGIARTI000033583888", "debut": "2017-07-01", "fin": "2017-07-01", "etat": "ABROGE_DIFF", "num": null, "position": 3, "_source": "struct/LEGITEXT000033583880"}]}')
('other_cid', 'JORFTEXT000033578386')
('other_dossier', 'TNC_non_vigueur')
('other_mtime', 1498848089)
Traceback (most recent call last):
File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "legi/tar2sqlite.py", line 510, in <module>
main()
File "legi/tar2sqlite.py", line 486, in main
process_archive(db, args.directory + '/' + archive_name)
File "legi/tar2sqlite.py", line 254, in process_archive
'other_mtime': mtime,
File "legi/utils.py", line 118, in insert
""".format(or_clause, table, keys, placeholders), values)
sqlite3.IntegrityError: UNIQUE constraint failed: duplicate_files.id, duplicate_files.sous_dossier, duplicate_files.cid, duplicate_files.dossier
Les bases JORF et LEGI sont liées : la première est la version officielle, juridiquement contraignante, la seconde sont les versions consolidées ultérieures. Ainsi, très souvent (moins vrai pour les textes anciens), un article avec un numéro donné est au moins dans JORF (avec un numéro JORFARTI) puis sa vie future est dans LEGI (avec des numéros LEGIARTI).
Après quelques recherches, j’ai trouvé dans le XML d’un LEGIARTI sa correspondance avec son JORFARTI (le LEGIARTI000031012495, extraire ce dossier de la livraison 20191011-102231 (*)). Dans les balises ARTICLE → VERSIONS → VERSION* → LIEN_ART, il y a la liste des articles de même numéro dans LEGI (ce qui est également intéressant) mais surtout l’article de même numéro dans JORF (JORFARTI000002469313 en l’occurrence).
Je propose de rajouter cette information dans la base LEGI SQLite, au moins la correspondance LEGIARTI → JORFARTI, mais éventuellement plus largement « la version précédente d’un LEGIARTI donné » ce qui permettrait un chaînage.
Sans cette information, la meilleure façon de lier LEGI et JORF est de s’appuyer sur les numéros d’articles (3, 6 bis, etc), mais cela est probablement moins robuste à cause du manque de normalisation des numéros d’articles (même si cela a beaucoup été amélioré par @Changaco). Au moins, cela ferait un lien possible supplémentaire, les deux approches pouvant même être comparées.
(*) tar xfz Freemium_Legi_global_20191011-102231.tar.gz legi/global/code_et_TNC_en_vigueur/TNC_en_vigueur/JORF/TEXT/00/00/00/87/44/JORFTEXT000000874463
Je viens de trouver un nouveau type d’anomalie (en débuguant Archéo Lex, mais c’est dans la base LEGI) : certains articles (voire sections j’imagine) ont une date de début de vigueur antérieure à la date de début de vigueur de la section contenant lesdits articles.
L’exemple que j’ai trouvé est le suivant : dans le code de la propriété intellectuelle, les articles L132-1, L132-2, L132-3, L132-5, L132-9, L132-11, L132-17 devraient être présents dans la section 1 du chapitre L132 dans la version initiale du texte (voir la loi n° 92-597 de création du code), mais on peut constater qu’il ne le sont pas. Plus exactement, les LEGIARTI existent (par exemple le L132-1 dans sa version initiale) mais ils sont rattachés à l’actuelle sous-section 1 de la section 1 du chapitre L132 (qui n’existait pas dans la version initiale et a été créée le 1er décembre 2014, date à laquelle ces articles "apparaissent" sur Légifrance et dans Archéo Lex). On notera que dans la version initiale du CPI, les articles L132-4, L132-6, etc. sont présents – je ne comprend pas la logique et penche soit pour une erreur humaine soit un bug dans SOLON ou autre logiciel.
Je pense qu’on peut caractériser cette anomalie en recherchant :
sommaires
, les dates de début de vigueur d’éléments strictement antérieures à la date de début de vigueur de leur élément parent,sommaires
, les dates de fin de vigueur d’éléments strictement postérieures à la date de fin de vigueur de leur élément parent, à voir s’il faut mettre des exceptions sur les date spéciales 2222-02-22 et 2999-01-01 (au passage je remarque qu’il y a deux articles avec une date de fin 2222-02-02 :-).L'archive legi_20180207-194628.tar.gz
contient des fichiers non conformes. Exemples :
20180207-194628/legi/global/eli/arrete/2018/2/2/INTR1801572A/jo/article_1/versions.xml
20180207-194628/legi/global/eli/arrete/2018/2/2/INTR1801572A/jo/texte/versions.xml
20180207-194628/legi/global/eli/decision/2018/1/24/SSAS1803616S/jo/article_1/versions.xml
20180207-194628/legi/global/eli/decision/2018/1/24/SSAS1803616S/jo/texte/versions.xml
20180207-194628/legi/global/eli/loi/2007/12/24/BCFX0765271L/jo/article_80/versions.xml
20180207-194628/legi/global/eli/loi/2007/12/24/BCFX0765271L/jo/article_104/versions.xml
Du coup tar2sqlite
plante :
=> Starting tar2sqlite...
> last_update is 20180206-193721
> Skipped 287 old archives
> Processing legi_20180207-194628.tar.gz...
File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "legi/tar2sqlite.py", line 515, in <module>
main()
File "legi/tar2sqlite.py", line 491, in main
process_archive(db, args.directory + '/' + archive_name)
File "legi/tar2sqlite.py", line 204, in process_archive
text_cid = parts[11]
IndexError: list index out of range
Bonjour,
j'ai un petit pb avec legi.py, ou plutôt, libarchive sur mon Mac OS X 10.12.3, avec python 3.5
read format "7zip" is not supported
read format "rar" is not supported
read format "cab" is not supported
read format "lha" is not supported
read filter "none" is not supported
read filter "xz" is not supported
read filter "bzip2" is not supported
read filter "grzip" is not supported
read filter "rpm" is not supported
read filter "compress" is not supported
read filter "gzip" is not supported
read filter "uu" is not supported
read filter "lrzip" is not supported
read filter "lzma" is not supported
read filter "lzip" is not supported
read filter "all" is not supported
read filter "lzop" is not supported
Traceback (most recent call last):
File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 184, in _run_module_as_main
"__main__", mod_spec)
File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/Users/g/s/pro/dev/legi.py/legi/tar2sqlite.py", line 13, in <module>
import libarchive
File "/Users/g/s/.virtualenvs/legi/lib/python3.5/site-packages/libarchive/__init__.py", line 1, in <module>
from .entry import ArchiveEntry
File "/Users/g/s/.virtualenvs/legi/lib/python3.5/site-packages/libarchive/entry.py", line 6, in <module>
from . import ffi
File "/Users/g/s/.virtualenvs/legi/lib/python3.5/site-packages/libarchive/ffi.py", line 167, in <module>
c_int, check_int)
File "/Users/g/s/.virtualenvs/legi/lib/python3.5/site-packages/libarchive/ffi.py", line 92, in ffi
f = getattr(libarchive, 'archive_'+name)
File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ctypes/__init__.py", line 360, in __getattr__
func = self.__getitem__(name)
File "/usr/local/Cellar/python3/3.5.2_3/Frameworks/Python.framework/Versions/3.5/lib/python3.5/ctypes/__init__.py", line 365, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: dlsym(0x7ff6d9724f50, archive_read_open_filename_w): symbol not found
Peut-être que cette stack trace vous parle ? Il semble que libarchive (installé par brew) et le pypi libarchive-c "communique" pas bien ?
Merci,
191 remote files, 190 common files (0 invalid), 1 missing files
Downloading the file LEGI_20190329-223156.tar.gz
=> Starting tar2sqlite...
> last_update is 20190328-214428
> Skipped 306 old archives
> Processing LEGI_20190329-223156.tar.gz...
made 532629 changes in the database: {
"delete from liens": 204221,
"delete from sommaires": 45899,
"insert into articles": 987,
"insert into liens": 213389,
"insert into sections": 65,
"insert into sommaires": 47371,
"insert into textes_structs": 19,
"insert into textes_versions": 19,
"update in articles": 10414,
"update in sections": 5156,
"update in textes_structs": 470,
"update in textes_versions": 470,
"upsert into duplicate_files": 4149
}
skipped 27794 files in unknown folder `eli`
textes_structs
('id', 'LEGITEXT000006065566')
('versions', '<VERSION etat=""><LIEN_TXT debut="2999-01-01" fin="2999-01-01" id="JORFTEXT000000692519" num="86-520"/></VERSION><VERSION etat="ABROGE_DIFF"><LIEN_TXT debut="1986-03-16" fin="2019-04-01" id="LEGITEXT000006065566" num="86-520"/></VERSION>')
('dossier', 'TNC_en_vigueur')
('cid', 'JORFTEXT000000692519')
('mtime', 1544210873)
380.53it/s]2it [00:09, 829.26it/s]0.77it/s]52.37it/s]5it [00:31, 19.28it/s]36, 231.42it/s]it/s]0:53, 18.99it/s] 113.83it/s]/s] 42.84it/s]it/s]it [01:30, 15.12it/s]01:37, 115.77it/s]8252it [01:49, 34.46it/s]6.98it/s]/s]04, 95.89it/s]1it/s]3620it [02:14, 119.89it/s]02:19, 177.50it/s]:29, 13.84it/s]02:34, 202.32it/s]37.81it/s]s]Traceback (most recent call last):
File "/usr/lib/python3.7/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/lib/python3.7/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "legi/tar2sqlite.py", line 556, in <module>
main()
File "legi/tar2sqlite.py", line 530, in main
process_archive(db, args.directory + '/' + archive_name, not args.skip_links)
File "legi/tar2sqlite.py", line 461, in process_archive
suppress(get_table, db, liste_suppression)
File "legi/tar2sqlite.py", line 119, in suppress
db.insert(table, row)
File "legi/utils.py", line 125, in insert
""".format(or_clause, table, keys, placeholders), values)
sqlite3.IntegrityError: UNIQUE constraint failed: textes_structs.id
Bonjour,
J'ai essayé d'installer legi.py sur Ubuntu 16.04. Outre quelques difficultés lors de l'installation de hunspell (résolus en installant successivement les packages libhunspell-dev, hunspell et hunspell-fr avec apt-get sous Ubuntu), j'ai eu surtout une erreur SQL avec deux requêtes dans legi/normalize.py lors de l'initialisation de la base :
> python -m legi.tar2sqlite legi.sqlite ./tarballs
(...)
Traceback (most recent call last):
File "/usr/local/lib/python3.7/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/local/lib/python3.7/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/home/thbz/prog/legi.py/legi/tar2sqlite.py", line 575, in <module>
main()
File "/home/thbz/prog/legi.py/legi/tar2sqlite.py", line 568, in main
normalize_sommaires_num(db)
File "/home/thbz/prog/legi.py/legi/normalize.py", line 624, in normalize_sommaires_num
""")
sqlite3.OperationalError: near "AS": syntax error
J'obtiens la même erreur en exécutant la requête en question directement dans le client SLQite en ligne de commande (SQLite 3.11.0).
En supprimant les alias dans les deux requêtes en question ("UPDATE sommaires SET num=...") dans normalize.py, le problème est résolu et j'arrive à la fin de l'initialisation de la base.
Je vois sur plusieurs sites qu'on ne peut pas mettre un alias après un UPDATE (mais seulement après un FROM). Ca marche peut-être dans une version plus récente de SQLite ? (j'utilise celle fournie par apt-get)
Le serveur FTP de la DILA (ftp://echanges.dila.gouv.fr/) ne fonctionne plus correctement, il renvoie des erreurs "550 Failed to change directory" quand le client essaie d'accéder à certains dossiers, dont LEGI.
Similairement aux titres de textes, les numéros d'articles fournis par LEGI ne sont pas propres. Outre les articles mal découpés (#34), on a aussi :
*R111-1
, D180.
ANNEXE 1
, 2 BIS
ETAT A
qui devrait être État A
Annexe A : NORMES D'INSTALLATION
, Annexe II habitats humides
Annexe à l'article A931-11-9 (3e alinéa) Annexe II
CHAPITRE 1 PARAGRAPHE 2 ARTICLE 2
CHAPITRE 1 PARAGRAPHE 1
AOC "Vin de Corse"
, : CA d'Agen
, REFERENTIEL DU METIER D'AUTEUR
Annexe II , TABLEAU RELATIF A L'
qui devrait être Annexe II, Tableau relatif à l'avancement d'échelon des sous-préfets
Dans la base LEGI, parfois, un code référence dans son sommaire (fichier SCTA) un article mais la description de l’article (le fichier ARTI) manque. Cela est par exemple arrivé pour LEGIARTI000033706110 référencé dans la section LEGISCTA000018780362 (code de l’action sociale et des familles LEGITEXT000006074069) dans la version 20170224-204824 de la base LEGI.
Il pourrait être intéressant de détecter ce type d’anomalie : article référencé dans un sommaire mais sa description manque (c’est-à-dire notamment son texte). Cela serait l’inverse des "articles orphelins".
Voir aussi Legilibre/Archeo-Lex#30 : lorsque qu’un article manque, l’export avec Archéo Lex plante à juste titre.
À la nuit du code citoyen, @Pierrot-ongit et moi avons créé un diagramme du schéma de base de données de legi.py, notamment pour mieux visualiser sa structure et l’utiliser dans nos programmes. Un résultat est disponible sur http://lab.seb35.fr/legi.svg (créé par https://github.com/dargosch/sqlite2dot).
On a cherché quelque temps avant de trouver un outil qui faisait le job, avec la difficulté supplémentaire que le schéma SQLite n’est pas compatible avec MySQL.
Où peux-t-on stocker de façon pérenne ce résultat ? Dans un sous-dossier /doc de legi.py ? Dans un wiki ?
Pour mettre à jour ce diagramme, il suffit quasiment d’exécuter sqlite2dot (avec tclsh comme indiqué dans le README) puis dot (GraphViz). À noter que dot ne comprenait pas une ligne du résultat de sqlite2dot, je l’ai retiré mais ça reste un problème mineur.
Not that you need it to do what you're doing here, but in case you want to help build another interesting platform while working on your own effort :)
https://github.com/openaustralia/morph
https://morph.io/
It's a relaunch of what wikiscraper classic was -- open scrapers from github repos, which regularly spin up containers and scrape sites, making the results available via API.
But it's not quite at the place where scraperwiki was when it shut down. For instance, when you call the API, you need to pass manual sql queries, whereas wikiscraper offered an API that worked a little more as expected. But it's still a new project.
All the best @Changaco!
J'ai installé legi.py sur un mac et il a fallu rusé un peu. En attendant, une PR de mise à jour du README voici les contournements.
brew install hunspell
installe une version qui n'est pas compatible en l'état avec pyhunspell. L'auteur de cette librairie n'a pas l'air très préoccupé par la situation : pyhunspell/pyhunspell#67 (comment).
Pour ma part, je l'ai installé avec python setup.py install
après avoir modifié setup.py
de cette façon :
diff --git a/setup.py b/setup.py
index 80a4e55..84dad87 100755
--- a/setup.py
+++ b/setup.py
@@ -35,8 +35,8 @@ if platform.system() == "Windows":
main_module_kwargs['extra_compile_args'] = ['/MT']
elif platform.system() == "Darwin":
main_module_kwargs['define_macros'] = [('_LINUX', None)]
- main_module_kwargs['libraries'] = ['hunspell']
- main_module_kwargs['include_dirs'] = '/usr/local/Cellar/hunspell/1.6.2/include/hunspell',
+ main_module_kwargs['libraries'] = ['hunspell-1.7']
+ main_module_kwargs['include_dirs'] = '/usr/local/Cellar/hunspell/1.7.0_2/include/hunspell',
main_module_kwargs['extra_compile_args'] = ['-Wall']
else:
main_module_kwargs['define_macros'] = [('_LINUX', None)]
Peut être que cela fonctionnerait aussi en installant la version 1.6.2
via l'historique de brew.
Je n'ai pas regardé comme installer simplement le dico fr_FR
. Il y a pas de paquet prévu à cette effet.
Je viens de passer deux semaines à améliorer legi.py, voici un résumé des changements :
legi
plutôt qu'en scripts séparésEnfin, il y a désormais une page publique montrant les anomalies détectées dans LEGI : http://anomalies.legilibre.fr/. Le code qui la génère est dans le nouveau dossier cron/ du dépôt.
Je propose d'abandonner le style de build setup.py
et de passer à pyproject.toml
, qui est définit par la PEP 518 et la PEP 517. L'objectif est de simplifier la procédure d'installation d'un environnement de développement, et de passer sur un système que la plupart des outils de développeur (flake8, black, pylint, pytest, etc.) supportent désormais. J'éspère que ça augmentera l'attrait pour le projet.
Il reste à choisir un système de build entre les deux gros "compétiteurs" que sont Poetry et flit.
Les deux systèmes répondent largement au "besoin" de Legi.py. flit est développé par la PyPA ce qui est rassurant, cependant je trouve Poetry bien plus simple à utiliser (grace à sa gestion automatique des environnement virtuels, qui marche rudement bien). Quoi qu'il en soit, je préfère que tu fasses le choix @Changaco.
Certains textes présents dans LEGI n'ont pas été découpés correctement. Par exemple un arrêté de 2015 contient un article "28 à 30".
Bonjour,
Je me permets de remonter un petit souci, qui me semble-t-il vient de la conversion dans SQLite.
Article 1221-18 dans le code du travail
Freemium_legi_global_20180706-113123.tar.gz
(dans legi/global/code_et_TNC_en_vigueur/code_en_vigueur/LEGI/TEXT/00/00/06/07/20/LEGITEXT000006072050/article/LEGI/ARTI/00/00/37/06/49/LEGIARTI000037064963.xml
)Dans legi.sqlite :
select * from articles where id="LEGIARTI000037064963"
:select * from
sommaireswhere
parent= 'LEGISCTA000006195589' and
debut <= '2018-12-06' and (
fin> '2018-12-06' or
fin= '2018-12-06' or
etat= 'VIGUEUR') order by
position asc
.Aujourd’hui, j’ai assisté à un colloque sur la révision constitutionnelle de 2008 qui a, entre autres, vu l’apparition de la QPC. J’ai donc logiquement adapté (rapidement) legi.py à la base CONSTIT.
Pour information, il y a eu (jusqu’au 14 mars 2018), et sauf erreur de programmation (possible quoique les résultats semblent cohérents), 601 QPC au rythme de 70 à 100 par an depuis 2010, avec comme résultats : 306 conformité, 79 non-conformité, 76 conformité avec réserves, 37 non conformité totale + effet différé, puis de nombreux autres statuts.
Cette issue (ambitieuse) se propose de modifier en profondeur legi.py pour que ça puisse être adapté relativement facilement à d’autres bases (il y en a désormais une vingtaine fournies par la DILA). Chaque base a une structure propre même si une structure commune peut être dégagée. En premier inventaire (et pour ce que j’en ai étudié), les structures communes sont :
Et, sans être exhaustif, les différences sont :
Dans mon idée, les similitudes pourraient être mises en commun dans des fonctions/classes/modules avec une portée limitée à leur fonctionnalité, et les différences pourraient être soit des fichiers de configuration/description soit des classes enfants d’autres classes plus génériques s’il y a des différences qui ne peuvent pas être décrites simplement dans des fichiers de configuration et doivent avoir un aspect programmatique.
Éventuellement, pour être plus ambitieux et générique encore, mais ça sort du champ de la légistique numérique pour entrer dans le champ de l’informatique, il pourrait être créé une librairie qui prend un fichier XML ainsi qu’une table de correspondance XML -> SQL (ou NoSQL au choix) et transfère les données depuis le fichier XML vers la base SQL/NoSQL. Une telle librairie pourrait être un composant d’une librairie legi.py comme décrite ci-dessus (elle ne gèrerait pas par exemple la gestion des fichiers et des dossiers des bases juridiques).
Bonjour, si ça peut servir à quelqu'un j'ai crée un Dockerfile qui permet de lancer directement legi.py
sans avoir à installer les dépendances sur son système : https://github.com/revolunet/legi.py-docker
Bonjour,
J'ai fait une première approche laborieuse de la base LEGI avec basex et des requêtes XQuery, et là je découvre votre projet, j'essaie de suivre les premiers pas pour explorer votre approche.
Je teste sous Centos 7 avec Python 2.7 et j'ai une erreur d'exécution dans la phase de construction de la base. Je trouve cela plutôt étrange, l'erreur provient probablement d'ailleurs.
Si vous avez une piste pour contourner ce problème, je suis preneur ! Merci.
python -m legi.tar2sqlite legi.sqlite ./tarballs
Traceback (most recent call last):
File "/usr/lib64/python2.7/runpy.py", line 162, in _run_module_as_main
"main", fname, loader, pkg_name)
File "/usr/lib64/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/home/develie/LEGI/legi.py/legi/tar2sqlite.py", line 556, in
main()
File "/home/develie/LEGI/legi.py/legi/tar2sqlite.py", line 481, in main
db = connect_db(args.db, pragmas=args.pragma)
File "legi/utils.py", line 101, in connect_db
db.executescript(f.read())
sqlite3.OperationalError: near "WHERE": syntax error
Pour info :
python --version
Python 2.7.5
sudo pip install -r requirements.txt
Requirement already satisfied: libarchive-c in /usr/lib/python2.7/site-packages (from -r requirements.txt (line 1)) (2.8)
Requirement already satisfied: lxml in /usr/lib64/python2.7/site-packages (from -r requirements.txt (line 2)) (4.2.5)
Requirement already satisfied: tqdm in /usr/lib/python2.7/site-packages (from -r requirements.txt (line 3)) (4.28.1)
sudo pip install libarchive
Requirement already satisfied: libarchive in /usr/lib/python2.7/site-packages (0.4.6)
Requirement already satisfied: nose in /usr/lib/python2.7/site-packages (from libarchive) (1.3.7)
Bonjour à toute l'équipe,
Pourquoi avez-vous utilisé les couleurs de l'Italie pur votre logo ?
– Laurent LAPORTE.
Je trouve qu’il serait judicieux de donner un accès public à la base SQLite mise à jour quotidiennement afin que les gens qui ne font pas tourner legi.py quotidiennement aient accès aux données. (À ma connaissance, il n’y a que 2 déploiements mis à jour quotidiennement, ceux de anomalies.legilibre.fr et archeo-lex.fr).
Dans l’idée, ça serait un portail un peu comme https://query.wikidata.org qui donne accès aux données de Wikidata moyennant le fait qu’il faut connaître SPARQL. Afin d’atteindre rapidement cet objectif à peu de frais, il y a des logiciels comme PHPLiteAdmin et quelques autres qui s’appelle un peu pareils (Wikipédia a même un article même si deux tels logiciels sont inactifs).
J’ai un peu testé celui actif, PHPLiteAdmin : il est rudimentaire mais fait le job. De toutes façons, il faut être un peu technicien et connaître le SQL, donc ce type de public saura globalement se débrouiller même si l’interface n’est pas des plus abouties.
Qu’en dites-vous ? @Changaco @fgallaire
Je peux m’occuper de ce déploiement, et faire en sorte que les données ne soient pas modifiables via le web. Aussi, il faudrait trouver un nom de sous-domaine : sqlite.legilibre.fr ?
Les noms de fichiers ont changé un peu sur https://echanges.dila.gouv.fr/OPENDATA/LEGI/ : le mot 'legi' (pour les mises à jour quotidiennes) est désormais en majuscules 'LEGI'. Ça doit dater du 12-13 juin, date à laquelle http://anomalies.legilibre.fr/ s’est arrêté.
En conséquence, les fichiers postérieurs à cette date de changement ne sont plus pris en compte.
Bonjour,
Dans l'étape de génération de la BDD SQLite, j'obtiens les erreurs suivantes. Pourriez-vous m'indiquer la source de l'erreur et les dépendances qui manqueraient à mon installation?
(ml_data) bash-3.2$ python -m legi.tar2sqlite legi.sqlite ./tarballs
read format "cab" is not supported
read format "rar" is not supported
read format "lha" is not supported
read format "7zip" is not supported
read format "warc" is not supported
read filter "rpm" is not supported
read filter "lzip" is not supported
read filter "gzip" is not supported
read filter "uu" is not supported
read filter "grzip" is not supported
read filter "none" is not supported
read filter "compress" is not supported
read filter "lzop" is not supported
read filter "lrzip" is not supported
read filter "lzma" is not supported
read filter "lz4" is not supported
read filter "bzip2" is not supported
read filter "xz" is not supported
read filter "all" is not supported
Traceback (most recent call last):
File "/Users/mouradlounas/anaconda2/envs/ml_data/lib/python3.6/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/Users/mouradlounas/anaconda2/envs/ml_data/lib/python3.6/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/Users/mouradlounas/legi.py/legi/tar2sqlite.py", line 13, in <module>
import libarchive
File "/Users/mouradlounas/anaconda2/envs/ml_data/lib/python3.6/site-packages/libarchive/__init__.py", line 1, in <module>
from .entry import ArchiveEntry
File "/Users/mouradlounas/anaconda2/envs/ml_data/lib/python3.6/site-packages/libarchive/entry.py", line 6, in <module>
from . import ffi
File "/Users/mouradlounas/anaconda2/envs/ml_data/lib/python3.6/site-packages/libarchive/ffi.py", line 184, in <module>
c_int, check_int)
File "/Users/mouradlounas/anaconda2/envs/ml_data/lib/python3.6/site-packages/libarchive/ffi.py", line 95, in ffi
f = getattr(libarchive, 'archive_'+name)
File "/Users/mouradlounas/anaconda2/envs/ml_data/lib/python3.6/ctypes/__init__.py", line 361, in __getattr__
func = self.__getitem__(name)
File "/Users/mouradlounas/anaconda2/envs/ml_data/lib/python3.6/ctypes/__init__.py", line 366, in __getitem__
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: dlsym(0x7f88c9d47550, archive_read_open_filename_w): symbol not found_
Par avance merci,
Mourad.
Pour info je prévois de supprimer le support de python 2.7 dans legi.py d'ici deux ans maximum.
Bonjour,
est-il prévu de mettre legi sous une autre base de donnée que SDLite
En travaillant sur la détection des liens (#4) je me suis rendu compte que LEGI contient des soft hyphens dont il faudrait se débarrasser.
Bonjour,
j'essaie de faire tourner legy.py sur une machine Centos 7.
Ma première tentative avec python 2.7 n'ayant pas abouti, je viens de réessayer avec :
sqlite3
SQLite version 3.26.0 2018-12-01 12:34:55
python36 --version
Python 3.6.6
Mais j'ai des messages d'erreur.
A noter que le téléchargement des tar.gz fonctionne bien.
A la première exécution j'ai une erreur. Un fichier legi.sqlite a bien été créé.
A la seconde exécution (et les suivantes) j'ai une autre erreur.
Voici les erreurs, si nous avez une piste ... merci d'avance.
python36 -m legi.tar2sqlite legi.sqlite ./tarballs
read format "warc" is not supported
read filter "lz4" is not supported
write format "warc" is not supported
write filter "lz4" is not supported
Traceback (most recent call last):
File "/home/develie/LEGI/legi.py/legi/utils.py", line 90, in connect_db
db.run("SELECT 1 FROM db_meta LIMIT 1")
sqlite3.OperationalError: no such table: db_meta
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib64/python3.6/runpy.py", line 193, in _run_module_as_main
"main", mod_spec)
File "/usr/lib64/python3.6/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/home/develie/LEGI/legi.py/legi/tar2sqlite.py", line 552, in
main()
File "/home/develie/LEGI/legi.py/legi/tar2sqlite.py", line 477, in main
db = connect_db(args.db, pragmas=args.pragma)
File "/home/develie/LEGI/legi.py/legi/utils.py", line 93, in connect_db
db.executescript(f.read())
sqlite3.OperationalError: near "WHERE": syntax error
-rw-r--r-- 1 develie develie 25600 9 janv. 18:00 legi.sqlite
Nouvelle tentative (second appel):
[develie@ip80 legi.py]$ python36 -m legi.tar2sqlite legi.sqlite ./tarballs
read format "warc" is not supported
read filter "lz4" is not supported
write format "warc" is not supported
write filter "lz4" is not supported
last_update is None
Processing Freemium_legi_global_20180706-113123.tar.gz...
825014it [01:26, 11335.56it/s]Traceback (most recent call last):
File "/usr/lib64/python3.6/runpy.py", line 193, in _run_module_as_main
"main", mod_spec)
File "/usr/lib64/python3.6/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/home/develie/LEGI/legi.py/legi/tar2sqlite.py", line 552, in
main()
File "/home/develie/LEGI/legi.py/legi/tar2sqlite.py", line 526, in main
process_archive(db, args.directory + '/' + archive_name, not args.skip_links)
File "/home/develie/LEGI/legi.py/legi/tar2sqlite.py", line 267, in process_archive
}, replace=True)
File "/home/develie/LEGI/legi.py/legi/utils.py", line 117, in insert
""".format(or_clause, table, keys, placeholders), values)
sqlite3.OperationalError: no such table: duplicate_files
Exception ignored in: <bound method tqdm.del of 825014it [01:27, 11335.56it/s]>
Traceback (most recent call last):
File "/usr/local/lib/python3.6/site-packages/tqdm/_tqdm.py", line 931, in del
self.close()
File "/usr/local/lib/python3.6/site-packages/tqdm/_tqdm.py", line 1133, in close
self._decr_instances(self)
File "/usr/local/lib/python3.6/site-packages/tqdm/_tqdm.py", line 496, in _decr_instances
cls.monitor.exit()
File "/usr/local/lib/python3.6/site-packages/tqdm/_monitor.py", line 52, in exit
self.join()
File "/usr/lib64/python3.6/threading.py", line 1053, in join
raise RuntimeError("cannot join current thread")
RuntimeError: cannot join current thread
J'ai toujours des problèmes de connectivité et de lenteur avec le FTP de la DILA. Je viens de découvrir qu'ils fournissent aussi un accès HTTPS qui semble être ISO avec le contenu du ftp : https://echanges.dila.gouv.fr/OPENDATA/
C'est la DILA elle même qui a annoncé cet accès en commentaire sur la page de KALI sur data.gouv.fr : https://www.data.gouv.fr/fr/datasets/kali-conventions-collectives-nationales/#discussion-5942a79b88ee3827aea4c00a
Est-ce que vous seriez ouverts à ce que je remplace le téléchargement depuis le FTP par un téléchargement depuis le HTTPS ? J'ai de bien meilleures performances et surtout beaucoup moins d'échecs.
À la suite de #30, il est indiqué que la version minimum de Python est 3.6 ou 3.7. J’ai sur ma machine Python 3.4 qui génère une erreur minime dans legi/french.py
dans la variable short_ordinals_p
où la synaxe (?-i:)
a été introduite dans Python 3.6.
Étant donné que ça semble être la seule limitation et qu’il y a moyen de se passer de cette syntaxe en utilisant un flag dans short_ordinal_re
, je propose d’autoriser le Python 3.4.
Je peux m’occuper de faire la requête d’intégration (pull request) en changeant cette syntaxe et en ajoutant l’intégration continue pour Python 3.4.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.