Skip to content

Commit c4ff7ba

Browse files
authored
Merge pull request #154 from google/improve-reference
Improve reference
2 parents fdb045e + 9c7f3dd commit c4ff7ba

File tree

114 files changed

+2911
-2605
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

114 files changed

+2911
-2605
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ tmp
66
build_package
77
.ipynb_checkpoints
88
tmp_*
9+
.cache/
910
.env
1011

1112
# benchmark outputs
@@ -18,7 +19,7 @@ profile.*
1819
site/
1920

2021
# Build outputs
21-
build
22+
build/
2223
dist
2324
setup.py
2425
temporian.egg-info

.vscode/settings.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,17 @@
1717
"[python]": {
1818
"editor.defaultFormatter": "ms-python.black-formatter"
1919
},
20+
"black-formatter.path": [
21+
"${workspaceFolder}/.venv/bin/black"
22+
],
2023
"editor.tabSize": 4,
2124
"editor.formatOnSave": true,
2225
"python.linting.flake8Enabled": false,
2326
"python.linting.pylintEnabled": true,
2427
"python.linting.enabled": true,
25-
"editor.rulers": [80],
28+
"editor.rulers": [
29+
80
30+
],
2631
"editor.codeActionsOnSave": {
2732
"source.organizeImports": false
2833
},
@@ -82,4 +87,4 @@
8287
"span": "cpp",
8388
"algorithm": "cpp"
8489
}
85-
}
90+
}

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,22 +43,22 @@ date,feature_1,feature_2
4343
2023-02-01,30.0,5.0
4444
```
4545

46-
Check the [Getting Started tutorial](https://temporian.readthedocs.io/en/latest/tutorials/getting_started/) to try it out!
46+
Check the [Getting Started tutorial](https://temporian.readthedocs.io/en/stable/tutorials/getting_started/) to try it out!
4747

4848
## Key features
4949

5050
These are what set Temporian apart.
5151

5252
- **Simple and powerful API**: Temporian exports high level operations making processing complex programs short and ready to read.
5353
- **Flexible data model**: Temporian models temporal data as a sequence of events, supporting non-uniform sampling timestamps seamlessly.
54-
- **Prevents modeling errors**: Temporian programs are guaranteed not to have future leakage unless the user calls the `leak` function, ensuring that models are not trained on future data.
54+
- **Prevents modeling errors**: Temporian programs are guaranteed not to have future leakage unless explicitly specified, ensuring that models are not trained on future data.
5555
- **Iterative development**: Temporian can be used to develop preprocessing pipelines in Colab or local notebooks, allowing users to visualize results each step of the way to identify and correct errors early on.
5656
- **Efficient and well-tested implementations**: Temporian contains efficient and well-tested implementations of a variety of temporal data processing functions. For instance, our implementation of window operators is **x2000** faster than the same function implemented with NumPy.
57-
- **Wide range of preprocessing functions**: Temporian contains a wide range of preprocessing functions, including moving window operations, lagging, calendar features, arithmetic operations, index manipulation and propagation, resampling, and more. For a full list of the available operators, see the [operators documentation](https://temporian.readthedocs.io/en/latest/reference/temporian/core/operators/all_operators/).
57+
- **Wide range of preprocessing functions**: Temporian contains a wide range of preprocessing functions, including moving window operations, lagging, calendar features, arithmetic operations, index manipulation and propagation, resampling, and more. For a full list of the available operators, see the [operators documentation](https://temporian.readthedocs.io/en/stable/reference/).
5858

5959
## Documentation
6060

61-
The official documentation is available at [temporian.readthedocs.io](https://temporian.readthedocs.io/en/latest/).
61+
The official documentation is available at [temporian.readthedocs.io](https://temporian.readthedocs.io/en/stable/).
6262

6363
## Contributing
6464

docs/gen_ref_pages.py

Lines changed: 71 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -5,85 +5,107 @@
55
"""
66

77
from pathlib import Path
8+
from typing import Set, Tuple
89

910
import mkdocs_gen_files
1011

1112
nav = mkdocs_gen_files.Nav()
1213

1314
SRC_PATH = Path("temporian")
1415

15-
paths = set()
16+
# Stores symbol and path of each public API member
17+
members: Set[Tuple[str, Path]] = set()
18+
1619
non_parsable_imports = []
1720

18-
with open("temporian/__init__.py", "r", encoding="utf8") as f:
19-
lines = f.read().splitlines()
21+
# We need to be able to parse other files to allow wildcard imports
22+
# Storing pair of (prefix, path) to parse in a stack
23+
files_to_parse = [(None, SRC_PATH / "__init__.py")]
24+
25+
while files_to_parse:
26+
prefix, file = files_to_parse.pop()
27+
28+
with open(file, "r", encoding="utf8") as f:
29+
lines = f.read().splitlines()
30+
31+
for line in lines:
32+
words = line.split(" ")
33+
34+
# It is an import statement
35+
if words[0] == "from":
36+
# Remove trailing "as <name>" if it exists and save symbol's name
37+
symbol = None
38+
if words[-2] == "as":
39+
# If symbol was renamed to a private name, skip it
40+
if words[-1].startswith("_"):
41+
continue
2042

21-
for line in lines:
22-
words = line.split(" ")
43+
symbol = words[-1]
44+
words = words[:-2]
2345

24-
# It is an import statement
25-
if words[0] == "from":
26-
# Remove trailing "as <name>" if it exists
27-
if words[-2] == "as":
28-
# If symbol was renamed to a private name, skip it
29-
if words[-1].startswith("_"):
30-
continue
46+
# `words` is now in the form "from module.submodule import symbol"
47+
if words[-2] == "import":
48+
name = words[-1]
3149

32-
words = words[:-2]
50+
# We only allow wildcard imports from modules explicitly named
51+
# api_symbols to prevent unwanted names in the public API
52+
if name == "*":
53+
module_path = Path(words[1].replace(".", "/")).with_suffix(
54+
".py"
55+
)
56+
if module_path.stem == "api_symbols":
57+
new_prefix = (
58+
(prefix + ".") if prefix else ""
59+
) + module_path.parent.name
60+
files_to_parse.append((new_prefix, module_path))
61+
continue
3362

34-
# It is a single-symbol import like "from <module> import <symbol>"
35-
if words[-2] == "import":
36-
module_path = Path(words[1].replace(".", "/"))
63+
non_parsable_imports.append(line)
64+
continue
3765

38-
# Check if the import is a dir module
39-
module_path_with_suffix = module_path / words[-1]
40-
if module_path_with_suffix.exists():
41-
module_path = module_path_with_suffix
66+
# If symbol wasn't renamed, use its imported name
67+
if symbol is None:
68+
symbol = name
4269

43-
# Check if the import is a file module
44-
module_path_with_suffix = module_path / (words[-1] + ".py")
45-
if module_path_with_suffix.exists():
46-
module_path = module_path_with_suffix.with_suffix("")
70+
path = Path(words[1].replace(".", "/")) / name
4771

48-
# If it's not a module import it is a normal symbol import
49-
# (function, class, etc.) so we add its whole module to the docs
72+
if prefix:
73+
symbol = prefix + "." + symbol
5074

51-
paths.add(module_path)
75+
members.add((symbol, path))
5276

53-
else:
54-
non_parsable_imports.append(line)
77+
# It is a multi-symbol import statement, error will be raised below
78+
else:
79+
non_parsable_imports.append(line)
5580

5681
if non_parsable_imports:
5782
raise RuntimeError(
5883
"`gen_ref_pages` failed to parse the following import statements in"
5984
f" the top-level __init__.py file: {non_parsable_imports}. Import"
6085
" statements in the top-level module must import a single symbol each,"
61-
" in the form `from <module> import <symbol>` or `from <module> import"
62-
" <symbol> as <name>`."
86+
" in the form `from <module> import <symbol>`, `from <module> import"
87+
" <symbol> as <name>`, or `from <module> import *`."
6388
)
6489

