Coder Social home page Coder Social logo

legi.py's Introduction

legi.py est un module python qui peut :

  • créer une base de données SQLite à partir des archives de la base LEGI
  • mettre à jour automatiquement et incrémentalement cette BDD
  • normaliser les titres des textes
  • connecter les différentes versions d'un texte entre elles
  • analyser les données pour détecter les anomalies

Avoir les lois françaises dans une base SQL permet aussi d'autres choses qui ne sont pas encore implémentées directement dans legi.py, par exemple générer des statistiques sur l'activité législative, trouver le texte le plus ancien encore en vigueur, etc.

Build Status

Installation

legi.py a besoin de libarchive et hunspell. L'installation de ces dépendances varie selon le système d'exploitation :

  • Arch Linux : pacman -S --needed libarchive hunspell hunspell-fr
  • Mac OS X : la version de libarchive inclue dans Mac OS X est obsolète, vous pouvez utiliser Homebrew pour installer une version récente en exécutant brew install libarchive, puis indiquer au module Python qu'il doit utiliser cette version en ajoutant une variable d'environnement : export LIBARCHIVE="$(find "$(brew --cellar libarchive)" -name libarchive.13.dylib | sort | tail -1)" (cette commande peut être ajoutée au fichier d'initialisation de votre shell, typiquement ~/.bashrc ou ~/.zshrc)
  • Ubuntu : sudo apt-get install libarchive13 hunspell hunspell-fr libhunspell-dev

Une fois ces dépendances système installées, vous pouvez cloner le dépôt et utiliser pip pour installer les modules python nécessaires :

git clone https://github.com/Legilibre/legi.py.git
cd legi.py
python -m ensurepip
pip install -r requirements.txt

legi.py et les modules dont il dépend sont compatibles avec python 3.7, 3.8 et 3.9, les versions antérieurs de python peuvent générer des erreurs.

legi.py peut être utilisé comme dépendance d'un autre projet, il est disponible sous forme de paquet dans PyPI.

Création et maintenance de la BDD

La première étape est de télécharger les archives LEGI depuis ftp://echanges.dila.gouv.fr/LEGI/ :

python -m legi.download ./tarballs

La deuxième étape est la conversion des archives en base SQLite :

python -m legi.tar2sqlite legi.sqlite ./tarballs [--raw]

Cette opération peut prendre de quelques minutes à plusieurs heures selon votre machine et le nombre d'archives. Les deux caractéristiques importantes de votre machine sont: le disque dur (un SSD est beaucoup plus rapide), et le processeur (notamment sa fréquence, le nombre de cœurs importe peu car le travail n'est pas parallèle).

La taille du fichier SQLite créé est environ 4Go (en janvier 2020).

L'option --raw désactive le nettoyage des données, ajoutez-la si vous avez besoin des données LEGI brutes.

tar2sqlite permet aussi de maintenir votre base de données à jour, il saute automatiquement les archives qu'il a déjà traité. En général la DILA publie une nouvelle archive à la fin de chaque jour ouvré, vous pouvez donc programmer votre machine pour mettre à jour la BDD du mardi au samedi pendant la nuit, par exemple avec cron :

0 1 * * 2-6 ID=legi chronic ~/chemin/vers/legi.py/cron/cron.sh

(chronic fait partie des moreutils.)

Fonctionnalités

Normalisation des titres et numéros

Le module normalize nettoie les titres et numéros des textes, des sections et des articles afin qu'ils soient plus « standards ».

Factorisation des textes

La "factorisation" connecte entre elles les différentes version d'un même texte. La base LEGI n'a pas d'identifiant qui remplisse réellement ce rôle.

Nettoyage des contenus

Le module html permet de nettoyer les contenus des textes. Il supprime :

  • les espaces redondantes (whitespace collapse), sauf à l'intérieur des <pre>
  • les attributs inutiles, par exemple id et dir="ltr"
  • les éléments inutiles, par exemple un <span> sans attributs
  • les éléments vides, sauf <td> et <th>

En janvier 2020 il détecte 93 millions de caractères inutiles dans LEGI.

