Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redo reference #162

Merged
merged 8 commits into from
Jun 23, 2023
Merged
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
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
},
"search.exclude": {
"**/.venv/": true,
"**/bazel-*/**": true
"**/bazel-*/**": true,
"**/reference/**/*.md": true
},
"files.watcherExclude": {
"**/.venv/**": true,
Expand Down
5 changes: 5 additions & 0 deletions docs/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,8 @@ py_test(
"//temporian",
],
)

filegroup(
name = "reference",
srcs = glob(["src/reference/**/*.md"]),
)
127 changes: 37 additions & 90 deletions docs/gen_ref_pages.py
Original file line number Diff line number Diff line change
@@ -1,111 +1,58 @@
"""
Generate the code reference pages.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about adding a comment that tell that this script is executed when running mkdocs serve -f docs/mkdocs.yml?


Source: https://mkdocstrings.github.io/recipes/
This script traverses the markdown files under docs/src/reference and for each:
- If the file is not empty it will appear in the docs as-is (after mkdocstrings
has filled in any identifiers inside it).
- If the file is empty, it is interpreted as a placeholder for the top-level
symbol with its same name and its reference page is generated in its same
path. E.g., if an empty docs/src/reference/temporian/io/to_csv.md file
exists, the reference page for `temporian.to_csv` will be generated under
reference/temporian/io/to_csv/ in the docs.

Related: https://mkdocstrings.github.io/recipes/
"""

from pathlib import Path
from typing import Set, Tuple

import mkdocs_gen_files

nav = mkdocs_gen_files.Nav()

SRC_PATH = Path("temporian")
REFERENCE = Path("docs/src/reference")

# Stores symbol and path of each public API member
members: Set[Tuple[str, Path]] = set()
# Sort files by depth and name for alphabetical order and subdirs at the bottom
paths = sorted(
REFERENCE.rglob("*.md"), key=lambda p: str(len(p.parts)) + str(p)
)

non_parsable_imports = []
non_empty_files = []

# We need to be able to parse other files to allow wildcard imports
# Storing pair of (prefix, path) to parse in a stack
files_to_parse = [(None, SRC_PATH / "__init__.py")]
for path in paths:
ianspektor marked this conversation as resolved.
Show resolved Hide resolved
path = Path(path)
ref_path = path.relative_to(REFERENCE)
nav_path = ref_path.with_suffix("")
full_ref_path = "reference" / ref_path

while files_to_parse:
prefix, file = files_to_parse.pop()
nav[list(nav_path.parts)] = ref_path.as_posix()

with open(file, "r", encoding="utf8") as f:
lines = f.read().splitlines()
# If file is empty we assume it's a top-level symbol and auto
# generate the mkdocstring identifier for it
if path.stat().st_size == 0:
with mkdocs_gen_files.open(full_ref_path, "w") as fd:
ident = "temporian." + nav_path.name
fd.write(f"::: {ident}")
ianspektor marked this conversation as resolved.
Show resolved Hide resolved

for line in lines:
words = line.split(" ")
else:
non_empty_files.append(str(ref_path))

# It is an import statement
if words[0] == "from":
# Remove trailing "as <name>" if it exists and save symbol's name
symbol = None
if words[-2] == "as":
# If symbol was renamed to a private name, skip it
if words[-1].startswith("_"):
continue

symbol = words[-1]
words = words[:-2]

# `words` is now in the form "from module.submodule import symbol"
if words[-2] == "import":
name = words[-1]

# We only allow wildcard imports from modules explicitly named
# api_symbols to prevent unwanted names in the public API
if name == "*":
module_path = Path(words[1].replace(".", "/")).with_suffix(
".py"
)
if module_path.stem == "api_symbols":
new_prefix = (
(prefix + ".") if prefix else ""
) + module_path.parent.name
files_to_parse.append((new_prefix, module_path))
continue

non_parsable_imports.append(line)
continue

# If symbol wasn't renamed, use its imported name
if symbol is None:
symbol = name

path = Path(words[1].replace(".", "/")) / name

if prefix:
symbol = prefix + "." + symbol

members.add((symbol, path))

# It is a multi-symbol import statement, error will be raised below
else:
non_parsable_imports.append(line)

if non_parsable_imports:
raise RuntimeError(
"`gen_ref_pages` failed to parse the following import statements in"
f" the top-level __init__.py file: {non_parsable_imports}. Import"
" statements in the top-level module must import a single symbol each,"
" in the form `from <module> import <symbol>`, `from <module> import"
" <symbol> as <name>`, or `from <module> import *`."
)

nav["temporian"] = "index.md"

for symbol, path in sorted(members):
symbol_path = Path(symbol.replace(".", "/"))
symbol_name = symbol_path.name
src_path = SRC_PATH / symbol_name

doc_path = SRC_PATH / symbol_path
parts = list(doc_path.parts)
doc_path = doc_path.with_suffix(".md")
full_doc_path = Path("reference", doc_path)

nav[parts] = doc_path.as_posix()

with mkdocs_gen_files.open(full_doc_path, "w") as fd:
identifier = ".".join(list(src_path.parts))
print("::: " + identifier, file=fd)

mkdocs_gen_files.set_edit_path(full_doc_path, path)
print(
(
"These md files in docs/src/reference are not empty and will be"
" rendered my mkdocs as-is:"
),
non_empty_files,
)

