diff --git a/.conda/meta.yaml b/.conda/meta.yaml index 076dd397c6..336df12c9c 100644 --- a/.conda/meta.yaml +++ b/.conda/meta.yaml @@ -28,23 +28,24 @@ requirements: - python - pip run: - - python >=3.6,<4.0 - - dpath >=1.5.0,<3.0.0 - - nptyping ==1.4.4 - - numexpr >=2.7.0,<=3.0 - - numpy >=1.11,<1.21 - - psutil >=5.4.7,<6.0.0 - - pytest >=4.4.1,<6.0.0 - - PyYAML >=3.10 - - sortedcontainers ==2.2.2 - - typing-extensions ==3.10.0.2 + - python >= 3.7, < 4.0 + - PyYAML >= 6.0.0, < 7.0.0 + - dpath >= 2.1.0, < 3.0.0 + - importlib-metadata < 4.3.0 + - nptyping == 1.4.4 + - numexpr >= 2.8.0, <= 3.0.0 + - numpy >= 1.20, < 1.21 + - psutil >= 5.9.0, < 6.0.0 + - pytest >= 5.4.0, < 6.0.0 + - sortedcontainers == 2.2.2 + - typing-extensions >= 4.4.0, < 5.0.0 test: imports: - openfisca_core - openfisca_core.commons requires: - - pytest >=4.4.1,<6.0.0 + - pytest >= 5.4.0, < 6.0.0 - pip commands: - pip check @@ -61,11 +62,12 @@ outputs: host: - python run: - - python >=3.6,<4.0 - - flask ==1.1.2 - - flask-cors ==3.0.10 - - gunicorn >=20.0.0,<21.0.0 - - werkzeug >=1.0.0,<2.0.0 + - python >= 3.7, < 4.0 + - markupsafe == 2.0.1 + - flask == 1.1.4 + - flask-cors == 3.0.10 + - gunicorn >= 20.1.0, < 21.0.0 + - werkzeug >= 1.0.0, < 2.0.0 - {{ pin_subpackage('openfisca-core', exact=True) }} - name: openfisca-core-dev @@ -75,18 +77,23 @@ outputs: host: - python run: - - autopep8 >=1.4.0,<1.6.0 - - coverage ==6.0.2 - - darglint ==1.8.0 - - flake8 >=3.9.0,<4.0.0 - - flake8-bugbear >=19.3.0,<20.0.0 - - flake8-docstrings ==1.6.0 - - flake8-print >=3.1.0,<4.0.0 - - flake8-rst-docstrings ==0.2.3 - - mypy ==0.910 - - openfisca-country-template >=3.10.0,<4.0.0 - - openfisca-extension-template >=1.2.0rc0,<2.0.0 - - pylint ==2.10.2 + - autopep8 >= 1.5.0, < 1.6.0 + - coverage >= 6.5.0, < 7.0.0 + - darglint == 1.8.0 + - flake8 >= 4.0.0, < 4.1.0 + - flake8-bugbear >= 19.8.0, < 20.0.0 + - flake8-docstrings == 1.6.0 + - flake8-print >= 3.1.0, < 4.0.0 + - flake8-rst-docstrings == 0.2.3 + - idna >= 3.4.0, < 4.0.0 + - isort >= 5.11.0, < 6.0.0 + - mypy == 0.910 + - openapi-spec-validator >= 0.5.0, < 0.6.0 + - pycodestyle >= 2.8.0, < 2.9.0 + - pylint == 2.10.2 + - xdoctest >= 1.1.0, < 2.0.0 + - openfisca-country-template >= 5.0.0, < 6.0.0 + - openfisca-extension-template >= 1.3.13, < 2.0.0 - {{ pin_subpackage('openfisca-core-api', exact=True) }} about: diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index fcb2acc162..0000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,8 +0,0 @@ -version: 2 -updates: -- package-ecosystem: pip - directory: "/" - schedule: - interval: monthly - labels: - - kind:dependencies diff --git a/.github/get-numpy-version.py b/.github/get-numpy-version.py deleted file mode 100755 index 64cb68532e..0000000000 --- a/.github/get-numpy-version.py +++ /dev/null @@ -1,38 +0,0 @@ -#! /usr/bin/env python - -from __future__ import annotations - -import os -import sys -import typing -from packaging import version -from typing import NoReturn, Union - -import numpy - -if typing.TYPE_CHECKING: - from packaging.version import LegacyVersion, Version - - -def prev() -> NoReturn: - release = _installed().release - - if release is None: - sys.exit(os.EX_DATAERR) - - major, minor, _ = release - - if minor == 0: - sys.exit(os.EX_DATAERR) - - minor -= 1 - print(f"{major}.{minor}.0") # noqa: T001 - sys.exit(os.EX_OK) - - -def _installed() -> Union[LegacyVersion, Version]: - return version.parse(numpy.__version__) - - -if __name__ == "__main__": - globals()[sys.argv[1]]() diff --git a/.github/publish-git-tag.sh b/.github/publish-git-tag.sh deleted file mode 100755 index 4450357cbc..0000000000 --- a/.github/publish-git-tag.sh +++ /dev/null @@ -1,4 +0,0 @@ -#! /usr/bin/env bash - -git tag `python setup.py --version` -git push --tags # update the repository version diff --git a/.github/workflows/_before.yaml b/.github/workflows/_before.yaml new file mode 100644 index 0000000000..d347057bb3 --- /dev/null +++ b/.github/workflows/_before.yaml @@ -0,0 +1,102 @@ +name: Setup package + +on: + workflow_call: + inputs: + os: + required: true + type: string + + numpy: + required: true + type: string + + python: + required: true + type: string + + activate_command: + required: true + type: string + +jobs: + deps: + runs-on: ${{ inputs.os }} + name: deps-${{ inputs.os }}-np${{ inputs.numpy }}-py${{ inputs.python }} + env: + TERM: xterm-256color # To colorize output of make tasks. + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ inputs.python }} + + - name: Use zstd for faster cache restore (windows) + if: ${{ startsWith(inputs.os, 'windows') }} + shell: cmd + run: echo C:\Program Files\Git\usr\bin>>"%GITHUB_PATH%" + + - name: Cache dependencies + id: restore-deps + uses: actions/cache@v3 + with: + path: venv + key: deps-${{ inputs.os }}-np${{ inputs.numpy }}-py${{ inputs.python }}-${{ hashFiles('setup.py') }} + restore-keys: deps-${{ inputs.os }}-np${{ inputs.numpy }}-py${{ inputs.python }}- + + - name: Install dependencies + run: | + python -m venv venv + ${{ inputs.activate_command }} + make install-deps install-dist + + build: + runs-on: ${{ inputs.os }} + needs: [ deps ] + name: build-${{ inputs.os }}-np${{ inputs.numpy }}-py${{ inputs.python }} + env: + TERM: xterm-256color # To colorize output of make tasks. + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ inputs.python }} + + - name: Use zstd for faster cache restore (windows) + if: ${{ startsWith(inputs.os, 'windows') }} + shell: cmd + run: echo C:\Program Files\Git\usr\bin>>"%GITHUB_PATH%" + + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: venv + key: deps-${{ inputs.os }}-np${{ inputs.numpy }}-py${{ inputs.python }}-${{ hashFiles('setup.py') }} + + - name: Cache build + uses: actions/cache@v3 + with: + path: venv/**/[Oo]pen[Ff]isca* + key: build-${{ inputs.os }}-np${{ inputs.numpy }}-py${{ inputs.python }}-${{ hashFiles('setup.py') }}-${{ github.sha }} + restore-keys: | + build-${{ inputs.os }}-np${{ inputs.numpy }}-py${{ inputs.python }}-${{ hashFiles('setup.py') }}- + build-${{ inputs.os }}-np${{ inputs.numpy }}-py${{ inputs.python }}- + + - name: Cache release + uses: actions/cache@v3 + with: + path: dist + key: release-${{ inputs.os }}-np${{ inputs.numpy }}-py${{ inputs.python }}-${{ hashFiles('setup.py') }}-${{ github.sha }} + + - name: Build package + run: | + ${{ inputs.activate_command }} + make install-test clean build diff --git a/.github/workflows/_lint.yaml b/.github/workflows/_lint.yaml new file mode 100644 index 0000000000..c618c02817 --- /dev/null +++ b/.github/workflows/_lint.yaml @@ -0,0 +1,62 @@ +name: Lint package + +on: + workflow_call: + inputs: + os: + required: true + type: string + + numpy: + required: true + type: string + + python: + required: true + type: string + + activate_command: + required: true + type: string + +jobs: + lint: + runs-on: ${{ inputs.os }} + name: lint-doc-${{ inputs.os }}-np${{ inputs.numpy }}-py${{ inputs.python }} + env: + TERM: xterm-256color # To colorize output of make tasks. + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ inputs.python }} + + - name: Use zstd for faster cache restore (windows) + if: ${{ startsWith(inputs.os, 'windows') }} + shell: cmd + run: echo C:\Program Files\Git\usr\bin>>"%GITHUB_PATH%" + + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: venv + key: deps-${{ inputs.os }}-np${{ inputs.numpy }}-py${{ inputs.python }}-${{ hashFiles('setup.py') }} + + - name: Lint doc + run: | + ${{ inputs.activate_command }} + make clean compile lint-doc + + - name: Lint styles + run: | + ${{ inputs.activate_command }} + make clean compile lint-style + + - name: Lint typing + run: | + ${{ inputs.activate_command }} + make clean compile lint-typing lint-typing-strict diff --git a/.github/workflows/_test.yaml b/.github/workflows/_test.yaml new file mode 100644 index 0000000000..eda7224bb7 --- /dev/null +++ b/.github/workflows/_test.yaml @@ -0,0 +1,72 @@ +name: Test package + +on: + workflow_call: + inputs: + os: + required: true + type: string + + numpy: + required: true + type: string + + python: + required: true + type: string + + activate_command: + required: true + type: string + +jobs: + test: + runs-on: ${{ inputs.os }} + name: test-core-${{ inputs.os }}-np${{ inputs.numpy }}-py${{ inputs.python }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + TERM: xterm-256color # To colorize output of make tasks. + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: ${{ inputs.python }} + + - name: Use zstd for faster cache restore (windows) + if: ${{ startsWith(inputs.os, 'windows') }} + shell: cmd + run: echo C:\Program Files\Git\usr\bin>>"%GITHUB_PATH%" + + - name: Cache dependencies + uses: actions/cache@v3 + with: + path: venv + key: deps-${{ inputs.os }}-np${{ inputs.numpy }}-py${{ inputs.python }}-${{ hashFiles('setup.py') }} + + - name: Cache build + uses: actions/cache@v3 + with: + path: venv/**/[Oo]pen[Ff]isca* + key: build-${{ inputs.os }}-np${{ inputs.numpy }}-py${{ inputs.python }}-${{ hashFiles('setup.py') }}-${{ github.sha }} + + - name: Run Openfisca Core tests + run: | + ${{ inputs.activate_command }} + make test-core + python -m coveralls --service=github + + - name: Run Country Template tests + if: ${{ startsWith(inputs.os, 'ubuntu') }} + run: | + ${{ inputs.activate_command }} + make test-country + + - name: Run Extension Template tests + if: ${{ startsWith(inputs.os, 'ubuntu') }} + run: | + ${{ inputs.activate_command }} + make test-extension diff --git a/.github/workflows/merge.yaml b/.github/workflows/merge.yaml new file mode 100644 index 0000000000..edd103504e --- /dev/null +++ b/.github/workflows/merge.yaml @@ -0,0 +1,185 @@ +name: OpenFisca-Core / Deploy package to PyPi & Conda + +on: + push: + branches: [master] + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +jobs: + setup: + strategy: + fail-fast: true + matrix: + os: [ubuntu-20.04, windows-latest] + numpy: [1.20.3] + python: [3.8.10, 3.7.9] # Patch version must be specified to avoid any cache confusion, since the cache key depends on the full Python version. If left unspecified, different patch versions could be allocated between jobs, and any such difference would lead to a cache not found error. + include: + - os: ubuntu-20.04 + activate_command: source venv/bin/activate + - os: windows-latest + activate_command: .\venv\Scripts\activate + uses: ./.github/workflows/_before.yaml + with: + os: ${{ matrix.os }} + numpy: ${{ matrix.numpy }} + python: ${{ matrix.python }} + activate_command: ${{ matrix.activate_command }} + + test: + needs: [setup] + strategy: + fail-fast: true + matrix: + os: [ubuntu-20.04, windows-latest] + numpy: [1.20.3] + python: [3.8.10, 3.7.9] # Patch version must be specified to avoid any cache confusion, since the cache key depends on the full Python version. If left unspecified, different patch versions could be allocated between jobs, and any such difference would lead to a cache not found error. + include: + - os: ubuntu-20.04 + activate_command: source venv/bin/activate + - os: windows-latest + activate_command: .\venv\Scripts\activate + uses: ./.github/workflows/_test.yaml + with: + os: ${{ matrix.os }} + numpy: ${{ matrix.numpy }} + python: ${{ matrix.python }} + activate_command: ${{ matrix.activate_command }} + + lint: + needs: [setup] + strategy: + fail-fast: true + matrix: + numpy: [1.20.3] + python: [3.8.10, 3.7.9] # Patch version must be specified to avoid any cache confusion, since the cache key depends on the full Python version. If left unspecified, different patch versions could be allocated between jobs, and any such difference would lead to a cache not found error. + uses: ./.github/workflows/_lint.yaml + with: + os: ubuntu-20.04 + numpy: ${{ matrix.numpy }} + python: ${{ matrix.python }} + activate_command: source venv/bin/activate + + # The idea behind these dependencies is we want to give feedback to + # contributors on the version number only after they have passed all tests, + # so they don't have to do it twice after changes happened to the main branch + # during the time they took to fix the tests. + check-version: + runs-on: ubuntu-20.04 + needs: [test, lint] + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Fetch all the tags + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.8.10 # Patch version must be specified to avoid any cache confusion, since the cache key depends on the full Python version. If left unspecified, different patch versions could be allocated between jobs, and any such difference would lead to a cache not found error. + + - name: Check version number has been properly updated + run: "${GITHUB_WORKSPACE}/.github/is-version-number-acceptable.sh" + + # GitHub Actions does not have a halt job option, to stop from deploying if + # no functional changes were found. We build a separate job to substitute the + # halt option. The `deploy` job is dependent on the output of the + # `check-for-functional-changes`job. + check-for-functional-changes: + runs-on: ubuntu-20.04 + needs: [check-version] # Last job to run + outputs: + status: ${{ steps.stop-early.outputs.status }} + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Fetch all the tags + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.8.10 # Patch version must be specified to avoid any cache confusion, since the cache key depends on the full Python version. If left unspecified, different patch versions could be allocated between jobs, and any such difference would lead to a cache not found error. + + - id: stop-early + run: if "${GITHUB_WORKSPACE}/.github/has-functional-changes.sh" ; then echo "::set-output name=status::success" ; fi # The `check-for-functional-changes` job should always succeed regardless of the `has-functional-changes` script's exit code. Consequently, we do not use that exit code to trigger deploy, but rather a dedicated output variable `status`, to avoid a job failure if the exit code is different from 0. Conversely, if the job fails the entire workflow would be marked as `failed` which is disturbing for contributors. + + publish-to-pypi: + runs-on: ubuntu-20.04 + needs: [check-for-functional-changes] + if: needs.check-for-functional-changes.outputs.status == 'success' + env: + PYPI_USERNAME: openfisca-bot + PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }} + CIRCLE_TOKEN: ${{ secrets.CIRCLECI_V1_OPENFISCADOC_TOKEN }} # Personal API token created in CircleCI to grant full read and write permissions + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Fetch all the tags + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.8.10 # Patch version must be specified to avoid any cache confusion, since the cache key depends on the full Python version. If left unspecified, different patch versions could be allocated between jobs, and any such difference would lead to a cache not found error. + + - name: Cache deps + uses: actions/cache@v3 + with: + path: venv + key: deps-ubuntu-20.04-np1.20.3-py3.8.10-${{ hashFiles('setup.py') }} + + - name: Cache build + uses: actions/cache@v3 + with: + path: venv/**/[oO]pen[fF]isca* + key: build-ubuntu-20.04-np1.20.3-py3.8.10-${{ hashFiles('setup.py') }}-${{ github.sha }} + + - name: Cache release + uses: actions/cache@v3 + with: + path: dist + key: release-ubuntu-20.04-np1.20.3-py3.8.10-${{ hashFiles('setup.py') }}-${{ github.sha }} + + - name: Upload package to PyPi + run: | + source venv/bin/activate + make publish + + - name: Update doc + run: | + curl -X POST --header "Content-Type: application/json" -d '{"branch":"master"}' https://circleci.com/api/v1.1/project/github/openfisca/openfisca-doc/build?circle-token=${{ secrets.CIRCLECI_V1_OPENFISCADOC_TOKEN }} + + publish-to-conda: + runs-on: ubuntu-20.04 + needs: [publish-to-pypi] + + steps: + - uses: conda-incubator/setup-miniconda@v2 + with: + auto-update-conda: true + python-version: 3.7.9 # Patch version must be specified to avoid any cache confusion, since the cache key depends on the full Python version. If left unspecified, different patch versions could be allocated between jobs, and any such difference would lead to a cache not found error. + channels: conda-forge + activate-environment: true + + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Fetch all the tags + + - name: Update meta.yaml + run: | + python3 -m pip install requests argparse + # Sleep to allow PyPi to update its API + sleep 60 + python3 .github/get_pypi_info.py -p OpenFisca-Core + + - name: Conda Config + run: | + conda install conda-build anaconda-client + conda info + conda config --set anaconda_upload yes + + - name: Conda build + run: conda build -c conda-forge --token ${{ secrets.ANACONDA_TOKEN }} --user openfisca .conda diff --git a/.github/workflows/push.yaml b/.github/workflows/push.yaml new file mode 100644 index 0000000000..96485aa149 --- /dev/null +++ b/.github/workflows/push.yaml @@ -0,0 +1,84 @@ +name: OpenFisca-Core / Pull request review + +on: + pull_request: + types: [assigned, opened, reopened, synchronize, ready_for_review] + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +jobs: + setup: + strategy: + fail-fast: true + matrix: + os: [ubuntu-20.04, windows-latest] + numpy: [1.20.3] + python: [3.8.10, 3.7.9] # Patch version must be specified to avoid any cache confusion, since the cache key depends on the full Python version. If left unspecified, different patch versions could be allocated between jobs, and any such difference would lead to a cache not found error. + include: + - os: ubuntu-20.04 + activate_command: source venv/bin/activate + - os: windows-latest + activate_command: .\venv\Scripts\activate + uses: ./.github/workflows/_before.yaml + with: + os: ${{ matrix.os }} + numpy: ${{ matrix.numpy }} + python: ${{ matrix.python }} + activate_command: ${{ matrix.activate_command }} + + test: + needs: [setup] + strategy: + fail-fast: true + matrix: + os: [ubuntu-20.04, windows-latest] + numpy: [1.20.3] + python: [3.8.10, 3.7.9] # Patch version must be specified to avoid any cache confusion, since the cache key depends on the full Python version. If left unspecified, different patch versions could be allocated between jobs, and any such difference would lead to a cache not found error. + include: + - os: ubuntu-20.04 + activate_command: source venv/bin/activate + - os: windows-latest + activate_command: .\venv\Scripts\activate + uses: ./.github/workflows/_test.yaml + with: + os: ${{ matrix.os }} + numpy: ${{ matrix.numpy }} + python: ${{ matrix.python }} + activate_command: ${{ matrix.activate_command }} + + lint: + needs: [setup] + strategy: + fail-fast: true + matrix: + numpy: [1.20.3] + python: [3.8.10, 3.7.9] # Patch version must be specified to avoid any cache confusion, since the cache key depends on the full Python version. If left unspecified, different patch versions could be allocated between jobs, and any such difference would lead to a cache not found error. + uses: ./.github/workflows/_lint.yaml + with: + os: ubuntu-20.04 + numpy: ${{ matrix.numpy }} + python: ${{ matrix.python }} + activate_command: source venv/bin/activate + + # The idea behind these dependencies is we want to give feedback to + # contributors on the version number only after they have passed all tests, + # so they don't have to do it twice after changes happened to the main branch + # during the time they took to fix the tests. + check-version: + runs-on: ubuntu-20.04 + needs: [test, lint] + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # Fetch all the tags + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.8.10 # Patch version must be specified to avoid any cache confusion, since the cache key depends on the full Python version. If left unspecified, different patch versions could be allocated between jobs, and any such difference would lead to a cache not found error. + + - name: Check version number has been properly updated + run: "${GITHUB_WORKSPACE}/.github/is-version-number-acceptable.sh" diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml deleted file mode 100644 index c2d5334e43..0000000000 --- a/.github/workflows/workflow.yml +++ /dev/null @@ -1,303 +0,0 @@ -name: OpenFisca-Core - -on: [ push, pull_request, workflow_dispatch ] - -jobs: - build: - runs-on: ubuntu-20.04 - env: - TERM: xterm-256color # To colorize output of make tasks. - - steps: - - name: Checkout - uses: actions/checkout@v2 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: 3.7.12 # Patch version must be specified to avoid any cache confusion, since the cache key depends on the full Python version. If left unspecified, different patch versions could be allocated between jobs, and any such difference would lead to a cache not found error. - - - name: Cache build - id: restore-build - uses: actions/cache@v2 - with: - path: ${{ env.pythonLocation }} - key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }} - 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 }}- - - - name: Build package - run: make install-deps install-dist install-test clean build - - - name: Cache release - id: restore-release - uses: actions/cache@v2 - with: - path: dist - key: release-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }} - - test-core: - runs-on: ubuntu-20.04 - needs: [ build ] - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - TERM: xterm-256color # To colorize output of make tasks. - - steps: - - uses: actions/checkout@v2 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: 3.7.12 - - - name: Cache build - id: restore-build - uses: actions/cache@v2 - with: - path: ${{ env.pythonLocation }} - key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }} - - - name: Run openfisca-core tests - run: make test-core - - - name: Submit coverage to Coveralls - run: coveralls --service=github - - test-country-template: - runs-on: ubuntu-20.04 - needs: [ build ] - env: - TERM: xterm-256color - - steps: - - uses: actions/checkout@v2 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: 3.7.12 - - - name: Cache build - id: restore-build - uses: actions/cache@v2 - with: - path: ${{ env.pythonLocation }} - key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }} - - - name: Run Country Template tests - run: make test-country - - test-extension-template: - runs-on: ubuntu-20.04 - needs: [ build ] - env: - TERM: xterm-256color - - steps: - - uses: actions/checkout@v2 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: 3.7.12 - - - name: Cache build - id: restore-build - uses: actions/cache@v2 - with: - path: ${{ env.pythonLocation }} - key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }} - - - name: Run Extension Template tests - run: make test-extension - - check-numpy: - runs-on: ubuntu-20.04 - needs: [ build ] - env: - TERM: xterm-256color - - steps: - - uses: actions/checkout@v2 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: 3.7.12 - - - name: Cache build - id: restore-build - uses: actions/cache@v2 - with: - path: ${{ env.pythonLocation }} - key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }} - - - name: Check NumPy typing against latest 3 minor versions - run: for i in {1..3}; do VERSION=$(${GITHUB_WORKSPACE}/.github/get-numpy-version.py prev) && pip install numpy==$VERSION && make check-types; done - - lint-files: - runs-on: ubuntu-20.04 - needs: [ build ] - env: - TERM: xterm-256color - - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 # Fetch all the tags - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: 3.7.12 - - - name: Cache build - id: restore-build - uses: actions/cache@v2 - with: - path: ${{ env.pythonLocation }} - key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }} - - - name: Run linters - run: make lint - - check-version: - runs-on: ubuntu-20.04 - needs: [ test-core, test-country-template, test-extension-template, check-numpy, lint-files ] # Last job to run - - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 # Fetch all the tags - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: 3.7.12 - - - name: Check version number has been properly updated - run: "${GITHUB_WORKSPACE}/.github/is-version-number-acceptable.sh" - - # GitHub Actions does not have a halt job option, to stop from deploying if no functional changes were found. - # We build a separate job to substitute the halt option. - # The `deploy` job is dependent on the output of the `check-for-functional-changes`job. - check-for-functional-changes: - runs-on: ubuntu-20.04 - if: github.ref == 'refs/heads/master' # Only triggered for the `master` branch - needs: [ check-version ] - outputs: - status: ${{ steps.stop-early.outputs.status }} - - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 # Fetch all the tags - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: 3.7.12 - - - id: stop-early - run: if "${GITHUB_WORKSPACE}/.github/has-functional-changes.sh" ; then echo "::set-output name=status::success" ; fi # The `check-for-functional-changes` job should always succeed regardless of the `has-functional-changes` script's exit code. Consequently, we do not use that exit code to trigger deploy, but rather a dedicated output variable `status`, to avoid a job failure if the exit code is different from 0. Conversely, if the job fails the entire workflow would be marked as `failed` which is disturbing for contributors. - - deploy: - runs-on: ubuntu-20.04 - needs: [ check-for-functional-changes ] - if: needs.check-for-functional-changes.outputs.status == 'success' - env: - PYPI_USERNAME: openfisca-bot - PYPI_PASSWORD: ${{ secrets.PYPI_PASSWORD }} - CIRCLE_TOKEN: ${{ secrets.CIRCLECI_V1_OPENFISCADOC_TOKEN }} # Personal API token created in CircleCI to grant full read and write permissions - - steps: - - uses: actions/checkout@v2 - with: - fetch-depth: 0 # Fetch all the tags - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: 3.7.12 - - - name: Cache build - id: restore-build - uses: actions/cache@v2 - with: - path: ${{ env.pythonLocation }} - key: build-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }} - - - name: Cache release - id: restore-release - uses: actions/cache@v2 - with: - path: dist - key: release-${{ env.pythonLocation }}-${{ hashFiles('setup.py') }}-${{ github.sha }} - - - 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" - - - name: Update doc - run: | - curl -X POST --header "Content-Type: application/json" -d '{"branch":"master"}' https://circleci.com/api/v1.1/project/github/openfisca/openfisca-doc/build?circle-token=${{ secrets.CIRCLECI_V1_OPENFISCADOC_TOKEN }} - - publish-to-conda: - runs-on: "ubuntu-20.04" - needs: [ deploy ] - strategy: - fail-fast: false - - steps: - - uses: conda-incubator/setup-miniconda@v2 - with: - auto-update-conda: true - python-version: 3.7.12 - 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 - # Sleep to allow PyPi to update its API - sleep 60 - python3 .github/get_pypi_info.py -p OpenFisca-Core - - - name: Conda Config - run: | - conda install conda-build anaconda-client - conda info - conda config --set anaconda_upload yes - - - name: Conda build - run: conda build -c conda-forge --token ${{ secrets.ANACONDA_TOKEN }} --user openfisca .conda - - test-on-windows: - runs-on: "windows-latest" - needs: [ publish-to-conda ] - - steps: - - uses: conda-incubator/setup-miniconda@v2 - with: - auto-update-conda: true - python-version: "3.7.9" # 3.7.12 don't exist on GHA Windows https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json - 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-core - - - name: Test openfisca - run: openfisca --help diff --git a/CHANGELOG.md b/CHANGELOG.md index c79d9d0de5..8c027d3a79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,29 +1,41 @@ # Changelog +# 39.0.0 [#1168](https://github.com/openfisca/openfisca-core/pull/1168) + +#### Breaking changes + +- Drop support for NumPy < 1.20 +- Drop support for Python < 3.7 + +#### New features + +- Add support for Python 3.8 +- Add CI for Windows + ### 38.0.3 [#1179](https://github.com/openfisca/openfisca-core/pull/1179) #### Bug fix - Do not install dependencies outside the `setup.py` - - Dependencies installed outside the `setup.py` are not taken into account by + - Dependencies installed outside the `setup.py` are not taken into account by `pip`'s dependency resolver. - - In case of conflicting transient dependencies, the last library installed + - In case of conflicting transient dependencies, the last library installed will "impose" its dependency version. - - This makes the installation and build of the library non-deterministic and - prone to unforeseen bugs caused by external changes in dependencies' + - This makes the installation and build of the library non-deterministic and + prone to unforeseen bugs caused by external changes in dependencies' versions. #### Note -A definite way to solve this issue is to clearly separate library dependencies -(with a `virtualenv`) and a universal dependency installer for CI requirements +A definite way to solve this issue is to clearly separate library dependencies +(with a `virtualenv`) and a universal dependency installer for CI requirements (like `pipx`), taking care of: - Always running tests inside the `virtualenv` (for example with `nox`). -- Always building outside of the `virtualenv` (for example with `poetry` +- Always building outside of the `virtualenv` (for example with `poetry` installed by `pipx`). -Moreover, it is indeed even better to have a lock file for dependencies, +Moreover, it is indeed even better to have a lock file for dependencies, using `pip freeze`) or with tools providing such features (`pipenv`, etc.). ### 38.0.2 [#1178](https://github.com/openfisca/openfisca-core/pull/1178) @@ -40,8 +52,8 @@ using `pip freeze`) or with tools providing such features (`pipenv`, etc.). # 38.0.0 [#989](https://github.com/openfisca/openfisca-core/pull/989) -> Note: Version `38.0.0` has been unpublished as `35.11.1` introduced a bug -> preventing users to load a tax-benefit system. Please use versions `38.0.2` +> Note: Version `38.0.0` has been unpublished as `35.11.1` introduced a bug +> preventing users to load a tax-benefit system. Please use versions `38.0.2` > and subsequents. #### New Features @@ -56,8 +68,8 @@ using `pip freeze`) or with tools providing such features (`pipenv`, etc.). ### 37.0.2 [#1170](https://github.com/openfisca/openfisca-core/pull/1170) -> Note: Version `37.0.2` has been unpublished as `35.11.1` introduced a bug -> preventing users to load a tax-benefit system. Please use versions `38.0.2` +> Note: Version `37.0.2` has been unpublished as `35.11.1` introduced a bug +> preventing users to load a tax-benefit system. Please use versions `38.0.2` > and subsequents. #### Technical changes @@ -66,8 +78,8 @@ using `pip freeze`) or with tools providing such features (`pipenv`, etc.). ### 37.0.1 [#1169](https://github.com/openfisca/openfisca-core/pull/1169) -> Note: Version `37.0.1` has been unpublished as `35.11.1` introduced a bug -> preventing users to load a tax-benefit system. Please use versions `38.0.2` +> Note: Version `37.0.1` has been unpublished as `35.11.1` introduced a bug +> preventing users to load a tax-benefit system. Please use versions `38.0.2` > and subsequents. #### Technical changes @@ -76,8 +88,8 @@ using `pip freeze`) or with tools providing such features (`pipenv`, etc.). # 37.0.0 [#1142](https://github.com/openfisca/openfisca-core/pull/1142) -> Note: Version `37.0.0` has been unpublished as `35.11.1` introduced a bug -> preventing users to load a tax-benefit system. Please use versions `38.0.2` +> Note: Version `37.0.0` has been unpublished as `35.11.1` introduced a bug +> preventing users to load a tax-benefit system. Please use versions `38.0.2` > and subsequents. #### Deprecations @@ -93,8 +105,8 @@ using `pip freeze`) or with tools providing such features (`pipenv`, etc.). # 36.0.0 [#1149](https://github.com/openfisca/openfisca-core/pull/1162) -> Note: Version `36.0.0` has been unpublished as `35.11.1` introduced a bug -> preventing users to load a tax-benefit system. Please use versions `38.0.2` +> Note: Version `36.0.0` has been unpublished as `35.11.1` introduced a bug +> preventing users to load a tax-benefit system. Please use versions `38.0.2` > and subsequents. #### Breaking changes @@ -105,8 +117,8 @@ using `pip freeze`) or with tools providing such features (`pipenv`, etc.). ## 35.12.0 [#1160](https://github.com/openfisca/openfisca-core/pull/1160) -> Note: Version `35.12.0` has been unpublished as `35.11.1` introduced a bug -> preventing users to load a tax-benefit system. Please use versions `38.0.2` +> Note: Version `35.12.0` has been unpublished as `35.11.1` introduced a bug +> preventing users to load a tax-benefit system. Please use versions `38.0.2` > and subsequents. #### New Features @@ -115,8 +127,8 @@ using `pip freeze`) or with tools providing such features (`pipenv`, etc.). ### 35.11.2 [#1166](https://github.com/openfisca/openfisca-core/pull/1166) -> Note: Version `35.11.2` has been unpublished as `35.11.1` introduced a bug -> preventing users to load a tax-benefit system. Please use versions `38.0.2` +> Note: Version `35.11.2` has been unpublished as `35.11.1` introduced a bug +> preventing users to load a tax-benefit system. Please use versions `38.0.2` > and subsequents. #### Technical changes @@ -125,8 +137,8 @@ using `pip freeze`) or with tools providing such features (`pipenv`, etc.). ### 35.11.1 [#1165](https://github.com/openfisca/openfisca-core/pull/1165) -> Note: Version `35.11.1` has been unpublished as it introduced a bug -> preventing users to load a tax-benefit system. Please use versions `38.0.2` +> Note: Version `35.11.1` has been unpublished as it introduced a bug +> preventing users to load a tax-benefit system. Please use versions `38.0.2` > and subsequents. #### Bug fix @@ -207,7 +219,7 @@ using `pip freeze`) or with tools providing such features (`pipenv`, etc.). #### New Features - Introduce `rate_from_bracket_indice` method on `RateTaxScaleLike` class - - Allows for the determination of the tax rate based on the tax bracket indice + - Allows for the determination of the tax rate based on the tax bracket index - Introduce `rate_from_tax_base` method on `RateTaxScaleLike` class - Allows for the determination of the tax rate based on the tax base @@ -430,8 +442,8 @@ _Note: this version has been unpublished due to an issue introduced by NumPy upg #### Bug fix - Repair expansion of axes on a variable given as input - - When expanding axes, the expected behavour is to override any input value for the requested variable and period - - As longs as we passed some input for a variable on a period, it was not being overrode, creating a NumPy's error (boradcasting) + - When expanding axes, the expected behaviour is to override any input value for the requested variable and period + - As longs as we passed some input for a variable on a period, it was not being overrode, creating a NumPy's error (broadcasting) - By additionally checking that an input was given, now we make that the array has the correct shape by constructing it with NumPy's tile with a shape equal to the number of the axis expansion count requested. ### 35.3.2 [#992](https://github.com/openfisca/openfisca-core/pull/992) @@ -499,7 +511,7 @@ _Note: this version has been unpublished due to an issue introduced by NumPy upg #### Technical changes -- Improve error message when laoding parameters file to detect the problematic file +- Improve error message when loading parameters file to detect the problematic file ### 35.0.3 [#961](https://github.com/openfisca/openfisca-core/pull/961) @@ -513,7 +525,7 @@ _Note: this version has been unpublished due to an issue introduced by NumPy upg #### Technical changes -- Update dependency: `flask-cors` (`Flask` extension for Cross Origin Resouce Sharing) +- Update dependency: `flask-cors` (`Flask` extension for Cross Origin Resource Sharing) ### 35.0.1 [#968](https://github.com/openfisca/openfisca-core/pull/968) @@ -773,7 +785,7 @@ _Note: this version has been unpublished due to an issue introduced by it. Pleas ### 34.4.4 [#908](https://github.com/openfisca/openfisca-core/pull/908) -- Make parameter cloning return clones that are truly independant from their source +- Make parameter cloning return clones that are truly independent from their source - Before this PR, editing the clone of a parameter tree would change the initial tree - Only impacts reforms that edit parameters tree @@ -2135,7 +2147,7 @@ sum_salary = person.household.sum(salaries) # The sum of the salaries of the pe >>> [4000, 4000, 4000, 4000] # Has the dimension of persons (4) ``` -This is a breaking change, as all the adaptations (such as [this one](https://github.com/openfisca/openfisca-france/blob/18.11.0/openfisca_france/model/prestations/minima_sociaux/rsa.py#L375-L376)) used to overcome these inconsistensies must be removed. +This is a breaking change, as all the adaptations (such as [this one](https://github.com/openfisca/openfisca-france/blob/18.11.0/openfisca_france/model/prestations/minima_sociaux/rsa.py#L375-L376)) used to overcome these inconsistencies must be removed. ## 21.5.0 [#621](https://github.com/openfisca/openfisca-core/pull/621) @@ -2336,7 +2348,7 @@ class housing_occupancy_status(Variable): - When using the Python API (`set_input`), the three following inputs are accepted: - The enum item (e.g. HousingOccupancyStatus.tenant) - The enum string identifier (e.g. "tenant") - - The enum item index, though this is not recommanded. + - The enum item index, though this is not recommended. - If you rely on index, make sure to specify an `__order__` attribute to all your enums to make sure each intem has the right index. See the enum34 [doc](https://pypi.python.org/pypi/enum34/1.1.1). > Example: @@ -2840,8 +2852,8 @@ For more information, check the [documentation](https://openfisca.org/doc/coding #### Technical changes * Refactor the internal representation and the interface of legislation parameters - - The parameters of a legislation are wraped into the classes `Node`, `Parameter`, `Scale`, `Bracket`, `ValuesHistory`, `ValueAtInstant` instead of bare python dict. - - The parameters of a legislation at a given instant are wraped into the classes `NodeAtInstant`, `ValueAtInstant` and tax scales instead of bare python objects. + - The parameters of a legislation are wrapped into the classes `Node`, `Parameter`, `Scale`, `Bracket`, `ValuesHistory`, `ValueAtInstant` instead of bare python dict. + - The parameters of a legislation at a given instant are wrapped into the classes `NodeAtInstant`, `ValueAtInstant` and tax scales instead of bare python objects. - The file `parameters.py` and the classes defined inside are responsible both for loading and accessing the parameters. Before the loading was implemented in `legislationsxml.py` and the other processings were implemented in `legislations.py` - The validation of the XML files was performed against a XML schema defined in `legislation.xsd`. Now the YAML files are loaded with the library `yaml` and then validated in basic Python. @@ -2852,7 +2864,7 @@ For more information, check the [documentation](https://openfisca.org/doc/coding - `Simulation.get_compact_legislation()` -> `Simulation._get_parameters_at_instant()` - `Simulation.get_baseline_compact_legislation()` -> `Simulation._get_baseline_parameters_at_instant()` -* The optionnal parameter `traced_simulation` is removed in function `TaxBenefitSystem.get_compact_legislation()` (now `TaxBenefitSystem.get_parameters_at_instant()`). This parameter had no effect. +* The optional parameter `traced_simulation` is removed in function `TaxBenefitSystem.get_compact_legislation()` (now `TaxBenefitSystem.get_parameters_at_instant()`). This parameter had no effect. * The optional parameter `with_source_file_infos` is removed in functions `TaxBenefitSystem.compute_legislation()` (now `TaxBenefitSystem._compute_parameters()`) and `TaxBenefitSystem.get_legislation()`. This parameter had no effect. @@ -2870,7 +2882,7 @@ For more information, check the [documentation](https://openfisca.org/doc/coding In the preview web API, for variables of type `Enum`: * Accept and recommend to use strings as simulation inputs, instead of the enum indices. - - For instance, `{"housing_occupancy_status": {"2017-01": "Tenant"}}` is now accepted and prefered to `{"housing_occupancy_status": {"2017-01": 0}}`). + - For instance, `{"housing_occupancy_status": {"2017-01": "Tenant"}}` is now accepted and preferred to `{"housing_occupancy_status": {"2017-01": 0}}`). - Using the enum indices as inputs is _still accepted_ for backward compatibility, but _should not_ be encouraged. * Return strings instead of enum indices. - For instance, is `housing_occupancy_status` is calculated for `2017-01`, `{"housing_occupancy_status": {"2017-01": "Tenant"}}` is now returned, instead of `{"housing_occupancy_status": {"2017-01": 0}}`. @@ -2916,7 +2928,7 @@ In the preview web API, for variables of type `Enum`: - This attribute is the legislative reference of a variable. - As previously, this attribute can be a string, or a list of strings. * Rename `Variable` attribute `reference` to `baseline_variable` - - This attibute is, for a variable defined in a reform, the baseline variable the reform variable is replacing. + - This attribute is, for a variable defined in a reform, the baseline variable the reform variable is replacing. * Remove variable attribute `law_reference` * Rename `TaxBenefitSystem.reference` to `TaxBenefitSystem.baseline` * Rename `TaxBenefitSystem.get_reference_compact_legislation` to `TaxBenefitSystem.get_baseline_compact_legislation` @@ -3194,7 +3206,7 @@ These breaking changes only concern variable and tax and benefit system **metada # 9.0.0 -* Make sure identic periods are stringified the same way +* Make sure identical periods are stringified the same way * _Breaking changes_: - Change `periods.period` signature. - It now only accepts strings. @@ -3231,7 +3243,7 @@ These breaking changes only concern variable and tax and benefit system **metada ## 6.1.0 * Move `base.py` content (file usually located in country packages) to core module `formula_toolbox` so that it can be reused by all countries -* Use `AbstractScenario` if no custom scenario is defined for a tax and benefit sytem +* Use `AbstractScenario` if no custom scenario is defined for a tax and benefit system # 6.0.0 @@ -3273,7 +3285,7 @@ These breaking changes only concern variable and tax and benefit system **metada * Improve `openfisca-run-test` script - Make country package detection more robust (it only worked for packages installed in editable mode) - Use spaces instead of commas as separator in the script arguments when loading several extensions or reforms (this is more standard) -* Refactor the `scripts` module to seperate the logic specific to yaml test running from the one that can be re-used by any script which needs to build a tax and benefit system. +* Refactor the `scripts` module to separate the logic specific to yaml test running from the one that can be re-used by any script which needs to build a tax and benefit system. # 5.0.0 @@ -3291,7 +3303,7 @@ These breaking changes only concern variable and tax and benefit system **metada ### 4.3.4 -* Fix occasionnal `NaN` creation in `MarginalRateTaxScale.calc` resulting from `0 * numpy.inf` +* Fix occasional `NaN` creation in `MarginalRateTaxScale.calc` resulting from `0 * numpy.inf` ### 4.3.3 @@ -3350,8 +3362,8 @@ Unlike simple formulas, a `DatedVariable` have several functions. We thus need t ### 4.1.2-Beta * Enable simulation initialization with only legacy roles - * New roles are in this case automatically infered - * Positions are always infered from persons entity id + * New roles are in this case automatically inferred + * Positions are always inferred from persons entity id ### 4.1.1-Beta @@ -3455,7 +3467,7 @@ Unlike simple formulas, a `DatedVariable` have several functions. We thus need t * Metaclasses are not used anymore. * New API for TaxBenefitSystem * Columns are now stored in the TaxBenefitSystem, not in entities. -* New API for rerforms. +* New API for reforms. * XmlBasedTaxBenefitSystem is deprecated, and MultipleXmlBasedTaxBenefitSystem renamed to TaxBenefitSystem ## 1.1.0 – [diff](https://github.com/openfisca/openfisca-core/compare/1.0.0...1.1.0) @@ -3469,7 +3481,7 @@ Unlike simple formulas, a `DatedVariable` have several functions. We thus need t ## 0.5.4 – [diff](https://github.com/openfisca/openfisca-core/compare/0.5.3...0.5.4) * Merge pull request #382 from openfisca/fix-sum-by-entity -* The result size must be the targent entity'one +* The result size must be the target entity's one ## 0.5.3 – [diff](https://github.com/openfisca/openfisca-core/compare/0.5.2...0.5.3) diff --git a/README.md b/README.md index 3974b4908c..2d134a2c74 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,9 @@ This package contains the core features of OpenFisca, which are meant to be used ## Environment -OpenFisca runs on Python 3.7. More recent versions should work but are not tested. +OpenFisca is tested against Python 3.8 and 3.7, yet newer versions should work. -OpenFisca also relies strongly on NumPy. The last four minor versions should work, but only the latest/stable is tested. +OpenFisca also depends on NumPy and is tested against v1.20. ## Installation diff --git a/openfisca_core/holders/holder.py b/openfisca_core/holders/holder.py index ae7e3fbcec..ea5feb66ae 100644 --- a/openfisca_core/holders/holder.py +++ b/openfisca_core/holders/holder.py @@ -198,12 +198,12 @@ def set_input( >>> holder = Holder(variable, population) >>> holder.set_input("2018", numpy.array([12.5, 14])) - >>> holder.get_array("2018") - array([12, 14], dtype=int32) + >>> holder.get_array("2018").tolist() + [12, 14] >>> holder.set_input("2018", [12.5, 14]) - >>> holder.get_array("2018") - array([12, 14], dtype=int32) + >>> holder.get_array("2018").tolist() + [12, 14] .. _documentation: https://openfisca.org/doc/coding-the-legislation/35_periods.html#set-input-automatically-process-variable-inputs-defined-for-periods-not-matching-the-definition-period diff --git a/openfisca_core/parameters/config.py b/openfisca_core/parameters/config.py index e9a3041ae8..420eb910e1 100644 --- a/openfisca_core/parameters/config.py +++ b/openfisca_core/parameters/config.py @@ -1,21 +1,13 @@ -import warnings -import os import yaml import typing -from openfisca_core.warnings import LibYAMLWarning try: from yaml import CLoader as Loader + except ImportError: - message = [ - "libyaml is not installed in your environment.", - "This can make OpenFisca slower to start.", - "Once you have installed libyaml, run 'pip uninstall pyyaml && pip install pyyaml --no-cache-dir'", - "so that it is used in your Python environment." + os.linesep - ] - warnings.warn(" ".join(message), LibYAMLWarning) - from yaml import Loader # type: ignore # (see https://github.com/python/mypy/issues/1153#issuecomment-455802270) + # (see https://github.com/python/mypy/issues/1153#issuecomment-455802270) + from yaml import SafeLoader as Loader # type: ignore # 'unit' and 'reference' are only listed here for backward compatibility. # It is now recommended to include them in metadata, until a common consensus emerges. diff --git a/openfisca_core/tools/test_runner.py b/openfisca_core/tools/test_runner.py index 4bdc238ce0..551dce94c0 100644 --- a/openfisca_core/tools/test_runner.py +++ b/openfisca_core/tools/test_runner.py @@ -8,7 +8,6 @@ import sys import textwrap import traceback -import warnings import pytest @@ -16,7 +15,6 @@ from openfisca_core.simulation_builder import SimulationBuilder from openfisca_core.tools import assert_near from openfisca_core.types import TaxBenefitSystem -from openfisca_core.warnings import LibYAMLWarning class Options(TypedDict, total = False): @@ -74,17 +72,13 @@ def build_test(params: Dict[str, Any]) -> Test: def import_yaml(): import yaml + try: from yaml import CLoader as Loader + except ImportError: - message = [ - "libyaml is not installed in your environment.", - "This can make your test suite slower to run. Once you have installed libyaml, ", - "run 'pip uninstall pyyaml && pip install pyyaml --no-cache-dir'", - "so that it is used in your Python environment." - ] - warnings.warn(" ".join(message), LibYAMLWarning) from yaml import SafeLoader as Loader + return yaml, Loader diff --git a/openfisca_core/warnings/__init__.py b/openfisca_core/warnings/__init__.py index 9e450c8702..5f6da1aecf 100644 --- a/openfisca_core/warnings/__init__.py +++ b/openfisca_core/warnings/__init__.py @@ -21,6 +21,5 @@ # # See: https://www.python.org/dev/peps/pep-0008/#imports -from .libyaml_warning import LibYAMLWarning # noqa: F401 from .memory_warning import MemoryConfigWarning # noqa: F401 from .tempfile_warning import TempfileWarning # noqa: F401 diff --git a/openfisca_core/warnings/libyaml_warning.py b/openfisca_core/warnings/libyaml_warning.py deleted file mode 100644 index 361a1688ad..0000000000 --- a/openfisca_core/warnings/libyaml_warning.py +++ /dev/null @@ -1,5 +0,0 @@ -class LibYAMLWarning(UserWarning): - """ - Custom warning for LibYAML not installed. - """ - pass diff --git a/openfisca_tasks/install.mk b/openfisca_tasks/install.mk index 0a8c81115b..3c81106111 100644 --- a/openfisca_tasks/install.mk +++ b/openfisca_tasks/install.mk @@ -1,20 +1,25 @@ ## Uninstall project's dependencies. uninstall: @$(call print_help,$@:) - @pip freeze | grep -v "^-e" | sed "s/@.*//" | xargs pip uninstall -y + @python -m pip freeze | grep -v "^-e" | sed "s/@.*//" | xargs python -m pip uninstall -y + @$(call print_pass,$@:) ## Install project's overall dependencies install-deps: @$(call print_help,$@:) - @pip install --upgrade pip + @python -m pip install --upgrade pip + @$(call print_pass,$@:) ## Install project's development dependencies. install-edit: @$(call print_help,$@:) - @pip install --upgrade --editable ".[dev]" + @python -m pip install --upgrade --editable ".[dev]" + @$(call print_pass,$@:) ## Delete builds and compiled python files. clean: @$(call print_help,$@:) @ls -d * | grep "build\|dist" | xargs rm -rf + @find . -name "__pycache__" | xargs rm -rf @find . -name "*.pyc" | xargs rm -rf + @$(call print_pass,$@:) diff --git a/openfisca_tasks/lint.mk b/openfisca_tasks/lint.mk index 115c6267bb..99c834371d 100644 --- a/openfisca_tasks/lint.mk +++ b/openfisca_tasks/lint.mk @@ -1,17 +1,17 @@ ## Lint the codebase. -lint: check-syntax-errors check-style lint-doc check-types lint-typing-strict +lint: compile lint-doc lint-style lint-typing lint-typing-strict @$(call print_pass,$@:) ## Compile python files to check for syntax errors. -check-syntax-errors: . +compile: . @$(call print_help,$@:) @python -m compileall -q $? @$(call print_pass,$@:) ## Run linters to check for syntax and style errors. -check-style: $(shell git ls-files "*.py") +lint-style: $(shell git ls-files "*.py") @$(call print_help,$@:) - @flake8 $? + @python -m flake8 $? @$(call print_pass,$@:) ## Run linters to check for syntax and style errors in the doc. @@ -29,14 +29,14 @@ lint-doc-%: @## able to integrate documentation improvements progresively. @## @$(call print_help,$(subst $*,%,$@:)) - @flake8 --select=D101,D102,D103,DAR openfisca_core/$* - @pylint openfisca_core/$* + @python -m flake8 --select=D101,D102,D103,DAR openfisca_core/$* + @python -m pylint openfisca_core/$* @$(call print_pass,$@:) ## Run static type checkers for type errors. -check-types: +lint-typing: @$(call print_help,$@:) - @mypy --package openfisca_core --package openfisca_web_api + @python -m mypy --package openfisca_core --package openfisca_web_api @$(call print_pass,$@:) ## Run static type checkers for type errors (strict). @@ -48,7 +48,7 @@ lint-typing-strict: \ ## Run static type checkers for type errors (strict). lint-typing-strict-%: @$(call print_help,$(subst $*,%,$@:)) - @mypy \ + @python -m mypy \ --cache-dir .mypy_cache-openfisca_core.$* \ --implicit-reexport \ --strict \ @@ -58,5 +58,5 @@ lint-typing-strict-%: ## Run code formatters to correct style errors. format-style: $(shell git ls-files "*.py") @$(call print_help,$@:) - @autopep8 $? + @python -m autopep8 $? @$(call print_pass,$@:) diff --git a/openfisca_tasks/publish.mk b/openfisca_tasks/publish.mk index aeeb51141b..412122595c 100644 --- a/openfisca_tasks/publish.mk +++ b/openfisca_tasks/publish.mk @@ -3,7 +3,7 @@ ## Install project's build dependencies. install-dist: @$(call print_help,$@:) - @pip install .[ci,dev] + @python -m pip install .[ci,dev] @$(call print_pass,$@:) ## Build & install openfisca-core for deployment and publishing. @@ -12,6 +12,16 @@ build: @## of openfisca-core, the same we put in the hands of users and reusers. @$(call print_help,$@:) @python -m build - @pip uninstall --yes openfisca-core - @find dist -name "*.whl" -exec pip install --no-deps {} \; + @python -m pip uninstall --yes openfisca-core + @find dist -name "*.whl" -exec python -m pip install --no-deps {} \; + @$(call print_pass,$@:) + +## Upload to PyPi. +publish: + @$(call print_help,$@:) + @python -m twine upload dist/* \ + --username $PYPI_USERNAME \ + --password $PYPI_PASSWORD + @git tag `python setup.py --version` + @git push --tags # update the repository version @$(call print_pass,$@:) diff --git a/openfisca_tasks/test_code.mk b/openfisca_tasks/test_code.mk index 63fdd4386a..22a3f47f0b 100644 --- a/openfisca_tasks/test_code.mk +++ b/openfisca_tasks/test_code.mk @@ -1,8 +1,12 @@ ## The openfisca command module. openfisca = openfisca_core.scripts.openfisca_command -## The path to the installed packages. -python_packages = $(shell python -c "import sysconfig; print(sysconfig.get_paths()[\"purelib\"])") +## The path to the templates' tests. +ifeq ($(OS),Windows_NT) + tests = $(shell python -c "import os, $(1); print(repr(os.path.join($(1).__path__[0], 'tests')))") +else + tests = $(shell python -c "import $(1); print($(1).__path__[0])")/tests +endif ## Run all tasks required for testing. install: install-deps install-edit install-test @@ -10,8 +14,9 @@ install: install-deps install-edit install-test ## Enable regression testing with template repositories. install-test: @$(call print_help,$@:) - @pip install --upgrade --no-dependencies openfisca-country-template - @pip install --upgrade --no-dependencies openfisca-extension-template + @python -m pip install --upgrade --no-deps openfisca-country-template + @python -m pip install --upgrade --no-deps openfisca-extension-template + @$(call print_pass,$@:) ## Run openfisca-core & country/extension template tests. test-code: test-core test-country test-extension @@ -29,15 +34,15 @@ test-code: test-core test-country test-extension @$(call print_pass,$@:) ## Run openfisca-core tests. -test-core: $(shell pytest --quiet --quiet --collect-only 2> /dev/null | cut -f 1 -d ":") +test-core: $(shell git ls-files "*test_*.py") @$(call print_help,$@:) - @pytest --quiet --capture=no --xdoctest --xdoctest-verbose=0 \ + @python -m pytest --quiet --capture=no --xdoctest --xdoctest-verbose=0 \ openfisca_core/commons \ openfisca_core/holders \ openfisca_core/types @PYTEST_ADDOPTS="$${PYTEST_ADDOPTS} ${pytest_args}" \ - coverage run -m \ - ${openfisca} test $? \ + python -m coverage run -m ${openfisca} test \ + $? \ ${openfisca_args} @$(call print_pass,$@:) @@ -45,7 +50,8 @@ test-core: $(shell pytest --quiet --quiet --collect-only 2> /dev/null | cut -f 1 test-country: @$(call print_help,$@:) @PYTEST_ADDOPTS="$${PYTEST_ADDOPTS} ${pytest_args}" \ - openfisca test ${python_packages}/openfisca_country_template/tests \ + python -m ${openfisca} test \ + $(call tests,"openfisca_country_template") \ --country-package openfisca_country_template \ ${openfisca_args} @$(call print_pass,$@:) @@ -54,7 +60,8 @@ test-country: test-extension: @$(call print_help,$@:) @PYTEST_ADDOPTS="$${PYTEST_ADDOPTS} ${pytest_args}" \ - openfisca test ${python_packages}/openfisca_extension_template/tests \ + python -m ${openfisca} test \ + $(call tests,"openfisca_extension_template") \ --country-package openfisca_country_template \ --extensions openfisca_extension_template \ ${openfisca_args} @@ -63,4 +70,5 @@ test-extension: ## Print the coverage report. test-cov: @$(call print_help,$@:) - @coverage report + @python -m coverage report + @$(call print_pass,$@:) diff --git a/setup.py b/setup.py index 4d1c1b8ee9..1b1307e2b8 100644 --- a/setup.py +++ b/setup.py @@ -26,47 +26,47 @@ # functional and integration breaks caused by external code updates. general_requirements = [ - 'PyYAML >= 3.10', - 'dpath >= 1.5.0, < 3.0.0', + 'PyYAML >= 6.0.0, < 7.0.0', + 'dpath >= 2.1.0, < 3.0.0', 'importlib-metadata < 4.3.0', # Required for Python 3.7 and Flake8 'nptyping == 1.4.4', - 'numexpr >= 2.7.0, <= 3.0', - 'numpy >= 1.11, < 1.21', - 'psutil >= 5.4.7, < 6.0.0', - 'pytest >= 4.4.1, < 6.0.0', # For openfisca test + 'numexpr >= 2.8.0, <= 3.0.0', + 'numpy >= 1.20, < 1.21', + 'psutil >= 5.9.0, < 6.0.0', + 'pytest >= 5.4.0, < 6.0.0', # For openfisca test 'sortedcontainers == 2.2.2', - 'typing-extensions >= 4.0.0, < 5.0.0', + 'typing-extensions >= 4.4.0, < 5.0.0', ] api_requirements = [ 'markupsafe == 2.0.1', # While flask revision < 2 'flask == 1.1.4', 'flask-cors == 3.0.10', - 'gunicorn >= 20.0.0, < 21.0.0', + 'gunicorn >= 20.1.0, < 21.0.0', 'werkzeug >= 1.0.0, < 2.0.0', ] dev_requirements = [ - 'autopep8 >= 1.4.0, < 1.6.0', - 'coverage >= 6.0.2, < 7.0.0', + 'autopep8 >= 1.5.0, < 1.6.0', + 'coverage >= 6.5.0, < 7.0.0', 'darglint == 1.8.0', 'flake8 >= 4.0.0, < 4.1.0', - 'flake8-bugbear >= 19.3.0, < 20.0.0', + 'flake8-bugbear >= 19.8.0, < 20.0.0', 'flake8-docstrings == 1.6.0', 'flake8-print >= 3.1.0, < 4.0.0', 'flake8-rst-docstrings == 0.2.3', 'idna >= 3.4.0, < 4.0.0', - 'isort >= 5.0.0, < 6.0.0', + 'isort >= 5.11.0, < 6.0.0', 'mypy == 0.910', 'openapi-spec-validator >= 0.5.0, < 0.6.0', 'pycodestyle >= 2.8.0, < 2.9.0', 'pylint == 2.10.2', - 'xdoctest >= 1.0.0, < 2.0.0', + 'xdoctest >= 1.1.0, < 2.0.0', ] + api_requirements setup( name = 'OpenFisca-Core', - version = '38.0.3', + version = '39.0.0', author = 'OpenFisca Team', author_email = 'contact@openfisca.org', classifiers = [ @@ -74,8 +74,6 @@ 'License :: OSI Approved :: GNU Affero General Public License v3', 'Operating System :: POSIX', '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', @@ -85,15 +83,8 @@ license = 'https://www.fsf.org/licensing/licenses/agpl-3.0.html', license_files = ("LICENSE",), url = 'https://github.com/openfisca/openfisca-core', - long_description=long_description, - long_description_content_type='text/markdown', - - data_files = [ - ( - 'share/openfisca/openfisca-core', - ['CHANGELOG.md', 'README.md'], - ), - ], + long_description = long_description, + long_description_content_type = 'text/markdown', entry_points = { 'console_scripts': [ 'openfisca=openfisca_core.scripts.openfisca_command:main', @@ -104,12 +95,14 @@ 'web-api': api_requirements, 'dev': dev_requirements, 'ci': [ - 'build >= 0.9.0, < 1.0.0', - 'coveralls >= 3.0.0, < 4.0.0', + 'build >= 0.10.0, < 1.0.0', + 'coveralls >= 3.3.0, < 4.0.0', 'twine >= 4.0.0, < 5.0.0', 'wheel < 1.0.0', ], - 'tracker': ['openfisca-tracker == 0.4.0'], + 'tracker': [ + 'openfisca-tracker == 0.4.0', + ], }, include_package_data = True, # Will read MANIFEST.in install_requires = general_requirements, diff --git a/tests/core/test_yaml.py b/tests/core/test_yaml.py index f63e37ff39..d5a54d8863 100644 --- a/tests/core/test_yaml.py +++ b/tests/core/test_yaml.py @@ -1,5 +1,6 @@ import os import subprocess +import sys import pytest import openfisca_extension_template @@ -98,6 +99,7 @@ def test_shell_script_with_reform(): subprocess.check_call(command, stdout = devnull, stderr = devnull) +@pytest.mark.skipif(sys.platform == "win32", reason = "Fails on Windows") def test_shell_script_with_extension(): tests_dir = os.path.join(openfisca_extension_template.__path__[0], 'tests') command = ['openfisca', 'test', tests_dir, '-c', 'openfisca_country_template', '-e', 'openfisca_extension_template'] diff --git a/tests/web_api/test_parameters.py b/tests/web_api/test_parameters.py index 8f65cca9af..bb01ed561c 100644 --- a/tests/web_api/test_parameters.py +++ b/tests/web_api/test_parameters.py @@ -2,6 +2,7 @@ import json import pytest import re +import sys # /parameters @@ -43,6 +44,7 @@ def test_legacy_parameter_route(test_client): assert response.status_code == client.OK +@pytest.mark.skipif(sys.platform == "win32", reason = "Fails on Windows") def test_parameter_values(test_client): response = test_client.get('/parameter/taxes/income_tax_rate') parameter = json.loads(response.data) diff --git a/tests/web_api/test_variables.py b/tests/web_api/test_variables.py index 4581608aa8..a7f698f6dc 100644 --- a/tests/web_api/test_variables.py +++ b/tests/web_api/test_variables.py @@ -2,6 +2,7 @@ import json import pytest import re +import sys def assert_items_equal(x, y): @@ -68,6 +69,7 @@ def test_input_variable_value(expected_values, input_variable_response): check_input_variable_value(*expected_values, input_variable=input_variable) +@pytest.mark.skipif(sys.platform == "win32", reason = "Fails on Windows") def test_input_variable_github_url(test_client): input_variable_response = test_client.get('/variable/income_tax') input_variable = json.loads(input_variable_response.data.decode('utf-8')) @@ -97,6 +99,7 @@ def test_variable_value(expected_values, test_client): check_variable_value(*expected_values, variable=variable) +@pytest.mark.skipif(sys.platform == "win32", reason = "Fails on Windows") def test_variable_formula_github_link(test_client): variable_response = test_client.get('/variable/income_tax') variable = json.loads(variable_response.data.decode('utf-8'))