Cette fonctionnalité n'est pas activée par défaut car elle est « destructrice » et récente. Vous pouvez nettoyer tout l'HTML d'une base en exécutant la commande python -m legi.html clean legi.sqlite (les modifications ne sont enregistrées que si vous entrez y à la fin).

Détection d'anomalies

Le module anomalies est conçu pour détecter les incohérences dans les données afin de les signaler à la DILA. Le résultat est visible sur anomalies.legilibre.fr. (cron/anomalies-cron.sh est le script qui génère ce mini-site.)

Pour détecter les anomalies actuellement présentes dans la base :

python -m legi.anomalies legi.sqlite

Contribuer

Les Pull Requests sont bienvenues, n'hésitez pas à ouvrir une discussion avant de commencer le travail, ça permet une meilleure coopération et coordination. Vous pouvez aussi vous présenter dans le salon.

Tests

legi.py utilise Tox pour tester le code sur plusieurs versions de Python. Installez-le si nécessaire puis lancez la commande tox dans le dossier qui contient votre copie du dépôt legi.py.

Licence

CC0 Public Domain Dedication

Historique du projet

Fin juin 2014 la base de données LEGI contenant les lois françaises a été libérée en Open Data. J'ai immédiatement commencé le travail pour la convertir dans d'autres formats. Malheureusement, distrait par d'autres choses à faire et un peu découragé par la structure médiocre des données j'ai fini par laisser le projet de côté.

En 2015 j'ai réouvert, nettoyé et publié mon code. J'ai ensuite été très occupé à créer Liberapay.

Fin 2016 j'ai à nouveau travaillé sur legi.py. Le projet progressa fortement, anomalies.legilibre.fr fut créé.

En février 2017 la version 0.1 est publiée.

legi.py's People

Contributors

adipasquale avatar changaco avatar fgallaire avatar lel-amri avatar mdamien avatar seb35 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

legi.py's Issues

Nouveau type d’anomalie : date de début de vigueur avant la date de début de vigueur de la section

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 :

  1. dans la table 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,
  2. dans la table 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 :-).

Liens entre articles

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.)

Installation sur OS X (catalina)

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.

hunspell

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.

Échec du téléchargement

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.

TypeError factorize(db)

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 :)

Accès public à la base SQLite legi.py

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 ?

libarchive Apple Silicon M1

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

Nettoyage des numéros d'articles

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 :

  • des numéros entourés de caractères inutiles (espaces, points, astérisques), par exemple *R111-1, D180.
  • des numéros préfixés du mot "ARTICLE" qui fait évidemment doublon
  • des numéros en majuscules, par exemple ANNEXE 1, 2 BIS
  • des numéros en majuscule et sans accents, par exemple ETAT A qui devrait être État A
  • des numéros qui contiennent un sous-titre, par exemple Annexe A : NORMES D'INSTALLATION, Annexe II habitats humides
  • des numéros d'annexes préfixés d'une référence à un article, par exemple Annexe à l'article A931-11-9 (3e alinéa) Annexe II
  • des numéros préfixés de la position de l'article dans le texte, par exemple CHAPITRE 1 PARAGRAPHE 2 ARTICLE 2
  • des "numéros" qui ne sont que la position de l'article dans le texte, par exemple CHAPITRE 1 PARAGRAPHE 1
  • des "numéros" qui sont en réalité des titres, parfois en majuscules et sans accents, par exemple AOC "Vin de Corse", : CA d'Agen, REFERENTIEL DU METIER D'AUTEUR
  • des "numéros" qui contiennent un sous-titre tronqué et qui ne peuvent être corrigés que manuellement en consultant le facsimilé du texte original, par exemple Annexe II , TABLEAU RELATIF A L' qui devrait être Annexe II, Tableau relatif à l'avancement d'échelon des sous-préfets

Application de la PEP 518 et de la PEP 517

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.

Abstraire legi.py pour gérer d’autres bases juridiques

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 :

  • utilisation du XML
  • utilisation d’ID
  • rangement des sous-dossiers par ID
  • mécanisme de mise à jour : Freemium initial + màj légères avec nouvelle version du fichier et liste de suppression (hormis protocole du gouvernement)
  • métadonnées de liens intra-base ou inter-bases