with mkdocs_gen_files.open("reference/SUMMARY.md", "w") as nav_file:
nav_file.writelines(nav.build_literate_nav())
2 changes: 1 addition & 1 deletion docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ plugins:
scripts:
# Generate the index page from the README.md.
- gen_index.py
# Generate the reference pages from docstrings.
# Generate the ref pages and navigation.
- gen_ref_pages.py
- literate-nav:
nav_file: SUMMARY.md
Expand Down
12 changes: 6 additions & 6 deletions docs/src/reference/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Check the index on the left for a more detailed description of any symbol.
| ----------------------------------------- | -------------------------------------------------------------------------------------- |
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This front page is now awesome.

| [`tp.evaluate()`][temporian.evaluate] | Evaluates [`Nodes`][temporian.Node] on [`EventSets`][temporian.EventSet]. |
| [`tp.plot()`][temporian.plot] | Plots [`EventSets`][temporian.EventSet]. |
| [`tp.event_set()`][temporian.event_set] | Creates an [`EventSet`][temporian.EventSet] from arrays (list, numpy, pandas). |
| [`tp.event_set()`][temporian.event_set] | Creates an [`EventSet`][temporian.EventSet] from arrays (lists, NumPy, Pandas Series.) |
| [`tp.input_node()`][temporian.input_node] | Creates an input [`Node`][temporian.Node], that can be used to feed data into a graph. |

## Input/output
Expand Down Expand Up @@ -60,11 +60,11 @@ Check the index on the left for a more detailed description of any symbol.

### Binary operators

| Symbols | Description |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| [`tp.add()`][temporian.add] [`tp.subtract()`][temporian.subtract] [`tp.multiply()`][temporian.multiply] [`tp.divide()`][temporian.divide] [`tp.floordiv()`][temporian.floordiv] [`tp.modulo()`][temporian.modulo] [`tp.power()`][temporian.power] | Compute an arithmetic binary operation between two [`Nodes`][temporian.Node]. |
| [`tp.equal()`][temporian.equal] [`tp.not_equal()`][temporian.not_equal] [`tp.greater()`][temporian.greater] [`tp.greater_equal()`][temporian.greater_equal] [`tp.less()`][temporian.less] [`tp.less_equal()`][temporian.less_equal] | Compute a relational binary operator between two [`Nodes`][temporian.Node]. |
| [`tp.logical_and()`][temporian.logical_and] [`tp.logical_or()`][temporian.logical_or] [`tp.logical_xor()`][temporian.logical_xor] | Compute a logical binary operation between two [`Nodes`][temporian.Node]. |
| Symbols | Description |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| [`tp.add()`][temporian.add] [`tp.subtract()`][temporian.subtract] [`tp.multiply()`][temporian.multiply] [`tp.divide()`][temporian.divide] [`tp.floordiv()`][temporian.floordiv] [`tp.modulo()`][temporian.modulo] [`tp.power()`][temporian.power] | Compute an arithmetic binary operation between two [`Nodes`][temporian.Node]. Aliases for `+`, `-`, `\*`, `/`, etc. |
| [`tp.equal()`][temporian.equal] [`tp.not_equal()`][temporian.not_equal] [`tp.greater()`][temporian.greater] [`tp.greater_equal()`][temporian.greater_equal] [`tp.less()`][temporian.less] [`tp.less_equal()`][temporian.less_equal] | Compute a relational binary operator between two [`Nodes`][temporian.Node]. |
| [`tp.logical_and()`][temporian.logical_and] [`tp.logical_or()`][temporian.logical_or] [`tp.logical_xor()`][temporian.logical_xor] | Compute a logical binary operation between two [`Nodes`][temporian.Node]. |

### Unary operators

Expand Down
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
29 changes: 25 additions & 4 deletions temporian/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,37 @@ py_library(
"//temporian/core:evaluation",
"//temporian/core:graph",
"//temporian/core:operator_lib",
"//temporian/core:serialization",
"//temporian/core/data:dtype",
"//temporian/core/data:duration",
"//temporian/core/data:node",
"//temporian/core/data:schema",
"//temporian/core/data/dtypes:api_symbols",
"//temporian/core/operators:api_symbols",
"//temporian/core/operators:add_index",
"//temporian/core/operators:base",
"//temporian/core/serialization:api_symbols",
"//temporian/core/operators:begin",
"//temporian/core/operators:cast",
"//temporian/core/operators:drop_index",
"//temporian/core/operators:end",
"//temporian/core/operators:filter",
"//temporian/core/operators:glue",
"//temporian/core/operators:lag",
"//temporian/core/operators:leak",
"//temporian/core/operators:prefix",
"//temporian/core/operators:propagate",
"//temporian/core/operators:rename",
"//temporian/core/operators:resample",
"//temporian/core/operators:select",
"//temporian/core/operators:since_last",
"//temporian/core/operators:tick",
"//temporian/core/operators:unary",
"//temporian/core/operators:unique_timestamps",
"//temporian/core/operators/binary",
"//temporian/core/operators/calendar",
"//temporian/core/operators/scalar",
"//temporian/core/operators/window",
"//temporian/implementation/numpy/data:event_set",
"//temporian/implementation/numpy/data:io",
"//temporian/implementation/numpy/data:plotter",
"//temporian/io:api_symbols",
"//temporian/io",
],
)
Loading