'3.12.6 | packaged by conda-forge | (main, Sep 30 2024, 18:08:52) [GCC 13.3.0]'
1 Un cadavre exquis pour découvrir le travail collaboratif
Jusqu’à présent, nous avons découvert les vertus de Git
dans un projet
individuel. Nous allons maintenant aller plus loin dans un projet
collectif. Pour rappel, dans le chapitre précédent nous avons évoqué les concepts natifs de Git
que sont dépôts local et distant (remote
), l’opération de clone
, staging area, commit
, push
, pull
, les branches. Nous avons aussi évoqué certains concepts liés à la forge Github
que sont l’authentification et les issues.
Maintenant, nous allons évoquer les enjeux liés au travail collaboratif, ce qui nous amènera, notamment, à évoquer les enjeux de la gestion de conflits.
2 Le workflow adopté
Nous allons adopter le mode de travail le plus simple, le Github flow. Nous l’avons déjà adopté lors du dernier exercice du chapitre précédent, consacré à l’utilisation des branches.
Le Github flow correspond à cette forme caractéristique d’arbre:
- La branche
main
constitue le tronc - Les branches partent de
main
et divergent - Lorsque les modifications aboutissent, elles sont intégrées à
main
; la branche en question disparaît :
Des workflows plus complexes existent pour les projets de grande envergure.
Il existe des workflows plus complexes, notamment le Git Flow
que j’utilise
pour développer ce cours. Ce tutoriel, très bien fait,
illustre avec un graphique la complexité accrue de ce flow :
Cette fois, une branche intermédiaire, par exemple une branche development
,
intègre des modifications à tester avant de les intégrer dans la version
officielle (main
).
Vous pourrez trouvez des dizaines d’articles et d’ouvrages sur ce sujet dont chacun prétend avoir trouvé la meilleure organisation du travail (Git flow, GitHub flow, GitLab flow…). Ne lisez pas trop ces livres et articles sinon vous serez perdus (un peu comme avec les magazines destinés aux jeunes parents…).
La méthode de travail la plus simple est le Github flow qu’on vous a proposé d’adopter. L’arborescence est reconnaissable : des branches divergent et reviennent systématiquement vers main
.
Pour des projets plus complexes dans des équipes développant des applications, on pourra utiliser d’autres méthodes de travail, notamment le Git flow
. Il n’existe pas de règles universelles pour déterminer la méthode de travail ; l’important c’est, avant tout, de se mettre d’accord sur des règles communes de travail avec votre équipe.
2.1 Les conflits
Au cours du dernier exercice du chapitre précédent, nous avons, sans vraiment l’expliquer, découvert le principe du merge (ou fusion, en Français). Les fusions de versions consistent à réconcilier deux versions d’un code. Cela peut se faire en privilégiant l’une sur l’autre ou bien en choisissant, dans les passages qui divergent, parfois l’une et parfois l’autre. On parle de conflits pour désigner une situation où un même fichier présente deux versions différentes qui doivent être réconciliées.
Git
simplifie énormément la gestion de conflits, c’est l’une des raisons de son succès. Si vous avez déjà partagé du code par mail en équipe, vous devez savoir que réconcilier des versions est extrêmement fastidieux : il faut, plus ou moins ligne à ligne, vérifier que la version que vous avez reçu par mail ne diffère pas de la vôtre, que vous avez fait évoluer en parallèle. Grâce au suivi fin de l’évolution d’un fichier que permet Git
, cette gestion de conflits sera facilitée. Il faudra tout de même privilégier une version sur l’autre mais cela sera plus rapide et plus fiable.
Si Git
offre des fonctionnalités intéressantes, pour la gestion des conflits, ce n’est néanmoins pas une excuse pour être désorganisé. Comme nous allons le voir dans les prochains exercices, on a certes des chapitres
Lors du chapitre précédent, nous avons fait un merge de notre branche issue-1
vers main
, notre branche principale. Nous sommes passés par l’interface de Github
pour faire cela. Il s’agit de la méthode recommandée pour les merges vers main
. Cela permet de garder une trace explicite de ceux-ci (par exemple ici), sans avoir à chercher dans l’arborescence, parfois complexe, d’un projet.
La bonne pratique veut qu’on fasse un squash commit
pour éviter une inflation du nombre de commits dans main
: les branches ont vocation à proposer une multitude de petits commits, les modifications dans main
doivent être simples à tracer d’où le fait de modifier des petits bouts de code.
Comme on l’a fait dans un exercice précédent, il est très pratique d’ajouter dans le corps du message close #xx
où xx
est le numéro d’une issue associée à la pull request
. Lorsque la pull request
sera fusionnée, l’issue sera automatiquement fermée et un lien sera créé entre l’issue
et la pull request
. Cela vous permettra de comprendre, plusieurs mois ou années plus tard comment et pourquoi telle ou telle fonctionnalité a été implémentée.
En revanche, l’intégration des dernières modifications de main
vers une branche se fait en local. Si votre branche est en conflit, le conflit doit être résolu dans la branche et pas dans main.
main
doit toujours rester propre.
2.2 Divergence d’historique: les différentes situations
2.2.1 Cas simple
Imaginons deux personnes qui collaborent sur un projet, Alice et Bob. Bob a mis de côté le projet quelques jours. Il veut récupérer les avancées faites par Alice pendant cette période. Celle-ci a fait évoluer le projet, supposons avec un seul commit puisque cela ne change rien.
L’historique de Bob est cohérent avec celui sur Github
, il lui manque juste le dernier commit en bleu (Figure 2.1). Il suffit donc à Bob de récupérer ce commit en local avant de commencer à éditer ses fichiers.
Ce type de fusion est un fast-forward merge. Le commit distant est rajouté à l’historique local, sans difficulté. Le dépôt local est à nouveau à jour avec le dépôt distant.
Il s’agit du merge idéal car celui-ci peut être automatisé, il n’y a aucun risque d’écraser des modifications faites par Bob par celles d’Alice. Une organisation d’équipe adéquate permettra de s’assurer que la plupart des merges seront de ce type.
2.2.2 Cas plus compliqué
Maintenant, imaginons le cas plus compliqué où Bob avait fait évoluer son code en parallèle, sans récupérer les modifications d’Alice avant de revenir sur le projet.
Son historique local diverge donc de l’historique distant:
Les derniers commits ne sont pas les mêmes. Git
ne peut pas résoudre de lui-même la divergence. C’est à Bob de trancher sur la version qu’il préfère. Deux stratégies pour réconcilier les historiques sont accessibles:
- Le merge ;
- Le rebase.
La première méthode, la plus simple, est le merge.
Le rapatriement des modifications d’Alice dans l’historique de Bob crée un premier commit de merge. Les fichiers en question présenteront alors des balises permettant d’identifier la divergence de version et la source de celle-ci. Dans le fichier brut, cela donnera
import pandas as pd
<<<<<<< main
= pd.read_csv("source.csv")
toto =======
= pd.read_csv("source.csv", sep = ";")
toto >>>>>>> zyx911fhjehzafoldfkjknvjnvjnj;
2) toto.head(
VSCode
, grâce à l’extension Git
, propose une visualisation native de ce bout de code et propose, en clique-bouton, différentes manières de réconcilier les versions. Il est bien sûr toujours possible d’éditer ces fichiers : il suffit de supprimer les balises et modifier les lignes en question.
Une fois les versions réconciliées, il ne reste plus qu’à faire un nouveau commit. Cette histoire réconcilie les versions d’Alice et Bob. L’inconvénient est qu’elle rend l’historique non linéaire (voir la documentation d’Atlassian pour plus de détails) mais c’est Git
qui a géré automatiquement ce sujet en créant une branche temporaire. Jusqu’à récemment, ceci était le comportement par défaut de Git
.
Une autre approche est accessible, le rebase. In fine ceci va correspondre à cet historique, propre.
Néanmoins ceci implique des étapes intermédiaires qui consistent à réécrire l’historique, ce qui est déjà une opération avancée. En fait, Git
effectue trois étapes:
- Supprime temporairement le commit local
- Réalise un fast forward merge maintenant que le commit local n’est plus là
- Rajoute le commit local au bout de l’historique
Le commit local a changé d’identité, ce qui explique son nouveau SHA. Cette approche présente l’avantage de garder un historique linéaire. Néanmoins, elle peut avoir des effects de bord et est donc à utiliser avec précaution (plus d’explications dans la documentation de Git
). Quand on débute, et même après, il est recommandé de privilégier la méthode merge. Pour cela, en ligne de commande, il faut taper la commande
git config pull.rebase false
3 Mise en pratique
Cet exercice se fait par groupe de trois ou quatre. Il y aura deux rôles dans ce scénario :
- Une personne aura la responsabilité d’être mainteneur
- Deux à trois personnes seront développeurs.
1️⃣ Le.la mainteneur.e crée un dépôt sur Github
sans cliquer sur l’option Add a README
. Créer un .gitignore
selon le modèle Python
. Il/Elle donne des droits au(x) développeur.euse(s) du projet (Settings > Manage Access > Invite a collaborator
).
2️⃣ Chaque membre du projet, crée une copie locale du projet (un clone). Si vous avez un trou de mémoire, vous pouvez retourner au chapitre précédent pour vérifier la démarche.
3️⃣ Chaque membre du projet crée un fichier avec son nom et son prénom, selon cette structure nom-prenom.md
en évitant les caractères spéciaux. Il écrit dedans trois phrases de son choix sans ponctuation ni majuscules (pour pouvoir effectuer une correction ultérieurement). Enfin, il commit sur le projet par le biais de l’extension visuelle.
En ligne de commande cela donnerait les commandes équivalentes
git add nom-prenom.md
git commit -m "C'est l'histoire de XXXXX"
4️⃣ Chacun essaie d’envoyer (push) ses modifications locales sur le dépôt en passant par les boutons adéquats de l’extension visuelle.
En ligne de commande cela donnerait la commande équivalente
git push origin main
5️⃣ A ce stade, une seule personne (la plus rapide) devrait ne pas avoir rencontré de rejet du push
. C’est normal, avant d’accepter une modification Git
vérifie en premier lieu la cohérence de la branche avec le dépôt distant. Le premier ayant fait un push
a modifié le dépôt commun ; les autres doivent intégrer ces modifications dans leur version locale (pull) avant d’avoir le droit de proposer un changement.
Pour celui/celle/ceux dont le push
a été refusé, il faudra faire un pull. Faire celui-ci en utilisant l’extension graphique de VSCode
.
En ligne de commande cela donnerait la commande équivalente
git pull origin main
pour essayer de ramener les modifications distantes en local. Celui-ci devrait échouer et les options affichées par VSCode ne devraient pas vous permettre de résoudre le problème, seulement de le comprendre. En cliquant sur Show command output
, vous devriez voir s’afficher le message suivant:
and need to specify how to reconcile them.
hint: You have divergent branches
hint: You can do so by running one of the following commands sometime beforenext pull:
hint: your
hint:# merge
hint: git config pull.rebase false # rebase
hint: git config pull.rebase true # fast-forward only
hint: git config pull.ff only
hint:"git config" with "git config --global" to set a default
hint: You can replace for all repositories. You can also pass --rebase, --no-rebase,
hint: preference or --ff-only on the command line to override the configured default per
hint:
hint: invocation. fatal: Need to specify how to reconcile divergent branches.
Dans un terminal ((☰ > Terminal > New Terminal
), copier la règle git config pull.rebase false
qui est recommandée lorsqu’on débute dans Git
(et même quand on est plus à l’aise).
6️⃣ Regarder l’arbre obtenu dans l’interface pour comprendre comment a été intégrée la modification de votre camarade ayant pu faire son push
avant.
Vous remarquerez que les commits de vos camarades sont intégrés tels quels à l’histoire du dépôt.
7️⃣ Faire à nouveau un push. C’est fini pour la 2e personne. La dernière personne doit refaire, à nouveau, les étapes 5 à 7 (dans une équipe de quatre il faudra encore le refaire une fois).
❓ Question : que se serait-il passé si les différents membres du groupe avaient effectué leurs modifications sur un seul et même fichier ?
Le prochain exercice offre une réponse à cette question.
Dans la continuité de l’exercice précédent, chaque personne va travailler sur les fichiers des autres membres de l’équipe.
1️⃣ Les deux ou trois développeurs ajoutent la ponctuation et les majuscules du fichier du premier développeur.
2️⃣ Ils sautent une ligne et ajoutent une phrase (pas tous la même).
3️⃣ Valider les résultats avec un commit et faire un push.
4️⃣ La personne la plus rapide n’a, normalement, rencontré aucune difficulté (elle peut s’arrêter temporairement pour regarder ce qui va se passer chez les voisins). Les autres voient leur push
refusé et doivent faire un pull
.
💥 Il y a conflit, ce qui doit être signalé par un message du type :
-merging XXXXXX
Autoin XXXXXX.md
CONFLICT (content): Merge conflict ; fix conflicts and then commit the result. Automatic merge failed
5️⃣ Etudier le résultat de git status
6️⃣ Si vous ouvrez les fichiers incriminés, vous devriez voir des balises du type
<<<<<<< HEAD
is some content to mess with
this
content to append=======
totally different content to merge later>>>>>>> new_branch_to_merge_later
qui sont mises en forme par VSCode
comme dans la Figure 2.4.
7️⃣ Corriger les fichiers en choisissant, pour chaque bloc, la version qui vous convient grâce aux actions permises par Git (Accept Current Change
…)
Faire un commit avec le titre “Résolution du conflit par XXXX” où XXXX
est votre nom.
8️⃣ Faire un push. Pour la dernière personne, refaire les opérations 4 à 8
Git
permet donc de travailler, en même temps, sur le même fichier et de limiter le nombre de gestes manuels nécessaires pour faire la fusion. Lorsqu’on travaille sur des bouts différents du même fichier, on n’a même pas besoin de faire de modification manuelle, la fusion peut être automatique.
Git
est un outil très puissant. Mais, il ne remplace pas une bonne organisation du travail. Vous l’avez vu, ce mode de travail uniquement sur main
peut être pénible. Les branches prennent tout leur sens dans ce cas.
- 1️⃣ Le.la mainteneur.euse va contribuer directement dans
main
et ne crée pas de branche. Chaque développeur crée une branche, en local nomméecontrib-XXXXX
oùXXXXX
est le prénom. Pour cela, dans l’interface deVSCode
, cliquer sur... > Branch > Create branch
et mettre le nom de la branche dans le menu adéquat
En ligne de commande cela donnerait la commande équivalente
git checkout -b contrib-XXXXX
2️⃣ Chaque membre du groupe crée un fichier README.md
où il écrit une phrase sujet-verbe-complément. Le mainteneur est le seul à ajouter un titre dans le README
(qu’il commit dans main
).
3️⃣ Chacun push le produit de son subconscient sur le dépôt.
4️⃣ Les développeurs.euses ouvrent, chacun, une pull request sur Github
. Le sens à choisir est branche -> main
. Les développeurs.euses donnent un titre explicite à cette pull request.
Le/la mainteneur.euse choisit une des pull request
et la valide avec l’option squash commits
. Vérifier sur la page d’accueil le résultat.
5️⃣ Chaque développeur revient sur main
en cliquant sur ... > Checkout to
et en choisissant main
. Faire un pull.
6️⃣ Revenir sur votre branche et faire ... > Branch > Merge
et choisir main
. Regarder l’arbre obtenu.
7️⃣ L’auteur (si 2 développeurs) ou les deux auteurs (si 3 développeurs) de la pull request
non validée doivent à nouveau répéter les opérations 5 et 6.
8️⃣ Une fois le conflit de version réglé et poussé, le mainteneur valide la pull request
selon la même procédure que précédemment.
9️⃣ Vérifier l’arborescence du dépôt dans Insights > Network
. Votre arbre doit avoir une forme caractéristique de ce qu’on appelle le Github flow
:
Il n’est absolument pas obligatoire que chaque projet collaboratif choisisse ce mode de collaboration. Pour de nombreux projets, où on édite pas le même bout de fichier en même temps, passer directement par main
est suffisant. Le mode ci-dessus est important pour des projets conséquents, où la branche main
se doit d’être irréprochable parce que, par exemple, elle entraîne une série de tests automatisés et le déploiement automatisé d’un livrable. Mais pour des projets plus modestes, il n’est pas indispensable d’aller dans un formalisme extrême. Le bon usage de Git
est un usage pragmatique où celui-ci est utilisé pour ses avantages et où l’organisation du travail s’adapte à ceux-ci.
4 Les enjeux spécifiques liés à l’interaction difficile entre Git
et les notebooks
Le format notebook est très intéressant pour l’expérimentation et la diffusion finale de résultats. Néanmoins, la structure complexe d’un notebook rend compliquée le contrôle de version. En effet, l’ouverture dans un éditeur adapté (Jupyter
ou VSCode
) offre une mise en forme qui ne correspond pas à la structure brute du fichier, tel qu’il est stocké sur le disque. En arrière plan, les notebooks sont des JSON qui embarquent de nombreux éléments: code, résultats d’exécution, métadonnées annexes… Le suivi fin des modifications du fichier permis par Git
est compliqué sur un fichier ayant une telle structure. L’objectif de cet exercice est d’illustrer ces enjeux et évoque quelques solutions possibles.
Cet exercice se fait toujours en équipe. Lorsqu’il est demandé de faire un commit, lui donner un nom signifiant pour s’y retrouver facilement quand il est demandé de regarder l’historique. Ne pas faire de push ou pull avant d’en arriver à la partie où cela est demandé.
- Tous les membres de l’équipe reviennent à leur branche
main
sur leur copie de travail
Chaque membre de l’équipe fait les questions suivantes.
- Mesurer le poids de l’ensemble de l’historique en ligne de commande avec la commande
du -sh .git
- Télécharger le notebook servant à cet exercice avant la commande suivante, en ligne de commande:
curl "https://minio.lab.sspcloud.fr/lgaliana/python-ENSAE/inputs/git/exemple.ipynb" -o "notebook.ipynb"
Ne pas ouvrir ce fichier (objet de la prochaine question).
Faire un commit de ce notebook puis refaire
du -sh .git
- Observez le premier changement de poids de notre historique
- Ouvrir le notebook, exécuter ses cellules en les réordonnant si nécessaire pour débugger le fichier.
- Faire un commit de ce notebook quand il fonctionne puis refaire
du -sh .git
- Maintenant, faire les modifications suivantes du fichier:
- Modifier la cellule
df.head(3)
endf.head(20)
- Créer une nouvelle cellule avec le code
df["TYPEQU"].value_counts().plot(kind = "bar")
- Modifier la variable
zoom_start
dans la cellule produisant la carte interactive. Fixer sa valeur à 13 plutôt que 15.
- Modifier la cellule
- Faire un commit de ce notebook quand il fonctionne puis refaire
du -sh .git
- Changer la couleur du barplot avec l’argument
color
. Sauvegarder, committer puis refaire
du -sh .git
- Regarder l’historique depuis l’extension
VSCode
. Observer la manière dont évolue votre fichier à chaque commit.
Maintenant, nous pouvons passer à l’étape collaborative.
- Chaque membre de l’équipe push:
- Si le push fonctionne (personne la plus rapide), modifier à nouveau à nouveau la couleur du barplot. Committer mais ne pas pusher (attendre que les autres membres du groupe l’ait fait puis passer à la question 9)
- Si le push ne fonctionne pas (personnes moins rapides), passer à la question 9.
- Dans l’extension
VSCode
, afficher l’arbre en cliquant sur le boutonView Git Graph
.
- En haut de celui-ci, cliquer sur
Uncommitted changes
. Cela affiche les modifications qui ne sont pas encore acceptées. - Cliquer sur
notebook.ipynb
pour voir le diff entre votre version et celle de votre camarade. Comprenez-vous le problème ? - Accepter à la main chaque différence serait trop coûteux. Accepter la version de votre camarade (Accept incoming). Committer et observer le diff. Pusher.
Pour la dernière personne du groupe n’ayant pas pu pusher, refaire la question 9. Après avoir pushé, la personne ayant été la plus rapide à la question 8 peut faire la question 9 en récupérant les derniers commits.
Cet exercice permet d’illustrer trois points de difficultés avec les notebooks:
- La taille des fichiers
ipynb
devient vite importante car les outputs sont insérés dedans, de manière brute. - Il devient vite difficile de suivre les changements du code car celui-ci est noyé au milieu d’autres modifications (notamment celles des outputs).
- La résolution de conflits est compliquée car il faut garder la structure JSON. Il est d’ailleurs fréquent qu’un merge casse cette structure et rende le notebook illisible.
Pour régler ces problèmes, il existe plusieurs méthodes:
- Si on désire rester sur le notebook comme endroit où est stocké le code, il faut cliquer sur le bouton
Clear all outputs
avant de faire une étapegit add
. Le packagenbstripout
peut être une solution intéressante pour ne pas avoir à le faire manuellement à chaque fois car on prend le risque d’oublier et donc de faire quand même grossir la taille du dépôt. Néanmoins, cette approche ne règle qu’une partie des problèmes puisqu’elle ne fait qu’alléger le JSON versionné, elle rend moins probable mais ne rend pas impossible le risque de casser le notebook lors d’une résolution de conflit. - Travailler en équipe sur des notebooks différents comme ceci était conseillé pour les fichiers texte. Cela permet de ne plus avoir de conflit. Cependant, cela risque d’induire des redondances de code et donc des problèmes ultérieurement si on désire synthétiser les différents travaux.
- Adopter une structure plus modulaire en déportant le maximum de code dans des fichiers
.py
et en important les éléments adéquats dans les notebooks. Ceci permet de tirer avantage deGit
, qui suit très bien les fichiers.py
, tout en offrant des bénéfices sur la qualité des notebooks. En étant moins monolithiques, ils seront probablement de meilleure qualité.
Cette dernière approche est une manière de s’ouvrir aux bonnes pratiques qui sont évoquées dans le cours de 3e année de “Mise en production”.
5 Conclusion
Ces chapitres consacrés à Git
ont permis de démystifier ce logiciel en illustrant, par la pratique, les principaux concepts et la gymnastique quotidienne. Ils visent à faire économiser de précieuses heures car l’apprentissage de Git
en autodidacte est souvent frustrant et incomplet. Il est indispensable de garder cette habitude de faire du Git
sur ses projets. Ces derniers seront de meilleure qualité.
Nous n’avons vu que les fonctionnalités basiques de Git
et de Github
. L’objet du cours de 3e année de l’ENSAE de “Mise en production de projets data science” est de faire découvrir d’autres fonctionnalités de Git
et Github
qui permettent de produire des projets plus ambitieux, plus fiables et plus évolutifs.
Informations additionnelles
environment files have been tested on.
Latest built version: 2024-11-20
Python version used:
Package | Version |
---|---|
affine | 2.4.0 |
aiobotocore | 2.15.1 |
aiohappyeyeballs | 2.4.3 |
aiohttp | 3.10.8 |
aioitertools | 0.12.0 |
aiosignal | 1.3.1 |
alembic | 1.13.3 |
altair | 5.4.1 |
aniso8601 | 9.0.1 |
annotated-types | 0.7.0 |
appdirs | 1.4.4 |
archspec | 0.2.3 |
asttokens | 2.4.1 |
attrs | 24.2.0 |
babel | 2.16.0 |
bcrypt | 4.2.0 |
beautifulsoup4 | 4.12.3 |
black | 24.8.0 |
blinker | 1.8.2 |
blis | 0.7.11 |
bokeh | 3.5.2 |
boltons | 24.0.0 |
boto3 | 1.35.23 |
botocore | 1.35.23 |
branca | 0.7.2 |
Brotli | 1.1.0 |
cachetools | 5.5.0 |
cartiflette | 0.0.2 |
Cartopy | 0.24.1 |
catalogue | 2.0.10 |
cattrs | 24.1.2 |
certifi | 2024.8.30 |
cffi | 1.17.1 |
charset-normalizer | 3.3.2 |
click | 8.1.7 |
click-plugins | 1.1.1 |
cligj | 0.7.2 |
cloudpathlib | 0.20.0 |
cloudpickle | 3.0.0 |
colorama | 0.4.6 |
comm | 0.2.2 |
commonmark | 0.9.1 |
conda | 24.9.1 |
conda-libmamba-solver | 24.7.0 |
conda-package-handling | 2.3.0 |
conda_package_streaming | 0.10.0 |
confection | 0.1.5 |
contextily | 1.6.2 |
contourpy | 1.3.0 |
cryptography | 43.0.1 |
cycler | 0.12.1 |
cymem | 2.0.8 |
cytoolz | 1.0.0 |
dask | 2024.9.1 |
dask-expr | 1.1.15 |
databricks-sdk | 0.33.0 |
debugpy | 1.8.6 |
decorator | 5.1.1 |
Deprecated | 1.2.14 |
diskcache | 5.6.3 |
distributed | 2024.9.1 |
distro | 1.9.0 |
docker | 7.1.0 |
duckdb | 0.10.1 |
en-core-web-sm | 3.7.1 |
entrypoints | 0.4 |
et_xmlfile | 2.0.0 |
exceptiongroup | 1.2.2 |
executing | 2.1.0 |
fastexcel | 0.11.6 |
fastjsonschema | 2.20.0 |
fiona | 1.10.1 |
Flask | 3.0.3 |
folium | 0.17.0 |
fontawesomefree | 6.6.0 |
fonttools | 4.54.1 |
frozendict | 2.4.4 |
frozenlist | 1.4.1 |
fsspec | 2023.12.2 |
gensim | 4.3.2 |
geographiclib | 2.0 |
geopandas | 1.0.1 |
geoplot | 0.5.1 |
geopy | 2.4.1 |
gitdb | 4.0.11 |
GitPython | 3.1.43 |
google-auth | 2.35.0 |
graphene | 3.3 |
graphql-core | 3.2.4 |
graphql-relay | 3.2.0 |
graphviz | 0.20.3 |
great-tables | 0.12.0 |
greenlet | 3.1.1 |
gunicorn | 22.0.0 |
h2 | 4.1.0 |
hpack | 4.0.0 |
htmltools | 0.6.0 |
hyperframe | 6.0.1 |
idna | 3.10 |
imageio | 2.36.0 |
importlib_metadata | 8.5.0 |
importlib_resources | 6.4.5 |
inflate64 | 1.0.0 |
ipykernel | 6.29.5 |
ipython | 8.28.0 |
itsdangerous | 2.2.0 |
jedi | 0.19.1 |
Jinja2 | 3.1.4 |
jmespath | 1.0.1 |
joblib | 1.4.2 |
jsonpatch | 1.33 |
jsonpointer | 3.0.0 |
jsonschema | 4.23.0 |
jsonschema-specifications | 2024.10.1 |
jupyter-cache | 1.0.0 |
jupyter_client | 8.6.3 |
jupyter_core | 5.7.2 |
kaleido | 0.2.1 |
kiwisolver | 1.4.7 |
langcodes | 3.5.0 |
language_data | 1.3.0 |
lazy_loader | 0.4 |
libmambapy | 1.5.9 |
locket | 1.0.0 |
lxml | 5.3.0 |
lz4 | 4.3.3 |
Mako | 1.3.5 |
mamba | 1.5.9 |
mapclassify | 2.8.1 |
marisa-trie | 1.2.1 |
Markdown | 3.6 |
markdown-it-py | 3.0.0 |
MarkupSafe | 2.1.5 |
matplotlib | 3.9.2 |
matplotlib-inline | 0.1.7 |
mdurl | 0.1.2 |
menuinst | 2.1.2 |
mercantile | 1.2.1 |
mizani | 0.11.4 |
mlflow | 2.16.2 |
mlflow-skinny | 2.16.2 |
msgpack | 1.1.0 |
multidict | 6.1.0 |
multivolumefile | 0.2.3 |
munkres | 1.1.4 |
murmurhash | 1.0.10 |
mypy-extensions | 1.0.0 |
narwhals | 1.14.1 |
nbclient | 0.10.0 |
nbformat | 5.10.4 |
nest_asyncio | 1.6.0 |
networkx | 3.3 |
nltk | 3.9.1 |
numpy | 1.26.4 |
opencv-python-headless | 4.10.0.84 |
openpyxl | 3.1.5 |
opentelemetry-api | 1.16.0 |
opentelemetry-sdk | 1.16.0 |
opentelemetry-semantic-conventions | 0.37b0 |
OWSLib | 0.28.1 |
packaging | 24.1 |
pandas | 2.2.3 |
paramiko | 3.5.0 |
parso | 0.8.4 |
partd | 1.4.2 |
pathspec | 0.12.1 |
patsy | 0.5.6 |
Pebble | 5.0.7 |
pexpect | 4.9.0 |
pickleshare | 0.7.5 |
pillow | 10.4.0 |
pip | 24.2 |
platformdirs | 4.3.6 |
plotly | 5.24.1 |
plotnine | 0.13.6 |
pluggy | 1.5.0 |
polars | 1.8.2 |
preshed | 3.0.9 |
prometheus_client | 0.21.0 |
prometheus_flask_exporter | 0.23.1 |
prompt_toolkit | 3.0.48 |
protobuf | 4.25.3 |
psutil | 6.0.0 |
ptyprocess | 0.7.0 |
pure_eval | 0.2.3 |
py7zr | 0.20.8 |
pyarrow | 17.0.0 |
pyarrow-hotfix | 0.6 |
pyasn1 | 0.6.1 |
pyasn1_modules | 0.4.1 |
pybcj | 1.0.2 |
pycosat | 0.6.6 |
pycparser | 2.22 |
pycryptodomex | 3.21.0 |
pydantic | 2.9.2 |
pydantic_core | 2.23.4 |
Pygments | 2.18.0 |
PyNaCl | 1.5.0 |
pynsee | 0.1.8 |
pyogrio | 0.10.0 |
pyOpenSSL | 24.2.1 |
pyparsing | 3.1.4 |
pyppmd | 1.1.0 |
pyproj | 3.7.0 |
pyshp | 2.3.1 |
PySocks | 1.7.1 |
python-dateutil | 2.9.0 |
python-dotenv | 1.0.1 |
python-magic | 0.4.27 |
pytz | 2024.1 |
pyu2f | 0.1.5 |
pywaffle | 1.1.1 |
PyYAML | 6.0.2 |
pyzmq | 26.2.0 |
pyzstd | 0.16.2 |
querystring_parser | 1.2.4 |
rasterio | 1.4.2 |
referencing | 0.35.1 |
regex | 2024.9.11 |
requests | 2.32.3 |
requests-cache | 1.2.1 |
retrying | 1.3.4 |
rich | 13.9.4 |
rpds-py | 0.21.0 |
rsa | 4.9 |
ruamel.yaml | 0.18.6 |
ruamel.yaml.clib | 0.2.8 |
s3fs | 2023.12.2 |
s3transfer | 0.10.2 |
scikit-image | 0.24.0 |
scikit-learn | 1.5.2 |
scipy | 1.13.0 |
seaborn | 0.13.2 |
setuptools | 74.1.2 |
shapely | 2.0.6 |
shellingham | 1.5.4 |
six | 1.16.0 |
smart-open | 7.0.5 |
smmap | 5.0.0 |
sortedcontainers | 2.4.0 |
soupsieve | 2.5 |
spacy | 3.7.5 |
spacy-legacy | 3.0.12 |
spacy-loggers | 1.0.5 |
SQLAlchemy | 2.0.35 |
sqlparse | 0.5.1 |
srsly | 2.4.8 |
stack-data | 0.6.2 |
statsmodels | 0.14.4 |
tabulate | 0.9.0 |
tblib | 3.0.0 |
tenacity | 9.0.0 |
texttable | 1.7.0 |
thinc | 8.2.5 |
threadpoolctl | 3.5.0 |
tifffile | 2024.9.20 |
toolz | 1.0.0 |
topojson | 1.9 |
tornado | 6.4.1 |
tqdm | 4.66.5 |
traitlets | 5.14.3 |
truststore | 0.9.2 |
typer | 0.13.1 |
typing_extensions | 4.12.2 |
tzdata | 2024.2 |
Unidecode | 1.3.8 |
url-normalize | 1.4.3 |
urllib3 | 1.26.20 |
wasabi | 1.1.3 |
wcwidth | 0.2.13 |
weasel | 0.4.1 |
webdriver-manager | 4.0.2 |
websocket-client | 1.8.0 |
Werkzeug | 3.0.4 |
wheel | 0.44.0 |
wordcloud | 1.9.3 |
wrapt | 1.16.0 |
xgboost | 2.1.1 |
xlrd | 2.0.1 |
xyzservices | 2024.9.0 |
yarl | 1.13.1 |
yellowbrick | 1.5 |
zict | 3.0.0 |
zipp | 3.20.2 |
zstandard | 0.23.0 |
View file history
SHA | Date | Author | Description |
---|---|---|---|
1202a02 | 2024-10-22 11:25:10 | Lino Galiana | Git, modifs suite au cours de 2024 (#568) |
00f28a3 | 2024-10-15 13:41:20 | lgaliana | Ajoute questions collaboratifs Git |
e0fa908 | 2024-10-12 13:50:16 | lgaliana | Mise en forme exogit |
adc4657 | 2024-10-11 17:17:25 | lgaliana | color |
288bd4a | 2024-10-11 17:16:19 | lgaliana | Interface graphique pour l’exo 3 également |
25ca332 | 2024-10-11 16:38:02 | lgaliana | Retirer ligne de commande |
20672a4 | 2024-10-11 13:11:20 | Lino Galiana | Quelques correctifs supplémentaires sur Git et mercator (#566) |
3e04253 | 2024-09-30 10:11:32 | Lino Galiana | Grosse mise à jour de la partie Git (#557) |
580cba7 | 2024-08-07 18:59:35 | Lino Galiana | Multilingual version as quarto profile (#533) |
005d89b | 2023-12-20 17:23:04 | Lino Galiana | Finalise l’affichage des statistiques Git (#478) |
4c1c22d | 2023-12-10 11:50:56 | Lino Galiana | Badge en javascript plutôt (#469) |
1f23de2 | 2023-12-01 17:25:36 | Lino Galiana | Stockage des images sur S3 (#466) |
a06a268 | 2023-11-23 18:23:28 | Antoine Palazzolo | 2ème relectures chapitres ML (#457) |
56d092b | 2023-11-14 15:43:00 | Antoine Palazzolo | update readme (#451) |
09654c7 | 2023-11-14 15:16:44 | Antoine Palazzolo | Suggestions Git & Visualisation (#449) |
b6ae3e3 | 2023-11-14 05:49:42 | linogaliana | Corrige balise md |
ae5205f | 2023-11-13 20:35:43 | linogaliana | précision |
428d669 | 2023-11-13 20:31:11 | linogaliana | Exo gitignore |
66c6a29 | 2023-11-13 19:53:49 | linogaliana | jupyter sspcloud credential helper |
69d5bc7 | 2023-11-13 19:44:01 | linogaliana | mise à jour de quelques consignes |
e3f1ef1 | 2023-11-13 11:53:50 | Thomas Faria | Relecture git (#448) |
ea9400a | 2023-11-05 10:54:04 | tomseimandi | Include VSCode instructions in exogit (#447) |
9366e8d | 2023-10-09 12:06:23 | Lino Galiana | Retrait des box hugo sur l’exo git (#428) |
a771183 | 2023-10-09 11:27:45 | Antoine Palazzolo | Relecture TD2 par Antoine (#418) |
f8831e7 | 2023-10-09 10:53:34 | Lino Galiana | Relecture antuki geopandas (#429) |
5ab34aa | 2023-10-04 14:54:20 | Kim A | Relecture Kim pandas & git (#416) |
154f09e | 2023-09-26 14:59:11 | Antoine Palazzolo | Des typos corrigées par Antoine (#411) |
b649205 | 2023-08-28 15:47:09 | linogaliana | Nice image |
9a4e226 | 2023-08-28 17:11:52 | Lino Galiana | Action to check URL still exist (#399) |
3bdf3b0 | 2023-08-25 11:23:02 | Lino Galiana | Simplification de la structure 🤓 (#393) |
30823c4 | 2023-08-24 14:30:55 | Lino Galiana | Liens morts navbar (#392) |
2dbf853 | 2023-07-05 11:21:40 | Lino Galiana | Add nice featured images (#368) |
34cc32c | 2022-10-14 22:05:47 | Lino Galiana | Relecture Git (#300) |
fd439f0 | 2022-09-19 09:37:50 | avouacr | fix ssp cloud links |
3056d41 | 2022-09-02 12:19:55 | avouacr | fix all SSP Cloud launcher links |
f10815b | 2022-08-25 16:00:03 | Lino Galiana | Notebooks should now look more beautiful (#260) |
12965ba | 2022-05-25 15:53:27 | Lino Galiana | :launch: Bascule vers quarto (#226) |
9c71d6e | 2022-03-08 10:34:26 | Lino Galiana | Plus d’éléments sur S3 (#218) |
0e01c33 | 2021-11-10 12:09:22 | Lino Galiana | Relecture @antuki API+Webscraping + Git (#178) |
9a3f7ad | 2021-10-31 18:36:25 | Lino Galiana | Nettoyage partie API + Git (#170) |
2f4d390 | 2021-09-02 15:12:29 | Lino Galiana | Utilise un shortcode github (#131) |
4cdb759 | 2021-05-12 10:37:23 | Lino Galiana | :sparkles: :star2: Nouveau thème hugo :snake: :fire: (#105) |
7f9f97b | 2021-04-30 21:44:04 | Lino Galiana | 🐳 + 🐍 New workflow (docker 🐳) and new dataset for modelization (2020 🇺🇸 elections) (#99) |
36ed7b1 | 2020-10-07 12:36:03 | Lino Galiana | Cadavre exquis (#66) |
d1ad64c | 2020-10-04 14:43:55 | Lino Galiana | Finalisation de la première partie de l’exo git (#62) |
283e8e9 | 2020-10-02 18:54:30 | Lino Galiana | Première partie des exos git (#61) |
Citation
@book{galiana2023,
author = {Galiana, Lino},
title = {Python pour la data science},
date = {2023},
url = {https://pythonds.linogaliana.fr/},
doi = {10.5281/zenodo.8229676},
langid = {fr}
}