Et, sans être exhaustif, les différences sont :

  • LEGI : sous-dossiers initiaux "code_et_TNC_(en|non)_vigueur/(code|TNC)_en_vigueur"
  • LEGI : utilisation de CID pour regrouper l’appartenance à un même texte dans différentes vigueurs regroupés dans des sous-sous-dossiers
  • KALI, JORF : sous-dossiers initiaux "conteneur"
  • JORFSIMPLE : fichier JORFCONT similaire à celui de JORF dossier "conteneur" mais rangé à côté des JORFTEXT dans un sous-sous-dossier JORFCONT
  • JADE : sous-dossiers initiaux "inedit" vs "publie"
  • INCA : top dossier initial "juri" (puis "inca/global" selon l’arborescence classique)
  • INCA : sous-dossiers initiaux "criminelle" vs "sociale"
  • LEGI : sous-dossiers avec les articles
  • schéma XML propres à chaque base

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).

libarchive

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,

SQLite syntax error at runtime

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)

Erreur lors de la génération de la BDD SQLite

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.

Des tabulations qui trainent dans le code de la sécurité sociale

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é".

image

J'ai vu un bug similaire dans l'article D221-29 d'ailleurs.

image

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:

https://github.com/Legilibre/Archeo-Lex/blob/044b6ac726571e38a4770d4392c9e8edef0088cb/marcheolex/exports/Markdown.py#L145

Du style texte = re.sub( r'\s+', ' ', texte ).

Cette situation est-elle une anomalie dans les données ?

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

Échec de mise à jour

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

article présent dans LEGI, mais absent dans le sqlite

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

Dans legi.sqlite :

  • je ne le retrouve pas dans la table des articles : select * from articles where id="LEGIARTI000037064963" :
  • il est pourtant bien présent dans le sommaire : select * from sommaireswhereparent= 'LEGISCTA000006195589' anddebut <= '2018-12-06' and (fin> '2018-12-06' orfin= '2018-12-06' oretat= 'VIGUEUR') order byposition asc.

capture d ecran 2018-12-06 a 15 04 13

Python 3.4

À 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.

Échec de mise à jour 20190821

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'

Mettre à disposition les articles équivalents LEGI ↔ JORF

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

Soft hyphens (SHY)

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.

Messages d'erreur à l'éxécution sqlite3.OperationalError: near "WHERE": syntax error

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

Drapeau "italien" ? :O

Bonjour à toute l'équipe,

Pourquoi avez-vous utilisé les couleurs de l'Italie pur votre logo ?

– Laurent LAPORTE.

Ajouter un diagramme du schéma de BDD

À 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.

Erreurs à l'initialisation de la base

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)

Nouveau type d’anomalie : article référencé mais manquant

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.

Problème avec la mise à jour incrémentale 20180207

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

Investigate morph.io

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!

Échec de mise à jour incrémentale

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

reprise de téléchargment (resume)

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 👌

Télécharger les dumps en HTTPS plutôt qu'en FTP

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.

Python 2

Pour info je prévois de supprimer le support de python 2.7 dans legi.py d'ici deux ans maximum.

Rapport d'avancement du projet

Je viens de passer deux semaines à améliorer legi.py, voici un résumé des changements :

  • schéma SQL : améliorations et regroupement dans un fichier dédié (schema.sql)
  • correction de la "factorisation" des textes
  • anomalies : détection des articles et sections qui n'apparaissent dans aucun texte (orphelins)
  • anomalies : meilleur gestion des dates permettant une détection rétroactive des anomalies et diminuant les erreurs transitoires
  • tar2sqlite prend désormais comme argument un dossier et détecte dans celui-ci les archives qu'il n'a pas encore traité
  • le projet est désormais structuré autour d'un module nommé legi plutôt qu'en scripts séparés
  • il peut être empaqueté (https://pypi.python.org/pypi/legi est réservé mais il n'y a pas encore de première version publiée)
  • test du code : tox, flake8, et Travis CI sont opérationnels

Enfin, 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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.