diff --git a/.conda/README.md b/.conda/README.md new file mode 100644 index 0000000000..4e3f547b1d --- /dev/null +++ b/.conda/README.md @@ -0,0 +1,42 @@ +# Publication vers Anaconda + +Ce readme décrit la partie publication vers conda, pour utiliser le paquet conda résultant, voir [le readme principal](https://github.com/openfisca/openfisca-france/tree/publish-to-conda#installez-un-environnement-virtuel-avec-conda). + +Pour envoyer un paquet vers conda il faut obligatoirement un fichier `meta.yaml` qui décrit le package. + +Nous avons fait le choix d'utiliser le paquet PyPi comme source du paquet Conda, pour s'assurer que l'on publie bien la même chose sur les deux plateformes. + +L'upload automatique est fait de la façon suivante par la CI uniquement si l'étape de livraison sur PyPi s'est bien déroulée : +- Installation de Miniconda. +- Récupération par le script `.github/get_pypi_info.py` des informations du package sur PyPi. +- Ecriture de ces informations par ce même script dans le fichier `.conda/meta.yaml`. +- Exécution de `conda build` pour construire et publier le paquet conformément au fichier `.conda/meta.yaml`. Cette étape nécessite la variable de CI ANACONDA_TOKEN. + +Pour valider que tout a fonctionné, une étape `test-on-windows` a été ajoutée en fin de CI. Cette étape récupère le paquet conda sur une machine Windows et exécute les tests. + +**A noter** : Le paquet OpenFisca-France est aussi publié sur `conda-forge`, pour cela voir [le feedstock](https://github.com/openfisca/openfisca-france-feedstock/tree/master/recipe) + +C'est le channel `conda-forge` qui est le channel stable à conseiller aux utilisateurs. Le channel `openfisca` reçoit les derniers paquets de façon automatique. + +## Etapes préparatoires pour arriver à cette automatisation + +- Création d'un compte sur https://anaconda.org. +- Création d'un token sur https://anaconda.org/openfisca/settings/access avec le droit _Allow write access to the API site_. Attention il expire le 2023/01/13. + +- Mis en place du token dans GitHub Action sous le nom de variable ANACONDA_TOKEN. + +### Publication manuelle du package + +Les étapes suivantes peuvent être réalisées sous Windows pour tester la publication : + +_Cela fonctionne aussi sous macOS et Linux, à condition d'adapter les chemins._ + +- Editer `.conda/meta.yaml` pour vérifier son contenu. +- Installer [MiniConda](https://docs.conda.io/projects/conda/en/latest/user-guide/install/windows.html) si vous n'avez pas déjà [AnaConda](https://www.anaconda.com/products/individual). +- Puis dans le terminal saisissez les instructions suivantes : + - `conda install -c anaconda conda-build anaconda-client` Pour installer les outils indispensable. + - `conda build --croot c:\temp .conda` L'option `--croot ` est nécessaire sous Windows à cause des chemins trop long. + - `conda install -c anaconda anaconda-client` Pour installer l'outil en ligne de commande. + - `anaconda login` Pour vous connecter avec le compte _openfisca_, voir le Keepass OpenFisca. + - `anaconda upload c:\temp\noarch\openfisca-france--py_0.tar.bz2` pour publier le package. +- Vérifier que tout c'est bien passé sur https://anaconda.org/search?q=openfisca. diff --git a/.conda/meta.yaml b/.conda/meta.yaml new file mode 100644 index 0000000000..6930050f83 --- /dev/null +++ b/.conda/meta.yaml @@ -0,0 +1,78 @@ +############################################################################### +## Fichier de description du package pour Anaconda.org +## Attention, les chaines PYPI_VERSION, PYPI_URL et PYPI_SHA256 sont remplacées +## par la CI, il faut les conserver. +############################################################################### + +{% set name = "OpenFisca-France" %} +{% set version = "PYPI_VERSION" %} + +package: + name: {{ name|lower }} + version: {{ version }} + +source: + url: PYPI_URL + sha256: PYPI_SHA256 + +build: + noarch: python + number: 0 + script: "{{ PYTHON }} -m pip install . -vv" + +requirements: + host: + - python + - pip + run: + - python >=3.6,<4.0 + - OpenFisca-Core >=35.2.0,<36.0 + + +test: + imports: + - openfisca_france + requires: + - pip + commands: + - pip check + +outputs: + - name: openfisca-france + + - name: openfisca-france-scipy + build: + noarch: python + requirements: + host: + - python + run: + - scipy >=0.17 + - {{ pin_subpackage('openfisca-france', exact=True) }} + + - name: openfisca-france-dev + build: + noarch: python + requirements: + host: + - python + run: + - autopep8 ==1.5.7 + - flake8 >=3.8.0,<3.10.0 + - flake8-print + - pytest >=5.0.0, <7.0.0 + - requests >=2.8 + - yamllint >=1.11.1,<1.27 + - {{ pin_subpackage('openfisca-france-scipy', exact=True) }} + +about: + home: https://fr.openfisca.org/ + license_family: AGPL + license: AGPL-3.0-only + license_file: LICENSE.AGPL.txt + summary: "French tax and benefit system for OpenFisca" + description: | + OpenFisca is a versatile microsimulation free software. + This repository contains the OpenFisca model of the French tax and benefit system. + doc_url: https://fr.openfisca.org/ + dev_url: https://github.com/openfisca/openfisca-france/ diff --git a/.github/get_pypi_info.py b/.github/get_pypi_info.py new file mode 100644 index 0000000000..b82904f288 --- /dev/null +++ b/.github/get_pypi_info.py @@ -0,0 +1,47 @@ +import argparse +import requests + + +def get_info(package_name: str = "") -> dict: + """ + Get minimal informations needed by .conda/meta.yaml from PyPi JSON API. + ::package_name:: Name of package to get infos from. + ::return:: A dict with last_version, url and sha256 + """ + if package_name == "": + raise ValueError("Package name not provided.") + resp = requests.get(f"https://pypi.org/pypi/{package_name}/json").json() + version = resp["info"]["version"] + for v in resp["releases"][version]: + if v["packagetype"] == "sdist": # for .tag.gz + return { + "last_version": version, + "url": v["url"], + "sha256": v["digests"]["sha256"] + } + + +def replace_in_file(filepath: str, info: dict): + ''' + ::filepath:: Path to meta.yaml, with filename + ::info:: Dict with information to populate + ''' + with open(filepath, "rt") as fin: + meta = fin.read() + # Replace with info from PyPi + meta = meta.replace("PYPI_VERSION", info["last_version"]) + meta = meta.replace("PYPI_URL", info["url"]) + meta = meta.replace("PYPI_SHA256", info["sha256"]) + with open(filepath, "wt") as fout: + fout.write(meta) + print(f"File {filepath} has been updated with informations from PyPi.") # noqa: T001 + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument("-p", "--package", type=str, default="", required=True, help="The name of the package") + parser.add_argument("-f", "--filename", type=str, default=".conda/meta.yaml", help="Path to meta.yaml, with filename") + args = parser.parse_args() + info = get_info(args.package) + print("Information of the last published PyPi package :", info) # noqa: T001 + replace_in_file(args.filename, info) diff --git a/.github/workflows/validate_yaml.yml b/.github/workflows/validate_yaml.yml index 6d4833df32..4a2fb53bbf 100644 --- a/.github/workflows/validate_yaml.yml +++ b/.github/workflows/validate_yaml.yml @@ -1,9 +1,10 @@ name: Validate YAML on: - - pull_request - - push - - workflow_dispatch + push: + workflow_dispatch: + pull_request: + types: [opened, reopened] jobs: validate_yaml: diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index c29f955f00..2f6d88a75a 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -1,26 +1,34 @@ name: OpenFisca France -on: [push, pull_request] +on: + push: + pull_request: + types: [opened, reopened] jobs: build: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} + strategy: + fail-fast: true + matrix: + os: ["ubuntu-latest"] # On peut ajouter "macos-latest" si besoin + python-version: ["3.7.9", "3.8.9", "3.9.9"] steps: - name: Checkout uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.7.12 + python-version: ${{ matrix.python-version }} - name: Cache build id: restore-build uses: actions/cache@v2 with: path: ${{ env.pythonLocation }} - key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }} + key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }}-${{ matrix.os }} restore-keys: | # in case of a cache miss (systematically unless the same commit is built repeatedly), the keys below will be used to restore dependencies from previous builds, and the cache will be stored at the end of the job, making up-to-date dependencies available for all jobs of the workflow; see more at https://docs.github.com/en/actions/advanced-guides/caching-dependencies-to-speed-up-workflows#example-using-the-cache-action - build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }} - build-${{ env.pythonLocation }}- + build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ matrix.os }} + build-${{ env.pythonLocation }}-${{ matrix.os }} - name: Build package run: make build - name: Cache release @@ -28,7 +36,7 @@ jobs: uses: actions/cache@v2 with: path: dist - key: release-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }} + key: release-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }}-${{ matrix.os }} lint-files: runs-on: ubuntu-latest @@ -40,13 +48,13 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.7.12 + python-version: 3.7.9 - name: Cache build id: restore-build uses: actions/cache@v2 with: path: ${{ env.pythonLocation }} - key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }} + key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }}-ubuntu-latest - run: make check-syntax-errors - run: make check-style - name: Lint Python files @@ -55,20 +63,25 @@ jobs: run: "${GITHUB_WORKSPACE}/.github/lint-changed-yaml-tests.sh" test-python: - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} needs: [ build ] + strategy: + fail-fast: true + matrix: + os: [ "ubuntu-latest" ] # On peut ajouter "macos-latest" si besoin + python-version: ["3.7.9", "3.8.9", "3.9.9"] steps: - uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.7.12 + python-version: ${{ matrix.python-version }} - name: Cache build id: restore-build uses: actions/cache@v2 with: path: ${{ env.pythonLocation }} - key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }} + key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }}-${{ matrix.os }} - run: | shopt -s globstar openfisca test tests/**/*.py @@ -89,13 +102,13 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.7.12 + python-version: 3.7.9 - name: Cache build id: restore-build uses: actions/cache@v2 with: path: ${{ env.pythonLocation }} - key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }} + key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }}-ubuntu-latest - name: Split YAML tests id: yaml-test env: @@ -115,13 +128,13 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.7.12 + python-version: 3.7.9 - name: Cache build id: restore-build uses: actions/cache@v2 with: path: ${{ env.pythonLocation }} - key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }} + key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }}-ubuntu-latest - name: Test the Web API run: "${GITHUB_WORKSPACE}/.github/test-api.sh" @@ -135,7 +148,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.7.12 + python-version: 3.7.9 - name: Check version number has been properly updated run: "${GITHUB_WORKSPACE}/.github/is-version-number-acceptable.sh" @@ -155,7 +168,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.7.12 + python-version: 3.7.9 - id: stop-early run: if "${GITHUB_WORKSPACE}/.github/has-functional-changes.sh" ; then echo "::set-output name=status::success" ; fi @@ -173,20 +186,69 @@ jobs: - name: Set up Python uses: actions/setup-python@v2 with: - python-version: 3.7.12 + python-version: 3.7.9 - name: Cache build id: restore-build uses: actions/cache@v2 with: path: ${{ env.pythonLocation }} - key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }} + key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }}-ubuntu-latest - name: Cache release id: restore-release uses: actions/cache@v2 with: path: dist - key: release-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }} + key: release-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }}-ubuntu-latest - name: Upload a Python package to PyPi run: twine upload dist/* --username $PYPI_USERNAME --password $PYPI_PASSWORD - name: Publish a git tag run: "${GITHUB_WORKSPACE}/.github/publish-git-tag.sh" + + publish-to-conda: + runs-on: "ubuntu-latest" + needs: [ deploy ] + strategy: + fail-fast: false + steps: + - uses: conda-incubator/setup-miniconda@v2 + with: + auto-update-conda: true + python-version: "3.7.9" + # Add conda-forge for OpenFisca-Core + channels: conda-forge + activate-environment: true + - uses: actions/checkout@v2 + with: + fetch-depth: 0 # Fetch all the tags + - name: Update meta.yaml + run: | + python3 -m pip install requests argparse + python3 .github/get_pypi_info.py -p OpenFisca-France + - name: Conda Config + run: | + conda install conda-build anaconda-client + conda info + conda config --set anaconda_upload yes + - name: Conda build + run: conda build --token ${{ secrets.ANACONDA_TOKEN }} --user openfisca .conda + + test-on-windows: + runs-on: "windows-latest" + needs: [ publish-to-conda ] + strategy: + fail-fast: false + steps: + - uses: conda-incubator/setup-miniconda@v2 + with: + auto-update-conda: true + python-version: "3.9.9" + # Add conda-forge for OpenFisca-Core + channels: conda-forge + activate-environment: true + - uses: actions/checkout@v2 + with: + fetch-depth: 0 # Fetch all the tags + - name: Install with conda + run: conda install -c openfisca openfisca-france-dev + - name: openfisca test + run: openfisca test --country-package openfisca_france tests diff --git a/CHANGELOG.md b/CHANGELOG.md index 71f608735e..5c00419bde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,23 @@ # Changelog +### 106.0.1 [#1786](https://github.com/openfisca/openfisca-france/pull/1786) + +* Amélioration technique. +* Périodes concernées : aucune. +* Zones impactées : aucune. +* Détails : + - Ajout de la publication vers [conda](https://anaconda.org/search?q=openfisca-france) + - Ajout du dossier .conda pour les fichiers spécifiques à Conda. + - Plusieurs modifications sur le workflow Github Action : + - Changement de la règle de déclenchement pour éviter les exécutions en double sur les PR. + - Ajout des tests sur plusieurs versions de Python. + - Ajout d'un test sur Windows en utilisant le paquet conda, après publication. + # 106.0.0 [#1790](https://github.com/openfisca/openfisca-france/pull/1790) -* Amélioration technique. +* Amélioration technique. * Périodes concernées : toutes. -* Zones impactées : +* Zones impactées : - `parameters/prestations_sociales/prestations_familiales/petite_enfance`. * Détails : - Harmonisation des fichiers avec les barèmes-ipp @@ -15,9 +28,9 @@ git log --oneline 500832d46fc6^..281c8b368c1bceb| grep "variable_name" # 105.0.0 [#1789](https://github.com/openfisca/openfisca-france/pull/1789) -* Amélioration technique. +* Amélioration technique. * Périodes concernées : toutes. -* Zones impactées : +* Zones impactées : - `parameters/prestations_sociales/prestations_familiales/prestations_generales` - `parameters/prestations_sociales/prestations_familiales/def_biactif` - `parameters/prestations_sociales/prestations_familiales/def_pac` @@ -27,7 +40,6 @@ git log --oneline 500832d46fc6^..281c8b368c1bceb| grep "variable_name" * Détails : - Harmonisation des fichiers avec les barèmes-ipp - Tous les chemins sont updatés pour ne pas casser le code - - * Guide pour la migration: Vous pouvez chercher où sont passés vos fichiers avec la commande suivante: git log --oneline 66724eff27e8feb0^..60136e4a68e04 | grep "variable_name" @@ -43,7 +55,7 @@ git log --oneline 66724eff27e8feb0^..60136e4a68e04 | grep "variable_name" * Évolution du système socio-fiscal * Périodes concernées : à partir du 09/06/2021. -* Zones impactées : +* Zones impactées : * model/prestations/aide_mobilite.py * model/prestations/agepi.py * model/revenus/activite/salarie.py diff --git a/README.md b/README.md index 7b2ac3363f..95b02b43b3 100644 --- a/README.md +++ b/README.md @@ -31,18 +31,18 @@ L'ensembles des endpoints sont décrits dans la [documentation Swagger](https:// ## Installation -Ce paquet requiert [Python 3.7](https://www.python.org/downloads/release/python-370/) et [pip](https://pip.pypa.io/en/stable/installing/). +Ce paquet requiert [Python 3.7](https://www.python.org/downloads/release/python-370/) et [pip](https://pip.pypa.io/en/stable/installing/) ou [conda](https://www.anaconda.com/products/individual). Plateformes supportées : - distributions GNU/Linux (en particulier Debian and Ubuntu) ; - Mac OS X ; -- Windows (nous recommandons d'utiliser [ConEmu](https://conemu.github.io/) à la place de la console par défaut) ; +- Windows : Nous recommandons d'utiliser [conda](https://www.anaconda.com/products/individual), voir la procédure ci-dessous [Installez un environnement virtuel avec conda](./README.md#installez-un-environnement-virtuel-avec-conda) ; OpenFisca fonctionne également dans le [sous-système Windows pour Linux (WSL)](https://docs.microsoft.com/fr-fr/windows/wsl/install). Dans ce dernier cas, il suffit de suivre la procédure pour Linux car vous êtes alors dans un environnement Linux. Pour les autres OS : si vous pouvez exécuter Python et Numpy, l'installation d'OpenFisca devrait fonctionner. ### Installez un environnement virtuel avec Pew -Nous recommandons l'utilisation d'un [environnement virtuel](https://virtualenv.pypa.io/en/stable/) (_virtualenv_) avec un gestionnaire de _virtualenv_ tel que [Pew](https://github.com/berdario/pew). +Nous recommandons l'utilisation d'un [environnement virtuel](https://virtualenv.pypa.io/en/stable/) (_virtualenv_) avec un gestionnaire de _virtualenv_ tel que [Pew](https://github.com/berdario/pew). Vous pouvez aussi utiliser le gestionnaire d'environnemnt officiel de Python : [venv](https://docs.python.org/3/library/venv.html). - Un _[virtualenv](https://virtualenv.pypa.io/en/stable/)_ crée un environnement pour les besoins spécifiques du projet sur lequel vous travaillez. - Un gestionnaire de _virtualenv_, tel que [Pew](https://github.com/berdario/pew), vous permet de facilement créer, supprimer et naviguer entre différents projets. @@ -160,6 +160,33 @@ pytest tests/test_basics.py # Ces test peuvent prendre jusqu'à 60 secondes. ``` :tada: OpenFisca-France est prêt à être utilisé ! +### Installez un environnement virtuel avec conda + +Nous conseillons cette procédure pour les personnes utilisant Windows et n'ayant pas d'environnement Python fonctionnel. Elle fonctionne également sous Linux et macOS. + +Ceci vous permet d'obtenir en une seule installation : +- Python +- Le gestionnaire de paquets [Anaconda.org](https://docs.anaconda.com/anacondaorg/user-guide/) +- Le gestionnaire d'environnement Python virtuel : [conda](https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html) + +Voici les étapes à suivre : + +- Installer la version communautaire/gratuite en suivant la procédure décrite sur [le site Anaconda](https://www.anaconda.com/products/individual). A noter que Anaconda occupe beaucoup d'espace disque (>2 Go), vous pouvez installer à la place [Miniconda](https://docs.conda.io/projects/conda/en/latest/user-guide/install/windows.html) qui occupe beaucoup moins d'espace disque. Cependant vous n'aurez pas l'interface graphique [Anaconda Navigator](https://docs.anaconda.com/anaconda/navigator/index.html) qui vous permet de gérer vos environnements. Si vous êtes habituée à gérer les choses en ligne de commande, préfèrez Miniconda. +- Depuis le menu démarrer, exécuter `Anaconda Powershell Prompt`. Ou utiliser votre shell préféré avec Miniconda, il vous faudra peut-être utiliser la commande `conda init`, mais conda vous le dira. +- Exécuter les commandes suivantes dans le shell: + - Ajouter `conda-forge` comme channel par défaut : `conda config --add channels conda-forge && conda config --set channel_priority strict ` + - Créer un environnement virtuel dédié : `conda create --name openfisca python=3.7` + - Activer l'environnement : `conda activate openfisca` + - Installer OpenFisca : `conda install openfisca-france` + +:tada: OpenFisca-France est prêt à être utilisé ! + +Ensuite, pour quitter l'environnement OpenFisca : `conda deactivate` + +Pour y revenir : `conda activate openfisca` + +A noter que OpenFisca-France est présent sur [conda-forge](https://anaconda.org/conda-forge/openfisca-france) et sur un _channel_ dédié [openfisca](https://anaconda.org/openfisca/openfisca-france). C'est conda-forge qui est mis en avant dans cette documentation, car accessible par défaut dans les installations Anaconda. + #### Prochaines étapes - Pour enrichir ou faire évoluer la législation d'OpenFisca-France, lisez _[Coding the Legislation](https://openfisca.org/doc/coding-the-legislation/index.html)_ (en anglais). diff --git a/setup.py b/setup.py index 35c304459d..cd2c3e02cd 100644 --- a/setup.py +++ b/setup.py @@ -1,11 +1,15 @@ #! /usr/bin/env python from setuptools import setup, find_packages +from pathlib import Path +# Read the contents of our README file for PyPi +this_directory = Path(__file__).parent +long_description = (this_directory / "README.md").read_text() setup( name = "OpenFisca-France", - version = "106.0.0", + version = "106.0.1", author = "OpenFisca Team", author_email = "contact@openfisca.fr", classifiers = [ @@ -15,17 +19,22 @@ "Programming Language :: Python", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "Topic :: Scientific/Engineering :: Information Analysis", ], description = "French tax and benefit system for OpenFisca", keywords = "benefit france microsimulation social tax", license = "http://www.fsf.org/licensing/licenses/agpl-3.0.html", + license_files = ("LICENSE.AGPL.txt",), url = "https://github.com/openfisca/openfisca-france", + long_description=long_description, + long_description_content_type='text/markdown', data_files = [ ( "share/openfisca/openfisca-france", - ["CHANGELOG.md", "LICENSE.AGPL.txt", "README.md"], + ["CHANGELOG.md", "README.md"], ), ], extras_require = {