[Git][debian-gis-team/pint-xarray][upstream] New upstream version 0.4
Antonio Valentino (@antonio.valentino)
gitlab at salsa.debian.org
Sat Jun 29 14:33:10 BST 2024
Antonio Valentino pushed to branch upstream at Debian GIS Project / pint-xarray
Commits:
a0156ef8 by Antonio Valentino at 2024-06-29T15:15:40+02:00
New upstream version 0.4
- - - - -
22 changed files:
- + .flake8
- + .github/dependabot.yml
- .github/workflows/ci-additional.yml
- .github/workflows/ci.yml
- .github/workflows/nightly.yml
- .github/workflows/pypi.yaml
- .pre-commit-config.yaml
- .readthedocs.yaml
- ci/install-upstream-dev.sh
- ci/requirements.txt
- docs/conf.py
- docs/examples/plotting.ipynb
- docs/requirements.txt
- docs/whats-new.rst
- pint_xarray/accessors.py
- pint_xarray/conversion.py
- pint_xarray/formatting.py
- pint_xarray/tests/test_conversion.py
- pint_xarray/tests/utils.py
- pyproject.toml
- − setup.cfg
- − setup.py
Changes:
=====================================
.flake8
=====================================
@@ -0,0 +1,13 @@
+[flake8]
+ignore =
+ # E203: whitespace before ':' - doesn't work well with black
+ # E402: module level import not at top of file
+ # E501: line too long - let black worry about that
+ # E731: do not assign a lambda expression, use a def
+ # W503: line break before binary operator
+ E203, E402, E501, E731, W503
+exclude =
+ .eggs
+ doc
+builtins =
+ ellipsis
=====================================
.github/dependabot.yml
=====================================
@@ -0,0 +1,6 @@
+version: 2
+updates:
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
=====================================
.github/workflows/ci-additional.yml
=====================================
@@ -17,20 +17,26 @@ jobs:
name: Doctests
runs-on: ubuntu-latest
if: github.repository == 'xarray-contrib/pint-xarray'
+
+ strategy:
+ fail-fast: false
+ matrix:
+ python-version: ["3.12"]
+
steps:
- name: checkout
- uses: actions/checkout at v3
+ uses: actions/checkout at v4
- name: setup python
- uses: actions/setup-python at v3
+ uses: actions/setup-python at v5
with:
- python-version: "3.10"
+ python-version: ${{ matrix.python-version }}
- name: initialize cache
- uses: actions/cache at v2
+ uses: actions/cache at v4
with:
path: ~/.cache/pip
- key: ${{ runner.os }}-pip-py3.10-${{ hashFiles('ci/requirements/**.txt') }}
+ key: ${{ runner.os }}-pip-py${{ matrix.python-version }}-${{ hashFiles('ci/requirements/**.txt') }}
restore-keys: |
- ${{ runner.os }}-pip-py3.10-
+ ${{ runner.os }}-pip-py${{ matrix.python-version }}-
- name: upgrade pip
run: |
python -m pip install --upgrade pip setuptools wheel
=====================================
.github/workflows/ci.yml
=====================================
@@ -20,10 +20,10 @@ jobs:
outputs:
triggered: ${{ steps.detect-trigger.outputs.trigger-found }}
steps:
- - uses: actions/checkout at v3
+ - uses: actions/checkout at v4
with:
fetch-depth: 2
- - uses: keewis/ci-trigger at v1.1
+ - uses: xarray-contrib/ci-trigger at v1
id: detect-trigger
with:
keyword: "[skip-ci]"
@@ -32,6 +32,9 @@ jobs:
name: ${{ matrix.os }} py${{ matrix.python-version }}
runs-on: ${{ matrix.os }}
needs: detect-skip-ci-trigger
+ defaults:
+ run:
+ shell: bash -l {0}
if: |
always()
@@ -44,18 +47,18 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ["3.8", "3.9", "3.10"]
+ python-version: ["3.9", "3.10", "3.11", "3.12"]
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
steps:
- name: checkout the repository
- uses: actions/checkout at v3
+ uses: actions/checkout at v4
with:
# need to fetch all tags to get a correct version
fetch-depth: 0 # fetch all branches and tags
- name: cache pip
- uses: actions/cache at v2
+ uses: actions/cache at v4
with:
path: ~/.cache/pip
key: pip-py${{ matrix.python-version }}
@@ -63,7 +66,7 @@ jobs:
pip-
- name: setup python
- uses: actions/setup-python at v3
+ uses: actions/setup-python at v5
with:
python-version: ${{ matrix.python-version }}
@@ -73,6 +76,10 @@ jobs:
- name: install dependencies
run: |
python -m pip install -r ci/requirements.txt
+ if [[ "${{matrix.python-version}}" == "3.9" ]]; then
+ # remove after the release
+ python -m pip install 'numpy<2.0'
+ fi
- name: install pint-xarray
run: python -m pip install --no-deps .
@@ -91,7 +98,7 @@ jobs:
python -m pytest --cov=pint_xarray --cov-report=xml
- name: Upload code coverage to Codecov
- uses: codecov/codecov-action at v2.1.0
+ uses: codecov/codecov-action at v4.5.0
with:
file: ./coverage.xml
flags: unittests
=====================================
.github/workflows/nightly.yml
=====================================
@@ -8,6 +8,7 @@ on:
branches: [ main ]
schedule:
- cron: "0 0 * * *" # Daily "At 00:00" UTC
+
workflow_dispatch:
concurrency:
@@ -17,15 +18,17 @@ concurrency:
jobs:
detect-test-upstream-trigger:
name: "Detect CI Trigger: [test-upstream]"
- if: github.event_name == 'push' || github.event_name == 'pull_request'
+ if: |
+ github.repository_owner == 'xarray-contrib'
+ && (github.event_name == 'push' || github.event_name == 'pull_request')
runs-on: ubuntu-latest
outputs:
triggered: ${{ steps.detect-trigger.outputs.trigger-found }}
steps:
- - uses: actions/checkout at v3
+ - uses: actions/checkout at v4
with:
fetch-depth: 2
- - uses: keewis/ci-trigger at v1.1
+ - uses: xarray-contrib/ci-trigger at v1.2
id: detect-trigger
with:
keyword: "[test-upstream]"
@@ -37,30 +40,33 @@ jobs:
if: |
always()
- && github.repository == 'xarray-contrib/pint-xarray'
+ && github.repository_owner == 'xarray-contrib'
&& (
- github.event_name == 'schedule'
- || github.event_name == 'workflow_dispatch'
+ (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
|| needs.detect-test-upstream-trigger.outputs.triggered == 'true'
+ || (
+ github.event_name == 'pull_request'
+ && contains(github.event.pull_request.labels.*.name, 'run-upstream')
+ )
)
strategy:
fail-fast: false
matrix:
- python-version: ["3.10"]
+ python-version: ["3.12"]
outputs:
artifacts_availability: ${{ steps.status.outputs.ARTIFACTS_AVAILABLE }}
steps:
- name: checkout the repository
- uses: actions/checkout at v3
+ uses: actions/checkout at v4
with:
# need to fetch all tags to get a correct version
fetch-depth: 0 # fetch all branches and tags
- name: setup python
- uses: actions/setup-python at v3
+ uses: actions/setup-python at v5
with:
python-version: ${{ matrix.python-version }}
@@ -82,110 +88,16 @@ jobs:
run: python -m pip list
- name: run tests
+ if: success()
id: status
run: |
- set -euo pipefail
- python -m pytest -rf --report-log output-${{ matrix.python-version }}-log.jsonl || (
- echo '::set-output name=ARTIFACTS_AVAILABLE::true' && false
- )
+ python -m pytest -rf --report-log=pytest-log.jsonl
- - name: Upload artifacts
+ - name: report failures
if: |
failure()
- && steps.status.outcome == 'failure'
+ && steps.tests.outcome == 'failure'
&& github.event_name == 'schedule'
- uses: actions/upload-artifact at v2
- with:
- name: output-${{ matrix.python-version }}-log.jsonl
- path: output-${{ matrix.python-version }}-log.jsonl
- retention-days: 5
-
- report:
- name: Report
- runs-on: ubuntu-latest
- needs: upstream-dev
- if: |
- always()
- && github.event_name == 'schedule'
- && github.repository == 'xarray-contrib/pint-xarray'
- && needs.upstream-dev.outputs.artifacts_availability == 'true'
- steps:
- - name: checkout the repository
- uses: actions/checkout at v3
-
- - name: setup python
- uses: actions/setup-python at v3
- with:
- python-version: "3.x"
-
- - name: setup environment
- run: |
- python -m pip install --upgrade pip
- python -m pip install pytest
-
- - uses: actions/download-artifact at v2
- with:
- path: /tmp/workspace/logs
-
- - name: Move all log files into a single directory
- run: |
- rsync -a /tmp/workspace/logs/output-*/ ./logs
- ls -R ./logs
-
- - name: Parse logs
- run: |
- shopt -s globstar
- python .github/workflows/parse_logs.py logs/**/*-log.jsonl
-
- - name: Report failures
- uses: actions/github-script at v6
+ uses: xarray-contrib/issue-from-pytest-log at v1
with:
- github-token: ${{ secrets.GITHUB_TOKEN }}
- script: |
- const fs = require('fs');
- const pytest_logs = fs.readFileSync('pytest-logs.txt', 'utf8');
- const title = "⚠️ Nightly upstream-dev CI failed ⚠️"
- const workflow_url = `https://github.com/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`
- const issue_body = `[Workflow Run URL](${workflow_url})\n${pytest_logs}`
-
- // Run GraphQL query against GitHub API to find the most recent open issue used for reporting failures
- const query = `query($owner:String!, $name:String!, $creator:String!, $label:String!){
- repository(owner: $owner, name: $name) {
- issues(first: 1, states: OPEN, filterBy: {createdBy: $creator, labels: [$label]}, orderBy: {field: CREATED_AT, direction: DESC}) {
- edges {
- node {
- body
- id
- number
- }
- }
- }
- }
- }`;
-
- const variables = {
- owner: context.repo.owner,
- name: context.repo.repo,
- label: 'CI',
- creator: "github-actions[bot]"
- }
- const result = await github.graphql(query, variables)
-
- // If no issue is open, create a new issue,
- // else update the body of the existing issue.
- if (result.repository.issues.edges.length === 0) {
- github.rest.issues.create({
- owner: variables.owner,
- repo: variables.name,
- body: issue_body,
- title: title,
- labels: [variables.label]
- })
- } else {
- github.rest.issues.update({
- owner: variables.owner,
- repo: variables.name,
- issue_number: result.repository.issues.edges[0].node.number,
- body: issue_body
- })
- }
+ log-path: pytest-log.jsonl
=====================================
.github/workflows/pypi.yaml
=====================================
@@ -2,31 +2,66 @@ name: Upload Package to PyPI
on:
release:
- types: [created]
+ types:
+ - published
jobs:
- deploy:
+ build-artifacts:
runs-on: ubuntu-latest
if: github.repository == 'xarray-contrib/pint-xarray'
steps:
- - uses: actions/checkout at v3
- - name: Set up Python
- uses: actions/setup-python at v3
+ - uses: actions/checkout at v4
with:
- python-version: '3.x'
+ fetch-depth: 0
+
+ - uses: actions/setup-python at v5
+ name: Install Python
+ with:
+ python-version: "3.x"
+
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install build twine
- - name: Build
+
+ - name: Build tarball and wheels
run: |
- python -m build --sdist --wheel --outdir dist/ .
- - name: Check the built archives
+ git clean -xdf
+ git restore -SW .
+ python -m build --outdir dist/ .
+
+ - name: Check built artifacts
run: |
- twine check dist/*
- - name: Publish to PyPI
- uses: pypa/gh-action-pypi-publish at 54b39fb9371c0b3a6f9f14bb8a67394defc7a806
+ python -m twine check --strict dist/*
+ pwd
+ if [ -f dist/pint-xarray-0.0.0.tar.gz ]; then
+ echo "❌ INVALID VERSION NUMBER"
+ exit 1
+ else
+ echo "✅ Looks good"
+ fi
+ - uses: actions/upload-artifact at v4
+ with:
+ name: releases
+ path: dist
+
+ upload-to-pypi:
+ needs: build-artifacts
+ if: github.event_name == 'release'
+ runs-on: ubuntu-latest
+
+ environment:
+ name: pypi
+ url: https://pypi.org/p/pint-xarray
+ permissions:
+ id-token: write
+
+ steps:
+ - uses: actions/download-artifact at v4
+ with:
+ name: releases
+ path: dist
+ - name: Publish package to PyPI
+ uses: pypa/gh-action-pypi-publish at ec4db0b4ddc65acdf4bff5fa45ac92d78b56bdf0
with:
- user: __token__
- password: ${{ secrets.pypi_password }}
- repository_url: https://upload.pypi.org/legacy/
+ verbose: true
=====================================
.pre-commit-config.yaml
=====================================
@@ -4,7 +4,7 @@ ci:
# https://pre-commit.com/
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.3.0
+ rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
@@ -12,20 +12,26 @@ repos:
- id: check-yaml
# isort should run before black as black sometimes tweaks the isort output
- repo: https://github.com/pycqa/isort
- rev: 5.10.1
+ rev: 5.13.2
hooks:
- id: isort
# https://github.com/python/black#version-control-integration
- repo: https://github.com/psf/black
- rev: 22.6.0
+ rev: 24.4.2
hooks:
- - id: black
- id: black-jupyter
- repo: https://github.com/keewis/blackdoc
- rev: v0.3.4
+ rev: v0.3.9
hooks:
- id: blackdoc
+ additional_dependencies: ["black==24.4.2"]
+ - id: blackdoc-autoupdate-black
- repo: https://github.com/pycqa/flake8
- rev: 4.0.1
+ rev: 7.1.0
hooks:
- id: flake8
+ - repo: https://github.com/kynan/nbstripout
+ rev: 0.7.1
+ hooks:
+ - id: nbstripout
+ args: [--extra-keys=metadata.kernelspec metadata.language_info.version]
=====================================
.readthedocs.yaml
=====================================
@@ -3,7 +3,13 @@ version: 2
build:
os: ubuntu-22.04
tools:
- python: "3.10"
+ python: "3.11"
+ jobs:
+ post_checkout:
+ - (git --no-pager log --pretty="tformat:%s" -1 | grep -vqF "[skip-rtd]") || exit 183
+ - git fetch --unshallow || true
+ pre_install:
+ - git update-index --assume-unchanged docs/conf.py
python:
install:
=====================================
ci/install-upstream-dev.sh
=====================================
@@ -1,10 +1,11 @@
#!/usr/bin/env bash
python -m pip install \
- -i https://pypi.anaconda.org/scipy-wheels-nightly/simple \
+ -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple \
--no-deps \
--pre \
--upgrade \
- numpy
+ numpy \
+ scipy # until `scipy` has released a version compatible with `numpy>=2.0`
python -m pip install --upgrade \
git+https://github.com/hgrecco/pint \
git+https://github.com/pydata/xarray
=====================================
ci/requirements.txt
=====================================
@@ -1,5 +1,5 @@
-pint
-numpy
+pint!=0.24.0
+numpy<2
scipy
dask[array]
bottleneck
=====================================
docs/conf.py
=====================================
@@ -109,7 +109,7 @@ nbsphinx_execute = "always"
intersphinx_mapping = {
"python": ("https://docs.python.org/3/", None),
- "xarray": ("https://xarray.pydata.org/en/stable", None),
+ "xarray": ("https://docs.xarray.dev/en/stable", None),
"pint": ("https://pint.readthedocs.io/en/stable", None),
"pandas": ("https://pandas.pydata.org/pandas-docs/stable", None),
}
=====================================
docs/examples/plotting.ipynb
=====================================
@@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "markdown",
- "id": "round-optimization",
+ "id": "0",
"metadata": {},
"source": [
"# plotting quantified data"
@@ -11,7 +11,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "greatest-smart",
+ "id": "1",
"metadata": {},
"outputs": [],
"source": [
@@ -27,7 +27,7 @@
},
{
"cell_type": "markdown",
- "id": "fuzzy-maintenance",
+ "id": "2",
"metadata": {},
"source": [
"## load the data"
@@ -36,7 +36,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "proved-racing",
+ "id": "3",
"metadata": {},
"outputs": [],
"source": [
@@ -47,7 +47,7 @@
},
{
"cell_type": "markdown",
- "id": "banned-tolerance",
+ "id": "4",
"metadata": {},
"source": [
"## quantify the data"
@@ -55,7 +55,7 @@
},
{
"cell_type": "markdown",
- "id": "750e0995-b0a7-4302-8780-8c3d1f2a6199",
+ "id": "5",
"metadata": {},
"source": [
"<div class=\"alert alert-info\">\n",
@@ -66,7 +66,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "divine-boost",
+ "id": "6",
"metadata": {},
"outputs": [],
"source": [
@@ -76,7 +76,7 @@
},
{
"cell_type": "markdown",
- "id": "whole-momentum",
+ "id": "7",
"metadata": {},
"source": [
"## work with the data"
@@ -85,7 +85,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "dried-friday",
+ "id": "8",
"metadata": {},
"outputs": [],
"source": [
@@ -95,7 +95,7 @@
},
{
"cell_type": "markdown",
- "id": "14ea5eb8",
+ "id": "9",
"metadata": {},
"source": [
"Most operations will preserve the units but there are some which will drop them (see the [duck array integration status](https://xarray.pydata.org/en/stable/user-guide/duckarrays.html#missing-features) page). To work around that there are unit-aware versions on the `.pint` accessor. For example, to select data use `.pint.sel` instead of `.sel`:"
@@ -104,7 +104,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "93e4ca4e",
+ "id": "10",
"metadata": {},
"outputs": [],
"source": [
@@ -116,7 +116,7 @@
},
{
"cell_type": "markdown",
- "id": "still-ebony",
+ "id": "11",
"metadata": {},
"source": [
"## plot\n",
@@ -127,7 +127,7 @@
{
"cell_type": "code",
"execution_count": null,
- "id": "united-machine",
+ "id": "12",
"metadata": {},
"outputs": [],
"source": [
@@ -136,11 +136,6 @@
}
],
"metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
"language_info": {
"codemirror_mode": {
"name": "ipython",
@@ -150,8 +145,7 @@
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.9.2"
+ "pygments_lexer": "ipython3"
}
},
"nbformat": 4,
=====================================
docs/requirements.txt
=====================================
@@ -1,5 +1,5 @@
-pint>=0.14
-xarray>=0.16.0
+pint>=0.21
+xarray>=2022.06.0
pooch
netCDF4
cf-xarray>=0.6
=====================================
docs/whats-new.rst
=====================================
@@ -2,6 +2,27 @@
What's new
==========
+0.4 (23 Jun 2024)
+-----------------
+- adopt `SPEC0 <https://scientific-python.org/specs/spec-0000>`_ (:pull:`228`)
+
+ This means that the supported versions change:
+
+ ============ ============== ==============
+ dependency old minimum new minimum
+ ============ ============== ==============
+ python 3.8 3.9
+ xarray 0.16.1 2022.06.0
+ numpy 1.17 1.23
+ pint 0.16 0.21
+ ============ ============== ==============
+
+ By `Justus Magin <https://github.com/keewis>`_.
+- add support for python 3.11 and 3.12 (:pull:`228`, :pull:`263`)
+ By `Justus Magin <https://github.com/keewis>`_.
+- ignore datetime units on attributes (:pull:`241`)
+ By `Justus Magin <https://github.com/keewis>`_.
+
0.3 (27 Jul 2022)
-----------------
- drop support for python 3.7 (:pull:`153`)
=====================================
pint_xarray/accessors.py
=====================================
@@ -258,6 +258,12 @@ class PintDataArrayAccessor:
``xarray`` changes the way it implements indexes, these
units will be set as attributes.
+ .. note::
+ Also note that datetime units (i.e. ones that match
+ ``{units} since {date}``) in unit attributes will be
+ ignored, to avoid interfering with ``xarray``'s datetime
+ encoding / decoding.
+
Parameters
----------
units : unit-like or mapping of hashable to unit-like, optional
@@ -294,10 +300,10 @@ class PintDataArrayAccessor:
... coords={"wavelength": [1e-4, 2e-4, 4e-4, 6e-4, 1e-3, 2e-3]},
... )
>>> da.pint.quantify(units="Hz")
- <xarray.DataArray (wavelength: 6)>
+ <xarray.DataArray (wavelength: 6)> Size: 48B
<Quantity([0.4 0.9 1.7 4.8 3.2 9.1], 'hertz')>
Coordinates:
- * wavelength (wavelength) float64 0.0001 0.0002 0.0004 0.0006 0.001 0.002
+ * wavelength (wavelength) float64 48B 0.0001 0.0002 0.0004 0.0006 0.001 0.002
Don't quantify the data:
@@ -307,7 +313,7 @@ class PintDataArrayAccessor:
... attrs={"units": "Hz"},
... )
>>> da.pint.quantify(units=None)
- <xarray.DataArray (wavelength: 2)>
+ <xarray.DataArray (wavelength: 2)> Size: 16B
array([0.4, 0.9])
Dimensions without coordinates: wavelength
@@ -315,11 +321,11 @@ class PintDataArrayAccessor:
>>> q = da.pint.quantify()
>>> q
- <xarray.DataArray (wavelength: 2)>
+ <xarray.DataArray (wavelength: 2)> Size: 16B
<Quantity([0.4 0.9], 'hertz')>
Dimensions without coordinates: wavelength
>>> q.pint.quantify("Hz")
- <xarray.DataArray (wavelength: 2)>
+ <xarray.DataArray (wavelength: 2)> Size: 16B
<Quantity([0.4 0.9], 'hertz')>
Dimensions without coordinates: wavelength
"""
@@ -409,7 +415,7 @@ class PintDataArrayAccessor:
See Also
--------
- :doc:`pint:formatting`
+ :doc:`pint:user/formatting`
pint's string formatting guide
Examples
@@ -417,18 +423,18 @@ class PintDataArrayAccessor:
>>> da = xr.DataArray([0, 1], dims="x")
>>> q = da.pint.quantify("m / s")
>>> q
- <xarray.DataArray (x: 2)>
+ <xarray.DataArray (x: 2)> Size: 16B
<Quantity([0 1], 'meter / second')>
Dimensions without coordinates: x
>>> q.pint.dequantify(format="P")
- <xarray.DataArray (x: 2)>
+ <xarray.DataArray (x: 2)> Size: 16B
array([0, 1])
Dimensions without coordinates: x
Attributes:
units: meter/second
>>> q.pint.dequantify(format="~P")
- <xarray.DataArray (x: 2)>
+ <xarray.DataArray (x: 2)> Size: 16B
array([0, 1])
Dimensions without coordinates: x
Attributes:
@@ -438,7 +444,7 @@ class PintDataArrayAccessor:
>>> pint_xarray.unit_registry.default_format = "~L"
>>> q.pint.dequantify()
- <xarray.DataArray (x: 2)>
+ <xarray.DataArray (x: 2)> Size: 16B
array([0, 1])
Dimensions without coordinates: x
Attributes:
@@ -516,67 +522,67 @@ class PintDataArrayAccessor:
... name="arr",
... )
>>> da
- <xarray.DataArray 'arr' (x: 5)>
+ <xarray.DataArray 'arr' (x: 5)> Size: 40B
<Quantity([0. 0.25 0.5 0.75 1. ], 'meter')>
Coordinates:
- u (x) int64 [s] 0 1 2 3 4
+ u (x) int64 40B [s] 0 1 2 3 4
Dimensions without coordinates: x
Convert the data
>>> da.pint.to("mm")
- <xarray.DataArray 'arr' (x: 5)>
+ <xarray.DataArray 'arr' (x: 5)> Size: 40B
<Quantity([ 0. 250. 500. 750. 1000.], 'millimeter')>
Coordinates:
- u (x) int64 [s] 0 1 2 3 4
+ u (x) int64 40B [s] 0 1 2 3 4
Dimensions without coordinates: x
>>> da.pint.to(ureg.mm)
- <xarray.DataArray 'arr' (x: 5)>
+ <xarray.DataArray 'arr' (x: 5)> Size: 40B
<Quantity([ 0. 250. 500. 750. 1000.], 'millimeter')>
Coordinates:
- u (x) int64 [s] 0 1 2 3 4
+ u (x) int64 40B [s] 0 1 2 3 4
Dimensions without coordinates: x
>>> da.pint.to({da.name: "mm"})
- <xarray.DataArray 'arr' (x: 5)>
+ <xarray.DataArray 'arr' (x: 5)> Size: 40B
<Quantity([ 0. 250. 500. 750. 1000.], 'millimeter')>
Coordinates:
- u (x) int64 [s] 0 1 2 3 4
+ u (x) int64 40B [s] 0 1 2 3 4
Dimensions without coordinates: x
Convert coordinates
>>> da.pint.to({"u": ureg.ms})
- <xarray.DataArray 'arr' (x: 5)>
+ <xarray.DataArray 'arr' (x: 5)> Size: 40B
<Quantity([0. 0.25 0.5 0.75 1. ], 'meter')>
Coordinates:
- u (x) float64 [ms] 0.0 1e+03 2e+03 3e+03 4e+03
+ u (x) float64 40B [ms] 0.0 1e+03 2e+03 3e+03 4e+03
Dimensions without coordinates: x
>>> da.pint.to(u="ms")
- <xarray.DataArray 'arr' (x: 5)>
+ <xarray.DataArray 'arr' (x: 5)> Size: 40B
<Quantity([0. 0.25 0.5 0.75 1. ], 'meter')>
Coordinates:
- u (x) float64 [ms] 0.0 1e+03 2e+03 3e+03 4e+03
+ u (x) float64 40B [ms] 0.0 1e+03 2e+03 3e+03 4e+03
Dimensions without coordinates: x
Convert both simultaneously
>>> da.pint.to("mm", u="ms")
- <xarray.DataArray 'arr' (x: 5)>
+ <xarray.DataArray 'arr' (x: 5)> Size: 40B
<Quantity([ 0. 250. 500. 750. 1000.], 'millimeter')>
Coordinates:
- u (x) float64 [ms] 0.0 1e+03 2e+03 3e+03 4e+03
+ u (x) float64 40B [ms] 0.0 1e+03 2e+03 3e+03 4e+03
Dimensions without coordinates: x
>>> da.pint.to({"arr": ureg.mm, "u": ureg.ms})
- <xarray.DataArray 'arr' (x: 5)>
+ <xarray.DataArray 'arr' (x: 5)> Size: 40B
<Quantity([ 0. 250. 500. 750. 1000.], 'millimeter')>
Coordinates:
- u (x) float64 [ms] 0.0 1e+03 2e+03 3e+03 4e+03
+ u (x) float64 40B [ms] 0.0 1e+03 2e+03 3e+03 4e+03
Dimensions without coordinates: x
>>> da.pint.to(arr="mm", u="ms")
- <xarray.DataArray 'arr' (x: 5)>
+ <xarray.DataArray 'arr' (x: 5)> Size: 40B
<Quantity([ 0. 250. 500. 750. 1000.], 'millimeter')>
Coordinates:
- u (x) float64 [ms] 0.0 1e+03 2e+03 3e+03 4e+03
+ u (x) float64 40B [ms] 0.0 1e+03 2e+03 3e+03 4e+03
Dimensions without coordinates: x
"""
if isinstance(units, (str, pint.Unit)):
@@ -984,6 +990,12 @@ class PintDatasetAccessor:
``xarray`` changes the way it implements indexes, these
units will be set as attributes.
+ .. note::
+ Also note that datetime units (i.e. ones that match
+ ``{units} since {date}``) in unit attributes will be
+ ignored, to avoid interfering with ``xarray``'s datetime
+ encoding / decoding.
+
Parameters
----------
units : mapping of hashable to unit-like, optional
@@ -1019,57 +1031,57 @@ class PintDatasetAccessor:
... )
>>> ds.pint.quantify()
- <xarray.Dataset>
+ <xarray.Dataset> Size: 96B
Dimensions: (x: 3)
Coordinates:
- * x (x) int64 0 1 2
- u (x) int64 [s] -1 0 1
+ * x (x) int64 24B 0 1 2
+ u (x) int64 24B [s] -1 0 1
Data variables:
- a (x) int64 [m] 0 3 2
- b (x) int64 5 -2 1
+ a (x) int64 24B [m] 0 3 2
+ b (x) int64 24B 5 -2 1
>>> ds.pint.quantify({"b": "dm"})
- <xarray.Dataset>
+ <xarray.Dataset> Size: 96B
Dimensions: (x: 3)
Coordinates:
- * x (x) int64 0 1 2
- u (x) int64 [s] -1 0 1
+ * x (x) int64 24B 0 1 2
+ u (x) int64 24B [s] -1 0 1
Data variables:
- a (x) int64 [m] 0 3 2
- b (x) int64 [dm] 5 -2 1
+ a (x) int64 24B [m] 0 3 2
+ b (x) int64 24B [dm] 5 -2 1
Don't quantify specific variables:
>>> ds.pint.quantify({"a": None})
- <xarray.Dataset>
+ <xarray.Dataset> Size: 96B
Dimensions: (x: 3)
Coordinates:
- * x (x) int64 0 1 2
- u (x) int64 [s] -1 0 1
+ * x (x) int64 24B 0 1 2
+ u (x) int64 24B [s] -1 0 1
Data variables:
- a (x) int64 0 3 2
- b (x) int64 5 -2 1
+ a (x) int64 24B 0 3 2
+ b (x) int64 24B 5 -2 1
Quantify with the same unit:
>>> q = ds.pint.quantify()
>>> q
- <xarray.Dataset>
+ <xarray.Dataset> Size: 96B
Dimensions: (x: 3)
Coordinates:
- * x (x) int64 0 1 2
- u (x) int64 [s] -1 0 1
+ * x (x) int64 24B 0 1 2
+ u (x) int64 24B [s] -1 0 1
Data variables:
- a (x) int64 [m] 0 3 2
- b (x) int64 5 -2 1
+ a (x) int64 24B [m] 0 3 2
+ b (x) int64 24B 5 -2 1
>>> q.pint.quantify({"a": "m"})
- <xarray.Dataset>
+ <xarray.Dataset> Size: 96B
Dimensions: (x: 3)
Coordinates:
- * x (x) int64 0 1 2
- u (x) int64 [s] -1 0 1
+ * x (x) int64 24B 0 1 2
+ u (x) int64 24B [s] -1 0 1
Data variables:
- a (x) int64 [m] 0 3 2
- b (x) int64 5 -2 1
+ a (x) int64 24B [m] 0 3 2
+ b (x) int64 24B 5 -2 1
"""
units = either_dict_or_kwargs(units, unit_kwargs, "quantify")
registry = get_registry(unit_registry, units, conversion.extract_units(self.ds))
@@ -1147,7 +1159,7 @@ class PintDatasetAccessor:
See Also
--------
- :doc:`pint:formatting`
+ :doc:`pint:user/formatting`
pint's string formatting guide
Examples
@@ -1155,22 +1167,22 @@ class PintDatasetAccessor:
>>> ds = xr.Dataset({"a": ("x", [0, 1]), "b": ("y", [2, 3, 4])})
>>> q = ds.pint.quantify({"a": "m / s", "b": "s"})
>>> q
- <xarray.Dataset>
+ <xarray.Dataset> Size: 40B
Dimensions: (x: 2, y: 3)
Dimensions without coordinates: x, y
Data variables:
- a (x) int64 [m/s] 0 1
- b (y) int64 [s] 2 3 4
+ a (x) int64 16B [m/s] 0 1
+ b (y) int64 24B [s] 2 3 4
>>> d = q.pint.dequantify(format="P")
>>> d.a
- <xarray.DataArray 'a' (x: 2)>
+ <xarray.DataArray 'a' (x: 2)> Size: 16B
array([0, 1])
Dimensions without coordinates: x
Attributes:
units: meter/second
>>> d.b
- <xarray.DataArray 'b' (y: 3)>
+ <xarray.DataArray 'b' (y: 3)> Size: 24B
array([2, 3, 4])
Dimensions without coordinates: y
Attributes:
@@ -1178,13 +1190,13 @@ class PintDatasetAccessor:
>>> d = q.pint.dequantify(format="~P")
>>> d.a
- <xarray.DataArray 'a' (x: 2)>
+ <xarray.DataArray 'a' (x: 2)> Size: 16B
array([0, 1])
Dimensions without coordinates: x
Attributes:
units: m/s
>>> d.b
- <xarray.DataArray 'b' (y: 3)>
+ <xarray.DataArray 'b' (y: 3)> Size: 24B
array([2, 3, 4])
Dimensions without coordinates: y
Attributes:
@@ -1195,13 +1207,13 @@ class PintDatasetAccessor:
>>> pint_xarray.unit_registry.default_format = "~L"
>>> d = q.pint.dequantify()
>>> d.a
- <xarray.DataArray 'a' (x: 2)>
+ <xarray.DataArray 'a' (x: 2)> Size: 16B
array([0, 1])
Dimensions without coordinates: x
Attributes:
units: \frac{\mathrm{m}}{\mathrm{s}}
>>> d.b
- <xarray.DataArray 'b' (y: 3)>
+ <xarray.DataArray 'b' (y: 3)> Size: 24B
array([2, 3, 4])
Dimensions without coordinates: y
Attributes:
@@ -1248,77 +1260,77 @@ class PintDatasetAccessor:
... coords={"u": ("x", np.arange(5) * ureg.s)},
... )
>>> ds
- <xarray.Dataset>
+ <xarray.Dataset> Size: 120B
Dimensions: (x: 5)
Coordinates:
- u (x) int64 [s] 0 1 2 3 4
+ u (x) int64 40B [s] 0 1 2 3 4
Dimensions without coordinates: x
Data variables:
- a (x) float64 [m] 0.0 0.25 0.5 0.75 1.0
- b (x) float64 [kg] -1.0 -0.75 -0.5 -0.25 0.0
+ a (x) float64 40B [m] 0.0 0.25 0.5 0.75 1.0
+ b (x) float64 40B [kg] -1.0 -0.75 -0.5 -0.25 0.0
Convert the data
>>> ds.pint.to({"a": "mm", "b": ureg.g})
- <xarray.Dataset>
+ <xarray.Dataset> Size: 120B
Dimensions: (x: 5)
Coordinates:
- u (x) int64 [s] 0 1 2 3 4
+ u (x) int64 40B [s] 0 1 2 3 4
Dimensions without coordinates: x
Data variables:
- a (x) float64 [mm] 0.0 250.0 500.0 750.0 1e+03
- b (x) float64 [g] -1e+03 -750.0 -500.0 -250.0 0.0
+ a (x) float64 40B [mm] 0.0 250.0 500.0 750.0 1e+03
+ b (x) float64 40B [g] -1e+03 -750.0 -500.0 -250.0 0.0
>>> ds.pint.to(a=ureg.mm, b="g")
- <xarray.Dataset>
+ <xarray.Dataset> Size: 120B
Dimensions: (x: 5)
Coordinates:
- u (x) int64 [s] 0 1 2 3 4
+ u (x) int64 40B [s] 0 1 2 3 4
Dimensions without coordinates: x
Data variables:
- a (x) float64 [mm] 0.0 250.0 500.0 750.0 1e+03
- b (x) float64 [g] -1e+03 -750.0 -500.0 -250.0 0.0
+ a (x) float64 40B [mm] 0.0 250.0 500.0 750.0 1e+03
+ b (x) float64 40B [g] -1e+03 -750.0 -500.0 -250.0 0.0
Convert coordinates
>>> ds.pint.to({"u": ureg.ms})
- <xarray.Dataset>
+ <xarray.Dataset> Size: 120B
Dimensions: (x: 5)
Coordinates:
- u (x) float64 [ms] 0.0 1e+03 2e+03 3e+03 4e+03
+ u (x) float64 40B [ms] 0.0 1e+03 2e+03 3e+03 4e+03
Dimensions without coordinates: x
Data variables:
- a (x) float64 [m] 0.0 0.25 0.5 0.75 1.0
- b (x) float64 [kg] -1.0 -0.75 -0.5 -0.25 0.0
+ a (x) float64 40B [m] 0.0 0.25 0.5 0.75 1.0
+ b (x) float64 40B [kg] -1.0 -0.75 -0.5 -0.25 0.0
>>> ds.pint.to(u="ms")
- <xarray.Dataset>
+ <xarray.Dataset> Size: 120B
Dimensions: (x: 5)
Coordinates:
- u (x) float64 [ms] 0.0 1e+03 2e+03 3e+03 4e+03
+ u (x) float64 40B [ms] 0.0 1e+03 2e+03 3e+03 4e+03
Dimensions without coordinates: x
Data variables:
- a (x) float64 [m] 0.0 0.25 0.5 0.75 1.0
- b (x) float64 [kg] -1.0 -0.75 -0.5 -0.25 0.0
+ a (x) float64 40B [m] 0.0 0.25 0.5 0.75 1.0
+ b (x) float64 40B [kg] -1.0 -0.75 -0.5 -0.25 0.0
Convert both simultaneously
>>> ds.pint.to(a=ureg.mm, b=ureg.g, u="ms")
- <xarray.Dataset>
+ <xarray.Dataset> Size: 120B
Dimensions: (x: 5)
Coordinates:
- u (x) float64 [ms] 0.0 1e+03 2e+03 3e+03 4e+03
+ u (x) float64 40B [ms] 0.0 1e+03 2e+03 3e+03 4e+03
Dimensions without coordinates: x
Data variables:
- a (x) float64 [mm] 0.0 250.0 500.0 750.0 1e+03
- b (x) float64 [g] -1e+03 -750.0 -500.0 -250.0 0.0
+ a (x) float64 40B [mm] 0.0 250.0 500.0 750.0 1e+03
+ b (x) float64 40B [g] -1e+03 -750.0 -500.0 -250.0 0.0
>>> ds.pint.to({"a": "mm", "b": "g", "u": ureg.ms})
- <xarray.Dataset>
+ <xarray.Dataset> Size: 120B
Dimensions: (x: 5)
Coordinates:
- u (x) float64 [ms] 0.0 1e+03 2e+03 3e+03 4e+03
+ u (x) float64 40B [ms] 0.0 1e+03 2e+03 3e+03 4e+03
Dimensions without coordinates: x
Data variables:
- a (x) float64 [mm] 0.0 250.0 500.0 750.0 1e+03
- b (x) float64 [g] -1e+03 -750.0 -500.0 -250.0 0.0
+ a (x) float64 40B [mm] 0.0 250.0 500.0 750.0 1e+03
+ b (x) float64 40B [g] -1e+03 -750.0 -500.0 -250.0 0.0
Convert homogeneous data
@@ -1330,23 +1342,23 @@ class PintDatasetAccessor:
... coords={"u": ("x", np.arange(5) * ureg.s)},
... )
>>> ds
- <xarray.Dataset>
+ <xarray.Dataset> Size: 120B
Dimensions: (x: 5)
Coordinates:
- u (x) int64 [s] 0 1 2 3 4
+ u (x) int64 40B [s] 0 1 2 3 4
Dimensions without coordinates: x
Data variables:
- a (x) float64 [kg] 0.0 0.25 0.5 0.75 1.0
- b (x) float64 [mg] -1.0 -0.75 -0.5 -0.25 0.0
+ a (x) float64 40B [kg] 0.0 0.25 0.5 0.75 1.0
+ b (x) float64 40B [mg] -1.0 -0.75 -0.5 -0.25 0.0
>>> ds.pint.to("g")
- <xarray.Dataset>
+ <xarray.Dataset> Size: 120B
Dimensions: (x: 5)
Coordinates:
- u (x) int64 [s] 0 1 2 3 4
+ u (x) int64 40B [s] 0 1 2 3 4
Dimensions without coordinates: x
Data variables:
- a (x) float64 [g] 0.0 250.0 500.0 750.0 1e+03
- b (x) float64 [g] -0.001 -0.00075 -0.0005 -0.00025 0.0
+ a (x) float64 40B [g] 0.0 250.0 500.0 750.0 1e+03
+ b (x) float64 40B [g] -0.001 -0.00075 -0.0005 -0.00025 0.0
"""
if isinstance(units, (str, pint.Unit)):
unit_kwargs.update(
=====================================
pint_xarray/conversion.py
=====================================
@@ -1,4 +1,5 @@
import itertools
+import re
import pint
from xarray import DataArray, Dataset, IndexVariable, Variable
@@ -11,6 +12,14 @@ unit_attribute_name = "units"
slice_attributes = ("start", "stop", "step")
temporary_name = "<this-array>"
+time_units_re = r"\w+"
+datetime_re = r"\d{4}-\d{2}-\d{2}(?:[ T]\d{2}:\d{2}:\d{2}(?:\.\d+)?)?"
+datetime_units_re = re.compile(rf"{time_units_re} since {datetime_re}")
+
+
+def is_datetime_unit(unit):
+ return isinstance(unit, str) and datetime_units_re.match(unit) is not None
+
def array_attach_units(data, unit):
"""attach a unit to the data
@@ -266,7 +275,11 @@ def extract_units(obj):
def extract_unit_attributes_dataset(obj, attr="units"):
- return {name: var.attrs.get(attr, None) for name, var in obj.variables.items()}
+ all_units = {name: var.attrs.get(attr, None) for name, var in obj.variables.items()}
+
+ return {
+ name: unit for name, unit in all_units.items() if not is_datetime_unit(unit)
+ }
def extract_unit_attributes(obj, attr="units"):
@@ -308,6 +321,9 @@ def strip_units(obj):
def strip_unit_attributes_dataset(obj, attr="units"):
new_obj = obj.copy()
for var in new_obj.variables.values():
+ if is_datetime_unit(var.attrs.get(attr, "")):
+ continue
+
var.attrs.pop(attr, None)
return new_obj
=====================================
pint_xarray/formatting.py
=====================================
@@ -77,8 +77,10 @@ def format_item(x, quote_strings=True):
"""Returns a succinct summary of an object as a string"""
if isinstance(x, (str, bytes)):
return repr(x) if quote_strings else x
- elif isinstance(x, (float, np.float_)):
+ elif isinstance(x, float):
return f"{x:.4}"
+ elif hasattr(x, "dtype") and np.issubdtype(x.dtype, np.floating):
+ return f"{x.item():.4}"
else:
return str(x)
=====================================
pint_xarray/tests/test_conversion.py
=====================================
@@ -482,6 +482,11 @@ class TestXarrayFunctions:
{"a": "K", "b": "hPa", "x": "m", "u": "s"},
id="Dataset",
),
+ pytest.param(
+ Dataset(coords={"t": ("t", [], {"units": "seconds since 2000-01-01"})}),
+ {},
+ id="datetime_unit",
+ ),
),
)
def test_extract_unit_attributes(self, obj, expected):
@@ -546,6 +551,11 @@ class TestXarrayFunctions:
{"a": "K", "b": "hPa", "x": "m", "u": "s"},
id="Dataset",
),
+ pytest.param(
+ Dataset(coords={"t": ("t", [], {"units": "seconds since 2000-01-01"})}),
+ {},
+ id="datetime_unit",
+ ),
),
)
def test_strip_unit_attributes(self, obj, expected):
=====================================
pint_xarray/tests/utils.py
=====================================
@@ -76,7 +76,7 @@ def assert_slice_equal(a, b):
def assert_indexer_equal(a, b):
__tracebackhide__ = True
- assert type(a) == type(b)
+ assert type(a) is type(b)
if isinstance(a, slice):
assert_slice_equal(a, b)
elif isinstance(a, DataArray):
=====================================
pyproject.toml
=====================================
@@ -1,5 +1,44 @@
+[project]
+name = "pint-xarray"
+authors = [
+ {name = "Tom Nicholas", email = "tomnicholas1 at googlemail.com"}
+]
+description = "Physical units interface to xarray using Pint"
+license = {text = "Apache-2"}
+readme = "README.md"
+classifiers = [
+ "Development Status :: 3 - Alpha",
+ "Environment :: Console",
+ "Intended Audience :: Science/Research",
+ "License :: OSI Approved :: Apache Software License",
+ "Operating System :: OS Independent",
+ "Programming Language :: Python",
+ "Programming Language :: Python :: 3.9",
+ "Programming Language :: Python :: 3.10",
+ "Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
+ "Topic :: Scientific/Engineering",
+]
+requires-python = ">=3.9"
+dependencies = [
+ "numpy >= 1.23",
+ "xarray >= 2022.06.0",
+ "pint >= 0.21",
+]
+dynamic = ["version"]
+
+[project.urls]
+Home = "https://github.com/xarray-contrib/pint-xarray"
+Documentation = "https://pint-xarray.readthedocs.io/en/stable"
+
+[tool.setuptools.packages.find]
+include = [
+ "pint_xarray",
+ "pint_xarray.tests",
+]
+
[build-system]
-requires = ["setuptools >= 42", "wheel", "setuptools_scm[toml] >= 3.4"]
+requires = ["setuptools >= 64", "setuptools_scm >= 7.0"]
build-backend = "setuptools.build_meta"
[tool.setuptools_scm]
=====================================
setup.cfg deleted
=====================================
@@ -1,39 +0,0 @@
-[metadata]
-name = pint-xarray
-author = Tom Nicholas
-author_email = tomnicholas1 at googlemail.com
-description = Physical units interface to xarray using Pint
-url = https://github.com/xarray-contrib/pint-xarray
-project_urls =
- Documentation=https://pint-xarray.readthedocs.io/en/stable
-long_description = file: README.md
-long_description_content_type = text/markdown
-classifiers =
- Development Status :: 3 - Alpha
- Environment :: Console
- Intended Audience :: Science/Research
- License :: OSI Approved :: Apache Software License
- Operating System :: OS Independent
- Programming Language :: Python
- Programming Language :: Python :: 3.8
- Programming Language :: Python :: 3.9
- Programming Language :: Python :: 3.10
- Topic :: Scientific/Engineering
-
-[options]
-packages = find:
-python_requires = >=3.8
-install_requires =
- numpy >= 1.17
- xarray >= 0.16.1
- pint >= 0.16
-
-[flake8]
-ignore =
- E203 # whitespace before ':' - doesn't work well with black
- E402 # module level import not at top of file
- E501 # line too long - let black worry about that
- E731 # do not assign a lambda expression, use a def
- W503 # line break before binary operator
-exclude=
- .eggs
=====================================
setup.py deleted
=====================================
@@ -1,4 +0,0 @@
-from setuptools import setup
-
-if __name__ == "__main__":
- setup()
View it on GitLab: https://salsa.debian.org/debian-gis-team/pint-xarray/-/commit/a0156ef8ae4e7261a2d3d29fa61c0cdcc5caf10b
--
This project does not include diff previews in email notifications.
View it on GitLab: https://salsa.debian.org/debian-gis-team/pint-xarray/-/commit/a0156ef8ae4e7261a2d3d29fa61c0cdcc5caf10b
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20240629/28b49f3c/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list