Skip to content

Commit 78f18c7

Browse files
committed
Expand docs for #21; add to whatsnew
1 parent fdd3673 commit 78f18c7

17 files changed

+152
-30
lines changed

doc/api.in

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
oica
1515
org
1616
proto
17+
report
1718
store
1819
testing
1920
tests

doc/conf.py

+12
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,15 @@
3333
nitpicky = True
3434
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
3535

36+
# A string of reStructuredText included at the beginning of every source file.
37+
rst_prolog = r"""
38+
.. role:: py(code)
39+
:language: python
40+
41+
.. role:: xml(code)
42+
:language: xml
43+
"""
44+
3645

3746
def setup(app: "sphinx.application.Sphinx"):
3847
from sphinx.ext.autosummary.generate import generate_autosummary_docs
@@ -72,8 +81,11 @@ def setup(app: "sphinx.application.Sphinx"):
7281

7382
intersphinx_mapping = {
7483
"click": ("https://click.palletsprojects.com/en/8.1.x/", None),
84+
"docutils": ("https://sphinx-docutils.readthedocs.io/en/latest", None),
85+
"jinja2": ("https://jinja.palletsprojects.com/en/3.1.x", None),
7586
"pandas": ("https://pandas.pydata.org/pandas-docs/stable/", None),
7687
"platformdirs": ("https://platformdirs.readthedocs.io/en/latest/", None),
88+
"pluggy": ("https://pluggy.readthedocs.io/en/stable", None),
7789
"pooch": ("https://www.fatiando.org/pooch/latest/", None),
7890
"py": ("https://docs.python.org/3/", None),
7991
"pytest": ("https://docs.pytest.org/en/stable/", None),

doc/giz.rst

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ GIZ GmbH (`website <https://www.giz.de/en/>`_, lit. *Corporation for Internation
55
It is not currently a direct provider of (meta)data through TDC, but its members initiated what is now the TDCI and support its activities, including development of this :mod:`.transport_data` package.
66
This work mainly appears in the :mod:`.org` and :mod:`.proto` modules.
77

8+
.. _project-tuewas:
9+
810
TUEWAS
911
======
1012

1113
- “Transport, Environment, Energy, and Water in Asia” is an “internal sector network” of GIZ.
12-
- Website: https://tuewas-asia.org/
14+
- Website: https://tuewas-asia.org

doc/index.rst

+2
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,15 @@ The following modules contain *generic* code and utilities usable with (meta)dat
8484

8585
cli
8686
config
87+
report
8788
store
8889
testing
8990
tests
9091
util
9192

9293
- :mod:`~transport_data.cli`: :doc:`cli`
9394
- :mod:`.config`: :doc:`config`
95+
- :mod:`.report`: :doc:`report`
9496
- :mod:`.store`: :doc:`store`
9597
- :mod:`.testing`: :doc:`testing`
9698
- :mod:`.tests`: :doc:`tests`

doc/report.rst

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Reports
2+
*********
3+
4+
.. include:: _api/transport_data.report.rst

doc/roadmap.rst

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@ Roadmap
22
*******
33

44
This page gives a medium- and long-term overview of future development of :mod:`transport_data`, focused on the tools in this package, but with relevant details about the broader TDC and TDCI.
5-
See also `transport-data/projects/1 <https://github.com/orgs/transport-data/projects/1>`_ on GitHub.
5+
See also:
6+
7+
- GitHub project `transport-data/projects/1 <https://github.com/orgs/transport-data/projects/1>`_ for general TDCI development.
8+
- GitHub project `transport-data/projects/3 <https://github.com/orgs/transport-data/projects/3>`_ for deployment of CKAN (2024).

doc/whatsnew.rst

+8
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ What's new
44
Next release
55
============
66

7+
- Add tools and data for the :ref:`project-tuewas` project (:pull:`21`).
8+
9+
- Add :mod:`.metadata.spreadsheet`, :mod:`.metadata.report` submodules; expand :mod:`.metadata`.
10+
- Add :program:`tdc org read`, :program:`tdc org summarize`, :program:`tdc org tuewas` CLI commands.
11+
12+
- Add :class:`.report.Report`, a base class for generating ‘reports’ (documents derived from SDMX (meta)data) and supporting code in :mod:`.util.docutils`, :mod:`.util.jinja2` (:pull:`21`).
13+
- Adopt :mod:`pluggy <.util.pluggy>` for plug-in hooks and implementations (:pull:`21`); use the :func:`.hooks.get_agencies` hook across existing modules.
14+
- Add :func:`.tdc_cli`, :func:`.test_data_path` test fixtures (:pull:`21`).
715
- Python 3.8 support is dropped (:pull:`21`), as it has reached end-of-life.
816
- Add :mod:`.ipcc` (:doc:`ipcc`) module (:issue:`15`, :pull:`21`).
917
- Add :doc:`standards` and :doc:`roadmap` documentation pages (:pull:`9`).

transport_data/org/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
@hookimpl
1717
def get_agencies() -> "sdmx.model.v21.Agency":
18+
"""Return agencies and organizations including and subsidiary to TDCI itself."""
1819
# Agency
1920
a1 = m.Agency(
2021
id="TDCI",

transport_data/org/cli.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
"""CLI for :mod:`.org`.
22
3+
Use the :program:`--help` command-line option to see help for individual commands
4+
defined in this module.
5+
36
.. runblock:: console
47
58
$ tdc org --help

transport_data/org/metadata/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""Handle TDC-structured metadata."""
2+
13
import itertools
24
import logging
35
import re
@@ -174,6 +176,7 @@ def get_cs_common() -> "common.ConceptScheme":
174176

175177

176178
def get_msd() -> "v21.MetadataStructureDefinition":
179+
"""Generate and return the TDC metadata structure definition."""
177180
from transport_data import STORE
178181
from transport_data.org import get_agencyscheme
179182

transport_data/org/metadata/report.py

+96-28
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
"""Generate reports about TDC-structured metadata.
2+
3+
:class:`.Report` subclasses in this file **should** have names like::
4+
5+
{ Type }{ ID }{ Format }
6+
7+
…wherein:
8+
9+
- ``{ Type }`` refers to the type of object(s) from the SDMX Information Model that
10+
is/are represented in the report.
11+
Usually the first argument to the :py:`__init__()` method is an instance of this type.
12+
- ``{ ID }`` is a number that distinguishes different ‘kinds’ of reports for the same
13+
``{ Type }``.
14+
Report classes with the same ``{ Type }{ ID }`` **should** display roughly the same
15+
information in the same order and layout, regardless of ``{ Format }``.
16+
- ``{ Format }`` is the output format or file type.
17+
"""
18+
119
from dataclasses import dataclass
220
from functools import partial
321
from typing import TYPE_CHECKING
@@ -11,9 +29,15 @@
1129

1230
@dataclass
1331
class MetadataAttribute0Plain(Report):
14-
"""Summarize unique values appearing in `mds` for attribute `mda_id`."""
32+
"""Unique values appearing in `mds` for metadata attribute `mda_id`.
33+
34+
Each unique value is shown with the IDs of the data flows that contain the value for
35+
`mda_id`.
36+
"""
1537

38+
#: Metadata set to report.
1639
mds: "v21.MetadataSet"
40+
#: ID of a Metadata Attribute to report.
1741
mda_id: str
1842

1943
def render(self) -> str:
@@ -34,10 +58,16 @@ def render(self) -> str:
3458

3559
@dataclass
3660
class MetadataAttribute0RST(Report):
37-
"""Summarize unique values appearing in `mds` for attribute `mda_id`."""
61+
"""Unique values appearing in `mds` for the metadata attribute `mda_id`.
3862
63+
Same as :class:`.MetadataAttribute0Plain`, but in reStructuredText.
64+
"""
65+
66+
#: Jinja2 reStructuredText template.
3967
template_name = "metadata-attribute-0.rst"
68+
#: Metadata set to report.
4069
mds: "v21.MetadataSet"
70+
#: ID of a Metadata Attribute to report.
4171
mda_id: str
4272

4373
def render(self) -> str:
@@ -52,6 +82,9 @@ def render(self) -> str:
5282

5383
@dataclass
5484
class MetadataReport0HTML(Report):
85+
"""Same as :class:`.MetadataReport0Plain`, but in HTML."""
86+
87+
#: Metadata report to report.
5588
mdr: "v21.MetadataReport"
5689

5790
def render(self) -> str:
@@ -60,6 +93,15 @@ def render(self) -> str:
6093

6194
@dataclass
6295
class MetadataReport0Plain(Report):
96+
"""Contents of a single metadata report.
97+
98+
This includes:
99+
100+
1. The reported attribute values for all metadata attributes.
101+
2. The data flow that is targeted by the report and its dimensions.
102+
"""
103+
104+
#: Metadata report to report.
63105
mdr: "v21.MetadataReport"
64106

65107
def render(self) -> str:
@@ -100,9 +142,15 @@ def render(self) -> str:
100142

101143
@dataclass
102144
class MetadataSet0ODT(Report):
103-
"""Print a summary of the contents of `mds`."""
145+
"""Summary of the unique reported attribute values in `mds`.
146+
147+
Similar to :class:`.MetadataSet0Plain`, but also including:
148+
149+
- The unique dimension concepts appearing in the data structure definitions.
150+
"""
104151

105152
template_name = "metadata-set-0.rst"
153+
#: Metadata set to report.
106154
mds: "v21.MetadataSet"
107155

108156
def render(self) -> bytes:
@@ -124,8 +172,15 @@ def render(self) -> bytes:
124172

125173
@dataclass
126174
class MetadataSet0Plain(Report):
127-
"""Print a summary of the contents of `mds`."""
175+
"""Summary of the unique reported attribute values in `mds`.
176+
177+
This includes:
128178
179+
- Unique values of the metadata attributes ``MEASURE``, ``DATA_PROVIDER``, and
180+
``UNIT_MEASURE``.
181+
"""
182+
183+
#: Metadata set to report.
129184
mds: "v21.MetadataSet"
130185

131186
def render(self) -> str:
@@ -144,7 +199,7 @@ def render(self) -> str:
144199

145200
@dataclass
146201
class MetadataSet1HTML(Report):
147-
"""Generate a summary report in HTML."""
202+
"""Metadata reports related to `ref_area`."""
148203

149204
template_name = "metadata-set-1.html"
150205

@@ -166,31 +221,12 @@ def render(self) -> str:
166221

167222

168223
@dataclass
169-
class MetadataSet2HTML(Report):
170-
"""Generate a summary report in HTML."""
171-
172-
template_name = "metadata-set-2.html"
173-
174-
#: Metadata set to summarize.
175-
mds: "v21.MetadataSet"
176-
#: Geography.
177-
ref_area: list[str]
178-
179-
def render(self) -> str:
180-
from transport_data.org.metadata import contains_data_for
181-
182-
data = {
183-
mdr.attaches_to.key_values["DATAFLOW"].obj.id: { # type: ignore [union-attr]
184-
ra: contains_data_for(mdr, ra) for ra in self.ref_area
185-
}
186-
for mdr in self.mds.report
187-
}
188-
189-
return self.render_jinja_template(ref_area=self.ref_area, data=data)
224+
class MetadataSet1ODT(Report):
225+
"""Metadata reports related to `ref_area`.
190226
227+
Same as :class:`.MetadataSet1HTML` but as OpenDocument Text.
228+
"""
191229

192-
@dataclass
193-
class MetadataSet1ODT(Report):
194230
template_name = "metadata-set-1.rst"
195231

196232
#: Metadata set to summarize.
@@ -216,3 +252,35 @@ def render(self) -> bytes:
216252

217253
# Convert reStructuredText → OpenDocumentText
218254
return self.rst2odt(rst_source)
255+
256+
257+
@dataclass
258+
class MetadataSet2HTML(Report):
259+
"""Table of metadata reports.
260+
261+
This table has:
262+
263+
- One *column* per value in `ref_areas`.
264+
- One *row* per metadata report in `mds`.
265+
- A check-mark in cells where :func:`.contains_data_for` indicates that the metadata
266+
report targets a data flow that contains data for the reference area.
267+
"""
268+
269+
template_name = "metadata-set-2.html"
270+
271+
#: Metadata set to summarize.
272+
mds: "v21.MetadataSet"
273+
#: Geographies to show.
274+
ref_area: list[str]
275+
276+
def render(self) -> str:
277+
from transport_data.org.metadata import contains_data_for
278+
279+
data = {
280+
mdr.attaches_to.key_values["DATAFLOW"].obj.id: { # type: ignore [union-attr]
281+
ra: contains_data_for(mdr, ra) for ra in self.ref_area
282+
}
283+
for mdr in self.mds.report
284+
}
285+
286+
return self.render_jinja_template(ref_area=self.ref_area, data=data)

transport_data/org/metadata/spreadsheet.py

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""Non-standard TDC Excel file format for collecting metadata."""
2+
13
import logging
24
import re
35
from typing import TYPE_CHECKING, List, Optional, Tuple

transport_data/util/docutils.py

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""Utilities for :mod:`docutils`."""
2+
13
from pathlib import Path
24
from zipfile import BadZipFile, ZipFile
35

transport_data/util/hooks.py

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""Plug-in hooks to be implemented by submodules and other packages."""
2+
13
from typing import TYPE_CHECKING, Iterable
24

35
import pluggy

transport_data/util/jinja2.py

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""Utilities for :mod:`jinja2`."""
2+
13
from functools import lru_cache
24

35

transport_data/util/pluggy.py

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""Utilities for :mod:`pluggy`."""
2+
13
from importlib import import_module
24

35
import pluggy

transport_data/util/pycountry.py

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
"""Utilities for working with pycountry_.
2+
3+
.. _pycountry: https://pypi.org/project/pycountry/
4+
"""
5+
16
#: Mapping from country name forms appearing in data to values recognized by
27
#: :meth:`pycountry.countries.lookup`.
38
NAME_MAP = {

0 commit comments

Comments
 (0)