Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 147 additions & 15 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,22 +1,154 @@
# Byte-compiled / optimized / DLL files
*.py[cod]
__pycache__
*$py.class
__pycache__/

*.cache
*.egg-info
*.pdf
*.sqlite
# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Development and build files
# PyInstaller
*.manifest
*.spec

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.pytest_cache
build
.coverage.*
.cache
nosetests.xml
coverage.xml
dist
doc/cache.sqlite
doc/_build
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
prof/
htmlcov
.eggs/

# Editors
.vscode/settings.json
# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
doc/_build/
doc/cache.sqlite

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
Pipfile.lock

# PEP 582
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# IDEs and editors
.idea/
.vscode/
*.swp
*.swo
*~
.project
.pydevproject
.settings/
*.sublime-project
*.sublime-workspace

# OS specific
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
Desktop.ini

# Project specific
*.pdf
*.sqlite
*.cache
2 changes: 1 addition & 1 deletion doc/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pandaSDMX is a pure `Python <https://python.org>`_ package requiring Python 3.9
pandaSDMX also depends on:

- `pandas <http://pandas.pydata.org>`_ for data structures,
- `pydantic <https://docs.pydantic.dev>`_ to implement the IM,
- `pydantic 2.x <https://docs.pydantic.dev>`_ to implement the IM,
- `requests <https://pypi.python.org/pypi/requests/>`_ for HTTP requests, and
- `lxml <http://www.lxml.de>`_ for XML processing.

Expand Down
17 changes: 11 additions & 6 deletions doc/whatsnew.rst
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
:tocdepth: 1

What's new?
===========


v1.10.0 (2023-02-25)
-------------------------
What's new?
===========

Unreleased
----------

* Update dependency to pydantic 2.x and run the internal model layer via
``pydantic.v1`` compatibility imports.

v1.10.0 (2023-02-25)
-------------------------


* update ESTAT config to support new API
Expand Down
2 changes: 1 addition & 1 deletion pandasdmx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"to_xml",
]

__version__ = "1.10.0"
__version__ = "1.10.2"


#: Top-level logger.
Expand Down
5 changes: 4 additions & 1 deletion pandasdmx/source/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
from pydantic import HttpUrl
try:
from pydantic.v1 import HttpUrl
except Exception:
from pydantic import HttpUrl
from enum import Enum
from importlib import import_module, resources
import json
Expand Down
5 changes: 4 additions & 1 deletion pandasdmx/tests/test_model.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# TODO test str() and repr() implementations

import pydantic
try:
import pydantic.v1 as pydantic
except Exception:
import pydantic
import pytest
from pytest import raises

Expand Down
17 changes: 13 additions & 4 deletions pandasdmx/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,20 @@
from functools import lru_cache
from typing import Any, Dict, Mapping, Tuple, TypeVar, Union

import pydantic
import requests
from pydantic import Field, ValidationError, validator
from pydantic.class_validators import make_generic_validator
from pydantic.typing import get_origin # type: ignore [attr-defined]
try:
import pydantic.v1 as pydantic
from pydantic.v1 import Field, ValidationError, validator
from pydantic.v1.class_validators import make_generic_validator
from pydantic.v1.typing import get_origin
except Exception:
import pydantic
from pydantic import Field, ValidationError, validator
from pydantic.class_validators import make_generic_validator
try:
from pydantic.typing import get_origin # type: ignore [attr-defined]
except Exception: # pragma: no cover
from typing import get_origin

try:
import requests_cache
Expand Down
44 changes: 23 additions & 21 deletions pandasdmx/writer/pandas.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,31 +485,33 @@ def _get_attrs():
# Unstack all but the time dimension and convert
other_dims = list(filter(lambda d: d != param["dim"], df.index.names))
df = df.unstack(other_dims)
df.index = pd.to_datetime(df.index)
df.index = pd.to_datetime(df.index, format='ISO8601')

if param["freq"]:
# Determine frequency string, Dimension, or Attribute
try:
# pandas version prior to 1.1.0
prefix_mapping = pd.offsets.prefix_mapping
except AttributeError:
# pandas version >= 1.1.0
# See also issue #35482 in the pandas-dev repo
prefix_mapping = pd._libs.tslibs.offsets.prefix_mapping
from pandas.tseries.frequencies import to_offset

freq = param["freq"]
if isinstance(freq, str) and freq not in prefix_mapping:
# ID of a Dimension or Attribute
for component in chain(_get_dims(), _get_attrs()):
if component.id == freq:
freq = component
break

# No named dimension in the DSD; but perhaps on the df
if isinstance(freq, str):
if freq in df.columns.names:
freq = Dimension(id=freq)
else:
raise ValueError(freq)
if isinstance(freq, str):
# First, try to interpret as a pandas frequency string
try:
to_offset(freq)
# Valid pandas frequency string, use as-is
except (ValueError, KeyError):
# Not a valid pandas frequency; try as Dimension or Attribute ID
found = False
for component in chain(_get_dims(), _get_attrs()):
if component.id == freq:
freq = component
found = True
break

# No named dimension in the DSD; but perhaps on the df
if not found:
if freq in df.columns.names:
freq = Dimension(id=freq)
else:
raise ValueError(freq)

if isinstance(freq, Dimension):
# Retrieve Dimension values from pd.MultiIndex level
Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ requires = [
"requests >=2.26",
"lxml >= 4.8",
"pandas >= 1.3",
"pydantic >=1.9.2, < 2.0"]
requires-python = ">=3.9.6,<3.12"
"pydantic >=2.12, < 3.0"]
requires-python = ">=3.9.6,<3.13"
keywords = "statistics, SDMX, pandas, data, economics, science"
classifiers = [
"Intended Audience :: Developers",
Expand Down Expand Up @@ -42,4 +42,4 @@ test = ["pytest >= 5",

[tool.flit.sdist]
include = ["LICENSE", 'README.rst']
exclude = ['pandasdmx/tests']
exclude = ['pandasdmx/tests']
2 changes: 0 additions & 2 deletions requirements.txt

This file was deleted.