"""SDMX Information Model (SDMX-IM).
This module implements many of the classes described in the SDMX-IM specification
('spec'), which is available from:
- https://sdmx.org/?page_id=5008
- https://sdmx.org/wp-content/uploads/
SDMX_2-1-1_SECTION_2_InformationModel_201108.pdf
Details of the implementation:
- Python typing and pydantic are used to enforce the types of attributes that reference
instances of other classes.
- Some classes have convenience attributes not mentioned in the spec, to ease navigation
between related objects. These are marked “:mod:`sdmx` extension not in the IM.”
- Class definitions are grouped by section of the spec, but these sections appear out
of order so that dependent classes are defined first.
"""
# TODO for complete implementation of the IM, enforce TimeKeyValue (instead of KeyValue)
# for {Generic,StructureSpecific} TimeSeriesDataSet.
import logging
from collections import ChainMap
from collections.abc import Collection
from collections.abc import Iterable as IterableABC
from copy import copy
from datetime import date, datetime, timedelta
from enum import Enum
from functools import lru_cache
from inspect import isclass
from itertools import product
from operator import attrgetter, itemgetter
from typing import (
Any,
Dict,
Generator,
Generic,
Iterable,
List,
Mapping,
Optional,
Sequence,
Set,
Tuple,
Type,
TypeVar,
Union,
)
from warnings import warn
from pandasdmx.util import (
BaseModel,
DictLike,
compare,
dictlike_field,
only,
Resource,
validate_dictlike,
validator,
)
log = logging.getLogger(__name__)
# TODO read this from the environment, or use any value set in the SDMX-ML spec.
# Currently set to 'en' because test_dsd.py expects it.
DEFAULT_LOCALE = "en"
# Configure validation level (new in v1.8.0)
# This is currently used only to prevent URN matching
ValidationLevels = Enum("ValidationLevels", "strict sloppy")
DEFAULT_VAL_LEVEL = ValidationLevels.sloppy
# §3.2: Base structures
class InternationalString:
"""SDMX-IM InternationalString.
SDMX-IM LocalisedString is not implemented. Instead, the 'localizations' is a
mapping where:
- keys correspond to the 'locale' property of LocalisedString.
- values correspond to the 'label' property of LocalisedString.
When used as a type hint with pydantic, InternationalString fields can be assigned
to in one of four ways::
class Foo(BaseModel):
name: InternationalString = InternationalString()
# Equivalent: no localizations
f = Foo()
f = Foo(name={})
# Using an explicit locale
f.name['en'] = "Foo's name in English"
# Using a (locale, label) tuple
f.name = ('fr', "Foo's name in French")
# Using a dict
f.name = {'en': "Replacement English name",
'fr': "Replacement French name"}
# Using a bare string, implicitly for the DEFAULT_LOCALE
f.name = "Name in DEFAULT_LOCALE language"
Only the first method preserves existing localizations; the latter three replace
them.
"""
localizations: Dict[str, str] = {}
def __init__(self, value=None, **kwargs):
super().__init__()
# Handle initial values according to type
if isinstance(value, str):
# Bare string
value = {DEFAULT_LOCALE: value}
elif (
isinstance(value, Collection)
and len(value) == 2
and isinstance(value[0], str)
):
# 2-tuple of str is (locale, label)
value = {value[0]: value[1]}
elif isinstance(value, dict):
# dict; use directly
pass
elif isinstance(value, IterableABC):
# Iterable of 2-tuples
value = {locale: label for (locale, label) in value}
elif value is None:
# Keyword arguments → dict, possibly empty
value = dict(kwargs)
else:
raise ValueError(value, kwargs)
self.localizations = value
# Convenience access
def __getitem__(self, locale):
return self.localizations[locale]
def __setitem__(self, locale, label):
self.localizations[locale] = label
# Duplicate of __getitem__, to pass existing tests in test_dsd.py
def __getattr__(self, name):
try:
return self.__dict__["localizations"][name]
except KeyError:
raise AttributeError(name) from None
def __add__(self, other):
result = copy(self)
result.localizations.update(other.localizations)
return result
def localized_default(self, locale=None):
"""Return the string in *locale* if not empty, or else the first defined."""
if locale and (locale in self.localizations) and self.localizations[locale]:
return self.localizations[locale]
if len(self.localizations):
# No label in the default locale; use the first stored non-empty str value
return next(filter(None, self.localizations.values()))
else:
return ""
def __str__(self):
return self.localized_default(DEFAULT_LOCALE)
def __repr__(self):
return "\n".join(
["{}: {}".format(*kv) for kv in sorted(self.localizations.items())]
)
def __eq__(self, other):
try:
return self.localizations == other.localizations
except AttributeError:
return NotImplemented
@classmethod
def __get_validators__(cls):
yield cls.__validate
@classmethod
def __validate(cls, value, values, config, field):
# Any value that the constructor can handle can be assigned
if not isinstance(value, InternationalString):
value = InternationalString(value)
try:
# Update existing value
existing = values[field.name]
existing.localizations.update(value.localizations)
return existing
except KeyError:
# No existing value/None; return the assigned value
return value
class Annotation(BaseModel):
#: Can be used to disambiguate multiple annotations for one AnnotableArtefact.
id: Optional[str] = None
#: Title, used to identify an annotation.
title: Optional[str] = None
#: Specifies how the annotation is processed.
type: Optional[str] = None
#: A link to external descriptive text.
url: Optional[str] = None
#: Content of the annotation.
text: InternationalString = InternationalString()
class AnnotableArtefact(BaseModel):
#: :class:`Annotations <.Annotation>` of the object.
#:
#: :mod:`pandaSDMX` implementation: The IM does not specify the name of this
#: feature.
annotations: List[Annotation] = []
def get_annotation(self, **attrib):
"""Return a :class:`Annotation` with given `attrib`, e.g. 'id'.
If more than one `attrib` is given, all must match a particular annotation.
Raises
------
KeyError
If there is no matching annotation.
"""
for anno in self.annotations:
if all(getattr(anno, key, None) == value for key, value in attrib.items()):
return anno
raise KeyError(attrib)
def pop_annotation(self, **attrib):
"""Remove and return a :class:`Annotation` with given `attrib`, e.g. 'id'.
If more than one `attrib` is given, all must match a particular annotation.
Raises
------
KeyError
If there is no matching annotation.
"""
for i, anno in enum
没有合适的资源?快使用搜索试试~ 我知道了~
pandaSDMX-1.8.0.tar.gz
需积分: 1 1 下载量 34 浏览量
2024-03-09
13:50:33
上传
评论
收藏 74KB GZ 举报
温馨提示
Python库是一组预先编写的代码模块,旨在帮助开发者实现特定的编程任务,无需从零开始编写代码。这些库可以包括各种功能,如数学运算、文件操作、数据分析和网络编程等。Python社区提供了大量的第三方库,如NumPy、Pandas和Requests,极大地丰富了Python的应用领域,从数据科学到Web开发。Python库的丰富性是Python成为最受欢迎的编程语言之一的关键原因之一。这些库不仅为初学者提供了快速入门的途径,而且为经验丰富的开发者提供了强大的工具,以高效率、高质量地完成复杂任务。例如,Matplotlib和Seaborn库在数据可视化领域内非常受欢迎,它们提供了广泛的工具和技术,可以创建高度定制化的图表和图形,帮助数据科学家和分析师在数据探索和结果展示中更有效地传达信息。
资源推荐
资源详情
资源评论
收起资源包目录
pandaSDMX-1.8.0.tar.gz (34个子文件)
pandaSDMX-1.8.0
README.rst 3KB
LICENSE 10KB
PKG-INFO 4KB
pyproject.toml 1KB
pandasdmx
__init__.py 859B
remote.py 4KB
util.py 14KB
urn.py 2KB
model.py 73KB
source
__init__.py 6KB
abs.py 878B
istat.py 788B
estat.py 3KB
sgr.py 733B
wb.py 266B
lsd.py 509B
insee.py 770B
api.py 21KB
format
__init__.py 2KB
xml.py 4KB
protobuf_pb2.py 58B
json.py 328B
writer
__init__.py 107B
xml.py 19KB
protobuf.py 1KB
base.py 2KB
pandas.py 18KB
message.py 12KB
exceptions.py 385B
sources.json 7KB
reader
__init__.py 4KB
sdmxml.py 48KB
sdmxjson.py 7KB
base.py 2KB
共 34 条
- 1
资源评论
程序员Chino的日记
- 粉丝: 3683
- 资源: 5万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功