65-
for path in sorted(paths):
66-
if path.parent.name not in ["test", "tests"]:
67-
module_path = path.relative_to(SRC_PATH.parent).with_suffix("")
68-
doc_path = path.relative_to(SRC_PATH.parent).with_suffix(".md")
69-
full_doc_path = Path("reference", doc_path)
90+
nav["temporian"] = "index.md"
7091

71-
parts = list(module_path.parts)
92+
for symbol, path in sorted(members):
93+
symbol_path = Path(symbol.replace(".", "/"))
94+
symbol_name = symbol_path.name
95+
src_path = SRC_PATH / symbol_name
7296

73-
if parts[-1] == "__init__":
74-
parts = parts[:-1]
75-
doc_path = doc_path.with_name("index.md")
76-
full_doc_path = full_doc_path.with_name("index.md")
77-
elif parts[-1] == "__main__":
78-
continue
97+
doc_path = SRC_PATH / symbol_path
98+
parts = list(doc_path.parts)
99+
doc_path = doc_path.with_suffix(".md")
100+
full_doc_path = Path("reference", doc_path)
79101

80-
nav[parts] = doc_path.as_posix()
102+
nav[parts] = doc_path.as_posix()
81103

82-
with mkdocs_gen_files.open(full_doc_path, "w") as fd:
83-
identifier = ".".join(parts)
84-
print("::: " + identifier, file=fd)
104+
with mkdocs_gen_files.open(full_doc_path, "w") as fd:
105+
identifier = ".".join(list(src_path.parts))
106+
print("::: " + identifier, file=fd)
85107

86-
mkdocs_gen_files.set_edit_path(full_doc_path, path)
108+
mkdocs_gen_files.set_edit_path(full_doc_path, path)
87109

88-
with mkdocs_gen_files.open("reference/index.md", "w") as nav_file:
110+
with mkdocs_gen_files.open("reference/SUMMARY.md", "w") as nav_file:
89111
nav_file.writelines(nav.build_literate_nav())

docs/mkdocs.yml

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
site_name: Temporian
2+
site_url: https://temporian.readthedocs.io/en/stable/
3+
site_description: A Python package for feature engineering of temporal data.
4+
25
repo_url: https://github.com/google/temporian
6+
edit_uri_template: tree/main/temporian/{path_noext}
37

48
# Theme
59
theme:
@@ -48,14 +52,8 @@ nav:
4852
plugins:
4953
- search
5054
- exclude-search:
51-
# Avoid this since it excludes all ipynb
52-
exclude_unreferenced: false
53-
# Exclude reference's Index page
5455
exclude:
55-
- reference
56-
# Include all pages inside reference
57-
ignore:
58-
- reference/*
56+
- reference/SUMMARY
5957
- autorefs
6058
- gen-files:
6159
scripts:
@@ -65,6 +63,7 @@ plugins:
6563
- gen_ref_pages.py
6664
- literate-nav:
6765
nav_file: SUMMARY.md
66+
- social
6867
- mkdocs-jupyter:
6968
# Execute notebooks when building docs (set to true when temporian runs in a notebook w/o the start_notebook script).
7069
execute: false
@@ -76,24 +75,28 @@ plugins:
7675
default_handler: python
7776
handlers:
7877
python:
79-
paths: [temporian]
78+
paths: [..]
8079
import:
8180
- https://docs.python.org/3/objects.inv
8281
options:
8382
# https://mkdocstrings.github.io/python/usage/#globallocal-options
8483
docstring_style: google
8584
heading_level: 1
8685
members_order: source
87-
show_source: true
88-
show_root_heading: true
89-
show_category_heading: true
90-
show_submodules: true
86+
show_source: false
87+
show_submodules: false
9188
merge_init_into_class: false
9289
show_signature: true
9390
separate_signature: true
94-
show_signature_annotations: false
95-
show_if_no_docstring: false # TODO: TBD if we want this enabled
96-
group_by_category: false
91+
show_signature_annotations: true
92+
show_if_no_docstring: false
93+
group_by_category: true
94+
show_category_heading: false
95+
show_root_heading: true
96+
# show_root_toc_entry: false
97+
# show_symbol_type_heading: false
98+
# preload_modules: [temporian.core.operators]
99+
# allow_inspection: true
97100

98101
# Customization for Markdown
99102
markdown_extensions:

docs/requirements.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,6 @@ mkdocs-section-index==0.3.5
88
mkdocs-jupyter===0.24.1
99
mkdocs-exclude-search===0.6.5
1010
black==22.12.0
11-
griffe==0.26.0
11+
griffe==0.26.0
12+
cairosvg==2.7.0
13+
pillow==9.5.0

docs/src/3_minutes.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
This is a _very_ quick introduction to how Temporian works. For a complete tour of its capabilities, please refer to the [User Guide](../user_guide).
44

5-
## Events and `EventSets`
5+
## Events and [`EventSets`][temporian.EventSet]
66

77
The most basic unit of data in Temporian is an **event**. An event consists of a timestamp and a set of feature values.
88

9-
Events are not handled individually. Instead, events are grouped together into an **[EventSet](../reference/temporian/implementation/numpy/data/event_set)**.
9+
Events are not handled individually. Instead, events are grouped together into an **[EventSet][temporian.EventSet]**.
1010

11-
`EventSet`s are the main data structure in Temporian, and represent **[multivariate time sequences](../user_guide/#what-is-temporal-data)**. Note that "multivariate" indicates that each event in the time sequence holds several feature values, and "sequence" indicates that the events are not necessarily sampled at a uniform rate (in which case we would call it a time "series").
11+
[`EventSets`][temporian.EventSet] are the main data structure in Temporian, and represent **[multivariate time sequences](../user_guide/#what-is-temporal-data)**. Note that "multivariate" indicates that each event in the time sequence holds several feature values, and "sequence" indicates that the events are not necessarily sampled at a uniform rate (in which case we would call it a time "series").
1212

13-
You can create an `EventSet` from a pandas DataFrame, NumPy arrays, CSV files, and more. Here is an example of an `EventSet` containing four events and three features:
13+
You can create an [`EventSet`][temporian.EventSet] from a pandas DataFrame, NumPy arrays, CSV files, and more. Here is an example of an [`EventSet`][temporian.EventSet] containing four events and three features:
1414

1515
```python
1616
>>> evset = tp.event_set(
@@ -25,21 +25,21 @@ You can create an `EventSet` from a pandas DataFrame, NumPy arrays, CSV files, a
2525

2626
```
2727

28-
An `EventSet` can hold one or several time sequences, depending on what its **[index](../user_guide/#index-horizontal-and-vertical-operators)** is.
28+
An [`EventSet`][temporian.EventSet] can hold one or several time sequences, depending on what its **[index](../user_guide/#index-horizontal-and-vertical-operators)** is.
2929

30-
If the `EventSet` has no index, it will hold a single time sequence, which means that all events will be considered part of the same group and will interact with each other when operators are applied to the `EventSet`.
30+
If the [`EventSet`][temporian.EventSet] has no index, it will hold a single time sequence, which means that all events will be considered part of the same group and will interact with each other when operators are applied to the [`EventSet`][temporian.EventSet].
3131

32-
If the `EventSet` has one (or many) indexes, it will hold one time sequence for each unique value (or unique combination of values) of the indexes, the events will be grouped by their index value, and operators applied to the `EventSet` will be applied to each time sequence independently.
32+
If the [`EventSet`][temporian.EventSet] has one (or many) indexes, it will hold one time sequence for each unique value (or unique combination of values) of the indexes, the events will be grouped by their index value, and operators applied to the [`EventSet`][temporian.EventSet] will be applied to each time sequence independently.
3333

34-
## Graph, `Nodes` and Operators
34+
## Graph, [`Nodes`][temporian.Node] and Operators
3535

3636
There are two big phases in any Temporian script: graph **definition** and **evaluation**. This is a common pattern in computing libraries, and it allows us to perform optimizations before the graph is evaluated, share Temporian programs across different platforms, and more.
3737

38-
A graph is created by using **operators**. For example, the [`tp.simple_moving_average()`](../reference/temporian/core/operators/window/simple_moving_average) operator computes the [simple moving average](https://en.wikipedia.org/wiki/Moving_average) of each feature in an `EventSet`. You can find documentation for all available operators [here](../reference/temporian/core/operators/all_operators).
38+
A graph is created by using **operators**. For example, the [`tp.simple_moving_average()`][temporian.simple_moving_average] operator computes the [simple moving average](https://en.wikipedia.org/wiki/Moving_average) of each feature in an [`EventSet`][temporian.EventSet]. You can find documentation for all available operators [here](../reference/).
3939

4040
Note that when calling operators you are only defining the graph - i.e., you are telling Temporian what operations you want to perform on your data, but those operations are not yet being performed.
4141

42-
Operators are not applied directly to `EventSet`s, but to **[Nodes](../reference/temporian/core/data/node)**. You can think of a `Node` as the placeholder for an `EventSet` in the graph. When applying operators to `Node`s, you get back new `Node`s that are placeholders for the results of those operations. You can create arbitrarily complex graphs by combining operators and nodes.
42+
Operators are not applied directly to [`EventSets`][temporian.EventSet], but to **[Nodes][temporian.Node]**. You can think of a [`Node`][temporian.Node] as the placeholder for an [`EventSet`][temporian.EventSet] in the graph. When applying operators to [`Nodes`][temporian.Node], you get back new [`Nodes`][temporian.Node] that are placeholders for the results of those operations. You can create arbitrarily complex graphs by combining operators and nodes.
4343

4444
```python
4545
>>> # Obtain the Node corresponding to the EventSet we created above
@@ -53,14 +53,14 @@ Operators are not applied directly to `EventSet`s, but to **[Nodes](../reference
5353

5454
<!-- TODO: add image of the generated graph -->
5555

56-
Your graph can now be run by calling [`evaluate()`](../reference/temporian/core/data/node/#temporian.core.data.node.Node.evaluate) on any `Node` in the graph, which will perform all necessary operations and return the resulting `EventSet`.
56+
Your graph can now be run by calling [`.evaluate()`][temporian.Node.evaluate] on any [`Node`][temporian.Node] in the graph, which will perform all necessary operations and return the resulting [`EventSet`][temporian.EventSet].
5757

5858
```python
5959
>>> result = addition_lagged.evaluate(evset)
6060

6161
```
6262

63-
Note that you need to pass the `EventSet`s that correspond to the source `Node`s in the graph to `evaluate()` (since those are not part of the graph definition). Also, several `Node`s can be evaluated at the same time by calling [`tp.evaluate()`](../reference/temporian/core/evaluation/#temporian.core.evaluation.evaluate) directly.
63+
Note that you need to pass the [`EventSets`][temporian.EventSet] that correspond to the source [`Nodes`][temporian.Node] in the graph to [`.evaluate()`][temporian.Node.evaluate] (since those are not part of the graph definition). Also, several [`Nodes`][temporian.Node] can be evaluated at the same time by calling [`tp.evaluate()`][temporian.evaluate] directly.
6464

6565
🥳 Congratulations! You're all set to write your first pieces of Temporian code.
6666

docs/src/css/custom.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
[data-md-color-scheme="temporian"] {
22
--md-primary-fg-color--light: #24201D;
33
--md-primary-fg-color--dark: #24201D;
4+
background-color: red;
5+
--md-default-bg-color: red;
46
}
7+
8+
/* Change background color when dark mode */
9+
[data-md-color-scheme="slate"] {
10+
--md-default-bg-color: #121212;
11+
--md-code-bg-color: #212121;
12+
}

docs/src/reference/index.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# API Reference
2+
3+
Temporian's API Reference.
4+
5+
<!-- TODO: write reference home page. Include table of operators. -->

0 commit comments

Comments
 (0)