From 8c35e79bed33e98de8a188a12541e4a963ca8439 Mon Sep 17 00:00:00 2001 From: Eric Pinzur Date: Sun, 8 Oct 2023 08:42:22 -0500 Subject: [PATCH 01/14] removed old docs --- python/docs/.gitignore | 5 - .../source/_extensions/gallery_directive.py | 144 -------- python/docs/source/_layouts/default.yml | 46 --- python/docs/source/_static/favicon.png | Bin 5056 -> 0 bytes .../docs/source/_static/kaskada-negative.svg | 1 - .../docs/source/_static/kaskada-positive.svg | 1 - .../source/_templates/autosummary/class.rst | 10 - .../_templates/autosummary/function.rst | 7 - .../source/_templates/autosummary/method.rst | 7 - python/docs/source/blog/index.md | 9 - .../2023-03-28-announcing-kaskada-oss.md | 76 ---- .../blog/posts/2023-08-25-new-kaskada.md | 85 ----- python/docs/source/community/index.md | 38 -- python/docs/source/conf.py | 183 ---------- python/docs/source/examples/bluesky.md | 73 ---- python/docs/source/examples/bluesky.py | 184 ---------- python/docs/source/examples/index.md | 17 - python/docs/source/examples/reddit.md | 73 ---- python/docs/source/examples/reddit.py | 92 ----- .../docs/source/examples/time_centric.ipynb | 344 ------------------ python/docs/source/guide/aggregation.md | 41 --- python/docs/source/guide/data_types.md | 118 ------ python/docs/source/guide/entities.md | 109 ------ python/docs/source/guide/execution.md | 91 ----- python/docs/source/guide/index.md | 51 --- python/docs/source/guide/installation.md | 23 -- python/docs/source/guide/joins.md | 34 -- python/docs/source/guide/quickstart.md | 47 --- python/docs/source/guide/sources.md | 11 - python/docs/source/guide/timestreams.md | 59 --- python/docs/source/guide/tour.md | 124 ------- python/docs/source/guide/why.md | 15 - python/docs/source/index.md | 119 ------ python/docs/source/reference/destinations.md | 11 - python/docs/source/reference/execution.md | 11 - python/docs/source/reference/index.md | 13 - python/docs/source/reference/results.md | 13 - python/docs/source/reference/sources.md | 17 - .../reference/timestream/aggregation.md | 28 -- .../source/reference/timestream/arithmetic.md | 33 -- .../source/reference/timestream/collection.md | 18 - .../source/reference/timestream/comparison.md | 29 -- .../source/reference/timestream/execution.md | 13 - .../source/reference/timestream/grouping.md | 11 - .../docs/source/reference/timestream/index.md | 33 -- .../source/reference/timestream/logical.md | 12 - .../docs/source/reference/timestream/misc.md | 18 - .../source/reference/timestream/records.md | 19 - .../source/reference/timestream/string.md | 13 - .../docs/source/reference/timestream/time.md | 15 - python/docs/source/reference/windows.md | 13 - 51 files changed, 2557 deletions(-) delete mode 100644 python/docs/.gitignore delete mode 100644 python/docs/source/_extensions/gallery_directive.py delete mode 100644 python/docs/source/_layouts/default.yml delete mode 100644 python/docs/source/_static/favicon.png delete mode 100644 python/docs/source/_static/kaskada-negative.svg delete mode 100644 python/docs/source/_static/kaskada-positive.svg delete mode 100644 python/docs/source/_templates/autosummary/class.rst delete mode 100644 python/docs/source/_templates/autosummary/function.rst delete mode 100644 python/docs/source/_templates/autosummary/method.rst delete mode 100644 python/docs/source/blog/index.md delete mode 100644 python/docs/source/blog/posts/2023-03-28-announcing-kaskada-oss.md delete mode 100644 python/docs/source/blog/posts/2023-08-25-new-kaskada.md delete mode 100644 python/docs/source/community/index.md delete mode 100644 python/docs/source/conf.py delete mode 100644 python/docs/source/examples/bluesky.md delete mode 100644 python/docs/source/examples/bluesky.py delete mode 100644 python/docs/source/examples/index.md delete mode 100644 python/docs/source/examples/reddit.md delete mode 100644 python/docs/source/examples/reddit.py delete mode 100644 python/docs/source/examples/time_centric.ipynb delete mode 100644 python/docs/source/guide/aggregation.md delete mode 100644 python/docs/source/guide/data_types.md delete mode 100644 python/docs/source/guide/entities.md delete mode 100644 python/docs/source/guide/execution.md delete mode 100644 python/docs/source/guide/index.md delete mode 100644 python/docs/source/guide/installation.md delete mode 100644 python/docs/source/guide/joins.md delete mode 100644 python/docs/source/guide/quickstart.md delete mode 100644 python/docs/source/guide/sources.md delete mode 100644 python/docs/source/guide/timestreams.md delete mode 100644 python/docs/source/guide/tour.md delete mode 100644 python/docs/source/guide/why.md delete mode 100644 python/docs/source/index.md delete mode 100644 python/docs/source/reference/destinations.md delete mode 100644 python/docs/source/reference/execution.md delete mode 100644 python/docs/source/reference/index.md delete mode 100644 python/docs/source/reference/results.md delete mode 100644 python/docs/source/reference/sources.md delete mode 100644 python/docs/source/reference/timestream/aggregation.md delete mode 100644 python/docs/source/reference/timestream/arithmetic.md delete mode 100644 python/docs/source/reference/timestream/collection.md delete mode 100644 python/docs/source/reference/timestream/comparison.md delete mode 100644 python/docs/source/reference/timestream/execution.md delete mode 100644 python/docs/source/reference/timestream/grouping.md delete mode 100644 python/docs/source/reference/timestream/index.md delete mode 100644 python/docs/source/reference/timestream/logical.md delete mode 100644 python/docs/source/reference/timestream/misc.md delete mode 100644 python/docs/source/reference/timestream/records.md delete mode 100644 python/docs/source/reference/timestream/string.md delete mode 100644 python/docs/source/reference/timestream/time.md delete mode 100644 python/docs/source/reference/windows.md diff --git a/python/docs/.gitignore b/python/docs/.gitignore deleted file mode 100644 index c52066621..000000000 --- a/python/docs/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -_build -.jupyter_cache -jupyter_execute -source/reference/apidocs -source/iframe_figures \ No newline at end of file diff --git a/python/docs/source/_extensions/gallery_directive.py b/python/docs/source/_extensions/gallery_directive.py deleted file mode 100644 index 5c3ef3fdc..000000000 --- a/python/docs/source/_extensions/gallery_directive.py +++ /dev/null @@ -1,144 +0,0 @@ -"""A directive to generate a gallery of images from structured data. - -Generating a gallery of images that are all the same size is a common -pattern in documentation, and this can be cumbersome if the gallery is -generated programmatically. This directive wraps this particular use-case -in a helper-directive to generate it with a single YAML configuration file. - -It currently exists for maintainers of the pydata-sphinx-theme, -but might be abstracted into a standalone package if it proves useful. -""" -from pathlib import Path -from typing import Any, Dict, List - -from docutils import nodes -from docutils.parsers.rst import directives -from sphinx.application import Sphinx -from sphinx.util import logging -from sphinx.util.docutils import SphinxDirective -from yaml import safe_load - - -logger = logging.getLogger(__name__) - - -TEMPLATE_GRID = """ -`````{{grid}} {columns} -{options} - -{content} - -````` -""" - -GRID_CARD = """ -````{{grid-item-card}} {title} -{options} - -{content} -```` -""" - - -class GalleryGridDirective(SphinxDirective): - """A directive to show a gallery of images and links in a Bootstrap grid. - - The grid can be generated from a YAML file that contains a list of items, or - from the content of the directive (also formatted in YAML). Use the parameter - "class-card" to add an additional CSS class to all cards. When specifying the grid - items, you can use all parameters from "grid-item-card" directive to customize - individual cards + ["image", "header", "content", "title"]. - - Danger: - This directive can only be used in the context of a Myst documentation page as - the templates use Markdown flavored formatting. - """ - - name = "gallery-grid" - has_content = True - required_arguments = 0 - optional_arguments = 1 - final_argument_whitespace = True - option_spec = { - # A class to be added to the resulting container - "grid-columns": directives.unchanged, - "class-container": directives.unchanged, - "class-card": directives.unchanged, - } - - def run(self) -> List[nodes.Node]: - """Create the gallery grid.""" - if self.arguments: - # If an argument is given, assume it's a path to a YAML file - # Parse it and load it into the directive content - path_data_rel = Path(self.arguments[0]) - path_doc, _ = self.get_source_info() - path_doc = Path(path_doc).parent - path_data = (path_doc / path_data_rel).resolve() - if not path_data.exists(): - logger.warn(f"Could not find grid data at {path_data}.") - nodes.text("No grid data found at {path_data}.") - return - yaml_string = path_data.read_text() - else: - yaml_string = "\n".join(self.content) - - # Use all the element with an img-bottom key as sites to show - # and generate a card item for each of them - grid_items = [] - for item in safe_load(yaml_string): - # remove parameters that are not needed for the card options - title = item.pop("title", "") - - # build the content of the card using some extra parameters - header = f"{item.pop('header')} \n^^^ \n" if "header" in item else "" - image = f"![image]({item.pop('image')}) \n" if "image" in item else "" - content = f"{item.pop('content')} \n" if "content" in item else "" - - # optional parameter that influence all cards - if "class-card" in self.options: - item["class-card"] = self.options["class-card"] - - loc_options_str = "\n".join(f":{k}: {v}" for k, v in item.items()) + " \n" - - card = GRID_CARD.format( - options=loc_options_str, content=header + image + content, title=title - ) - grid_items.append(card) - - # Parse the template with Sphinx Design to create an output container - # Prep the options for the template grid - class_ = "gallery-directive" + f' {self.options.get("class-container", "")}' - options = {"gutter": 2, "class-container": class_} - options_str = "\n".join(f":{k}: {v}" for k, v in options.items()) - - # Create the directive string for the grid - grid_directive = TEMPLATE_GRID.format( - columns=self.options.get("grid-columns", "1 2 3 4"), - options=options_str, - content="\n".join(grid_items), - ) - - # Parse content as a directive so Sphinx Design processes it - container = nodes.container() - self.state.nested_parse([grid_directive], 0, container) - - # Sphinx Design outputs a container too, so just use that - return [container.children[0]] - - -def setup(app: Sphinx) -> Dict[str, Any]: - """Add custom configuration to sphinx app. - - Args: - app: the Sphinx application - - Returns: - the 2 parallel parameters set to ``True``. - """ - app.add_directive("gallery-grid", GalleryGridDirective) - - return { - "parallel_read_safe": True, - "parallel_write_safe": True, - } diff --git a/python/docs/source/_layouts/default.yml b/python/docs/source/_layouts/default.yml deleted file mode 100644 index bc243933e..000000000 --- a/python/docs/source/_layouts/default.yml +++ /dev/null @@ -1,46 +0,0 @@ -layers: - # the base layer for the background - - background: - color: "#26364a" - image: >- - #% if page.meta.card_image -%# - '{{ page.meta.card_image }}' - #%- elif layout.background_image -%# - '{{ layout.background_image }}' - #%- endif %# - # the layer for the logo image - - size: { width: 300, height: 83 } - offset: { x: 60, y: 60 } - icon: - image: "_static/kaskada-negative.svg" - # the layer for the page's title - - size: { width: 920, height: 300 } - offset: { x: 60, y: 180 } - typography: - content: >- - #% if page.meta.title -%# - '{{ page.meta.title }}' - #%- elif page.title -%# - '{{ page.title }}' - #%- endif %# - line: - # height: 0.85 - amount: 3 - font: - weight: 500 - color: white - # the layer for the site's (or page's) description - - offset: { x: 60, y: 480 } - size: { width: 1080, height: 90 } - typography: - content: >- - #% if page.meta and page.meta.description -%# - '{{ page.meta.description }}' - #%- else -%# - '{{ config.site_description }}' - #%- endif %# - line: - height: 0.87 - amount: 2 - align: start bottom - color: white \ No newline at end of file diff --git a/python/docs/source/_static/favicon.png b/python/docs/source/_static/favicon.png deleted file mode 100644 index 2983af6ae2d35357be1fe4f1f9a15e488e07eae2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5056 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 W<%7kilPt>s0000r}h diff --git a/python/docs/source/_static/kaskada-negative.svg b/python/docs/source/_static/kaskada-negative.svg deleted file mode 100644 index 6b78c25fc..000000000 --- a/python/docs/source/_static/kaskada-negative.svg +++ /dev/null @@ -1 +0,0 @@ -Kaskada Logo Horizontal Negative RGB \ No newline at end of file diff --git a/python/docs/source/_static/kaskada-positive.svg b/python/docs/source/_static/kaskada-positive.svg deleted file mode 100644 index ccfae84e2..000000000 --- a/python/docs/source/_static/kaskada-positive.svg +++ /dev/null @@ -1 +0,0 @@ -Kaskada Logo Horizontal Positive RGB \ No newline at end of file diff --git a/python/docs/source/_templates/autosummary/class.rst b/python/docs/source/_templates/autosummary/class.rst deleted file mode 100644 index bc23de59b..000000000 --- a/python/docs/source/_templates/autosummary/class.rst +++ /dev/null @@ -1,10 +0,0 @@ -:html_theme.sidebar_secondary.remove: - -{{ objname | escape | underline}} - -.. currentmodule:: {{ module }} - -.. auto{{ objtype }}:: {{ objname }} - :members: - :undoc-members: - :show-inheritance: \ No newline at end of file diff --git a/python/docs/source/_templates/autosummary/function.rst b/python/docs/source/_templates/autosummary/function.rst deleted file mode 100644 index 5a51f80a5..000000000 --- a/python/docs/source/_templates/autosummary/function.rst +++ /dev/null @@ -1,7 +0,0 @@ -:html_theme.sidebar_secondary.remove: - -{{ objname | escape | underline}} - -.. currentmodule:: {{ module }} - -.. auto{{ objtype }}:: {{ objname }} \ No newline at end of file diff --git a/python/docs/source/_templates/autosummary/method.rst b/python/docs/source/_templates/autosummary/method.rst deleted file mode 100644 index 5a51f80a5..000000000 --- a/python/docs/source/_templates/autosummary/method.rst +++ /dev/null @@ -1,7 +0,0 @@ -:html_theme.sidebar_secondary.remove: - -{{ objname | escape | underline}} - -.. currentmodule:: {{ module }} - -.. auto{{ objtype }}:: {{ objname }} \ No newline at end of file diff --git a/python/docs/source/blog/index.md b/python/docs/source/blog/index.md deleted file mode 100644 index 44144083b..000000000 --- a/python/docs/source/blog/index.md +++ /dev/null @@ -1,9 +0,0 @@ -# Blog - -```{eval-rst} -.. postlist:: - :list-style: circle - :format: {date} - {title} - :excerpts: - :expand: Read more ... -``` diff --git a/python/docs/source/blog/posts/2023-03-28-announcing-kaskada-oss.md b/python/docs/source/blog/posts/2023-03-28-announcing-kaskada-oss.md deleted file mode 100644 index 84095abdd..000000000 --- a/python/docs/source/blog/posts/2023-03-28-announcing-kaskada-oss.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -blogpost: true -author: ben -date: 2023-Mar-28 -tags: releases -excerpt: 1 -description: From Startup to Open Source Project ---- - -# Announcing Kaskada OSS - -Today, we’re announcing the open-source release of Kaskada – a modern, open-source event processing engine. - -# How it began: Simplifying ML - -Kaskada technology has evolved a lot since we began developing it three years ago. Initially, we were laser focused on the machine learning (ML) space. We saw many companies working on different approaches to the same ML problems -- managing computed feature values (what is now called a feature store), applying existing algorithms to train a model from those values, and serving that model by applying it to computed feature values. We saw a different problem. - -With our background in the data processing space we identified a critical gap -- no one was looking at the process of going from raw, event-based, data to computed feature values. This meant that users had to choose – use SQL and treat the events as a table, losing important information in the process, or use lower-level data pipeline APIs and worry about all the details. Our experience working on data processing systems at Google and as part of Apache Beam led us to create a compute engine designed for the needs of feature engineering — we called it a feature engine. - -We are extremely proud of where Kaskada technology is today. Unlike a feature store, it focuses on computing the features a user described using a simple, declarative language. Unlike existing data processing systems, it delivers on the needs of machine learning – expressing sophisticated, temporal features without leakage, working with raw events without pre-processing, and scalability that just worked for training and serving. - -The unique characteristics of Kaskada make it ideal for the time-based event processing required for accurate, real-time machine learning. While we see that ML will always be a great use case for Kaskada, we’ve realized it can be used for so much more. - -# Modern, Open-Source Event Processing - -When [DataStax acquired Kaskada](https://www.datastax.com/press-release/datastax-acquires-machine-learning-company-kaskada-to-unlock-real-time-ai) a few months ago, we began the process of open-sourcing the core Kaskada technology. In the conversations that followed, we realized that the capabilities of Kaskada that make it ideal for real-time ML – easy to use, high-performance columnar computations over event-based data – also make it great for general event processing. These features include: - -1. **Rich, Temporal Operations**: The ability to easily express computations over time beyond windowed aggregations. For instance, when computing training data it was often necessary to compute values at a point in time in the past and combine those with a label value computed at a later point in time. This led to a powerful set of operations for working with time. -2. **Events all the way down**: The ability to run a query both to get all results over time and just the final results. This means that Kaskada operates directly on the events – turning a sequence of events into a sequence of changes, which may be observed directly or materialized to a table. By treating everything as events, the temporal operations are always available and you never need to think about the difference between streams and tables, nor do you need to use different APIs for each. -3. **Modern and easy to use**: Kaskada is built in Rust and uses Apache Arrow for high-performance, columnar computations. It consists of a single binary which makes for easy local and cloud deployments. - - -This led to the decision to open source Kaskada as a modern, open-source event-processing language and native engine. Machine learning is still a great use case of Kaskada, but we didn’t want the feature engine label to constrain community creativity and innovation. It’s all available today in the [GitHub repository](https://github.com/kaskada-ai/kaskada) under the Apache 2.0 License. - -# Why use Kaskada? - -Kaskada is for you if… - -1. **You want to compute the results of your query over time.** -Operating over time all the way down means that Kaskada makes it easy to compute the result of any query over time. - -2. **You want to express temporal computations without writing pages of SQL.** -Kaskada provides a declarative language for event-processing. Because of the focus on temporal computations and composability, it is much easier and shorter than comparable SQL queries. - -3. **You want to process events today without setting up other tools.** -The columnar event-processing engine within Kaskada scales to X million events/second running on a single machine. This lets you get started and iterate quickly without becoming an expert in cluster management or big-data tools. - - -# What’s coming next? - -Our first goal was getting the project released. Now that it is, we are excited to see where the project goes! - -Some improvements on our mind are shown below. We look forward to hearing your thoughts on what would help you process events. - -1. **Increase extensibility and participate in the larger open-source community.** - - Introduce extension points for I/O connectors and contribute connectors for a larger set of supported formats. - - Expose a logical execution plan after the language constructs have been compiled away, so that other executors may be developed using the same parsing and type-checking rules. - - Introduce extension points for custom schema catalogs, allowing Kaskada queries to be compiled against existing data catalogs. - -2. **Align query capabilities with more general, event-processing use cases.** - - Ability to create composite events from patterns of existing events and subsequently process those composite events (“CEP”). - - Improvements to the declarative language to reduce surprises, make it more familiar to new users, and make it even easier to express temporal computations over events. - -3. **Continue to improve local performance and usability.** - - Make it possible to use the engine more easily in a variety of ways – via a command line REPL, via an API, etc. - - Improve performance and latency of real-time and partitioned execution within the native engine. - -# How can I contribute? - -Give it a try – [download one of the releases](https://github.com/kaskada-ai/kaskada/releases) and run some computations on your event data. Let us know how it works for you, and what you’d like to see improved! - -We’d love to hear what you think - please comment or ask on our [Kaskada GitHub discussions page](https://github.com/kaskada-ai/kaskada/discussions). - -Help spread the word – Star and Follow the project on GitHub! - -Please file issues, start discussions or join us on GitHub to chat about the project or event-processing in general. \ No newline at end of file diff --git a/python/docs/source/blog/posts/2023-08-25-new-kaskada.md b/python/docs/source/blog/posts/2023-08-25-new-kaskada.md deleted file mode 100644 index 9025e85c4..000000000 --- a/python/docs/source/blog/posts/2023-08-25-new-kaskada.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -blogpost: true -date: 2023-Aug-25 -author: ryan -tags: releases -excerpt: 2 -description: Embedded in Python for accessible Real-Time AI ---- - -# Introducing the New Kaskada - -We started Kaskada with the goal of simplifying the real-time AI/ML lifecycle, and in the past year AI has exploded in usefulness and accessibility. Generative models and Large Language Models (LLMs) have revolutionized how we approach AI. Their accessibility and incredible capabilities have made AI more valuable than it has ever been and democratized the practice of AI. - -Still, a challenge remains: building and managing real-time AI applications. - -## The Challenge of using Real-Time Data in AI Applications - -Real-time data for AI Applications has always been surrounded by an array of challenges. For example: - -1. **Infrastructure Hurdles**: Accessing real-time data often means struggling to acquire data and deploying complex infrastructure, requiring significant time and expertise to get right. - -2. **Cumbersome Tools**: Traditional tools for streaming data are bulky, with steep learning curves and complex JVM-based setups. - -3. **Analysis Disconnect**: AI models thrive on historical data, but the tools designed for bulk historical analysis are often worlds apart from those made for real-time or streaming data processing. - -4. **Challenges of Time-Travel**: AI applications frequently require a unique kind of historical analysis – one that can time-travel through your data. Expressing such analyses is challenging with conventional analytic tools that weren’t designed with time in mind. - -These challenges have made it difficult for all but the largest companies with the deepest development budgets to deliver on the promise of real-time AI, and these are the challenges we built Kaskada to solve. - -## Welcome to the New Kaskada - -We originally built Kaskada as a managed service. Earlier this year, we [released Kaskada as an open-source, self-managed service](./2023-03-28-announcing-kaskada-oss.md), simplifying data onboarding and allowing Kaskada to be deployed anywhere. - -Today, we take the next step in improving Kaskada’s usability by providing its core compute engine as an embedded Python library. Because Kaskada is written in Rust, we’re able to leverage the excellent [PyO3](https://pyo3.rs/) project to compile Python-native bindings for our compute engine and support Python-defined UDF’s. Additionally, Kaskada is built using [Apache Arrow](https://arrow.apache.org/), which allows zero-copy data transfers between Kaskada and other Python libraries such as [Pandas](https://pandas.pydata.org/), allowing you to operate on your data in-place. - -We’re also changing how you query Kaskada by implementing our query DSL as Python functions. This change makes it easier to get started by eliminating the learning curve of a new language and improving integration with code editors, syntax highlighters, and AI coding assistants. - -The result is an easy-to-use Python-native library with all the efficiency and performance of our low-level Rust implementation, fully integrated with the rich Python ecosystem of AI/ML tools, visualization libraries etc. - -## Features for Real-Time AI Applications - -Real-Time AI is easier today than it's ever been: - -* Foundation models built by OpenAI, Facebook and others can be used as a starting point, allowing sophisticated applications to be built with a fraction of the data that would otherwise be necessary. -* Services such as OpenAI eliminate the need to manage complex infrastructure. -* Platforms like HuggingFace have made it easier than ever to share and collaborate on open LLMs. - -The New Kaskada complements these resources, making it easier than ever to utilize real-time data by providing several key components: - -### 1. Real-time Aggregation - -In a world where data is continuously flowing, being able to efficiently precompute model inputs is invaluable. With Kaskada's real-time aggregation, you can effortlessly: - -- Connect with multiple data streams using our robust data connectors. -- Transform data on-the-go, ensuring that the model receives the most relevant inputs. -- Perform complex aggregations to derive meaningful insights from streams of data, making sure your AI models always have the most pertinent information. -- Pause and resume aggregations in the event of process termination. - -The result? Faster decision-making, timely insights, and AI models that are always a step ahead. - -### 2. Event Detection - -Real-time event detection can mean the difference between catching an anomaly and letting it slip through the cracks. The New Kaskada’s event detection system is designed to: - -- Expressively describe complex cross-event and cross-entity conditions to use as triggers. -- Identify important activities and patterns as they occur, ensuring nothing goes unnoticed. -- Trigger proactive AI behaviors, allowing for immediate actions or notifications based on the detected events. - -From spotting fraudulent activities to identifying high-priority user behaviors, Kaskada ensures that important activities are always on your radar. - -### 3. History Replay - -Past data holds the keys to effective future decisions. With Kaskada's history replay, you can: - -- Backtest AI models by revisiting historical data points. -- Fine-tune models using per-example time travel, ensuring your models are always optimized based on past and present data. -- Use point-in-time joins to seamlessly merge data from different data sources at a single point in history, unlocking deeper insights and more accurate predictions. - -Kaskada ties together the modern real-time AI stack, providing a data foundation for developing and operating AI applications. - -## Join the Community - -We believe in the transformative power of real-time AI and the possibilities it holds. We believe that real-time data will allow AI to go beyond question-answering to provide proactive, intelligent applications. We want to hear what excites you about real-time and generative AI - [Join our Slack community](https://kaskada.io/community/) and share your use cases, insights and experiences with the New Kaskada. - -*"Real-Time AI without the fuss."* Embrace the future with Kaskada. \ No newline at end of file diff --git a/python/docs/source/community/index.md b/python/docs/source/community/index.md deleted file mode 100644 index 37e6f3100..000000000 --- a/python/docs/source/community/index.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -html_theme.sidebar_secondary.remove: true ---- - -# Community - -Welcome to the Kaskada community! - -The Kaskada project was open-sourced in 2023. As a growing community, we're here to explore new ways to interact with event-based data at scale and have some fun along the way. We build in the open and use the channels below for communication. - -```{gallery-grid} -:grid-columns: 1 2 2 3 - -- header: "{fab}`github;pst-color-primary` GitHub Discussions" - content: "Ask questions and discuss Kaskada on GitHub." - link: https://github.com/kaskada-ai/kaskada/discussions -- header: "{fab}`slack;pst-color-primary` Join Slack" - content: "Join us on Slack to chat about Proactive AI!" - link: https://join.slack.com/t/kaskada-hq/shared_invite/zt-1t1lms085-bqs2jtGO2TYr9kuuam~c9w -- header: "{fas}`video;pst-color-primary` Meet with Us" - content: "Schedule time to meet with Kaskada developers and discuss your needs and ideas!" - link: https://calendly.com/kaskada-io/office-hours -``` - -## Contributing - -Nothing makes us happier than community contributions. See the README in the main Kaskada repository to get a grasp of the project layout and reference the [`CONTRIBUTING.md`](https://github.com/kaskada-ai/kaskada/blob/main/CONTRIBUTING.md){target="_blank" rel="noopener noreferrer"} file for detailed steps. - -Use the [GitHub issue tracker](https://github.com/kaskada-ai/kaskada/issues) to file bugs and feature requests. - -Acceptance of the DataStax [contributor license agreement (CLA)](https://cla.datastax.com/) is required in order for us to be able to accept your code contribution. You will see this on the standard pull request checklist for the Kaskada repositories. - -If you're interested in contributing but don't know where to start, we also recommend looking for a good first issue in the main repository. - -## Code of Conduct - -To make Kaskada a welcoming and harassment-free experience for everyone, we adopt and follow the [Contributor Covenant](https://www.contributor-covenant.org/). -Please read our [Code of Conduct](https://github.com/kaskada-ai/kaskada/blob/main/CODE_OF_CONDUCT.md) before engaging with the community. \ No newline at end of file diff --git a/python/docs/source/conf.py b/python/docs/source/conf.py deleted file mode 100644 index 052726882..000000000 --- a/python/docs/source/conf.py +++ /dev/null @@ -1,183 +0,0 @@ -"""Sphinx configuration.""" -import sys -from pathlib import Path -from typing import Any, Dict - - -sys.path.append(str(Path(".").resolve())) - -project = "kaskada" -author = "Kaskada Contributors" -copyright = "2023, Kaskada Contributors" -extensions = [ - "ablog", - "sphinx.ext.autodoc", - "sphinx.ext.autosummary", - "sphinx.ext.napoleon", - "sphinx.ext.intersphinx", - "sphinx.ext.todo", - "sphinx_design", - # "myst_parser", - "myst_nb", - "sphinx_copybutton", - "sphinx_autodoc_typehints", # must be after napoleon - "sphinx_social_cards", - "_extensions.gallery_directive", -] -autodoc_typehints = "description" -language = "en" - -html_theme = "pydata_sphinx_theme" -html_favicon = "_static/favicon.png" -html_title = "Kaskada" -html_js_files = [ - "https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js" -] - -# Configure the primary (left) sidebar. -# https://pydata-sphinx-theme.readthedocs.io/en/stable/user_guide/layout.html#primary-sidebar-left -html_sidebars = { - # No primary (left) sidebar on the landing page. - "index.md": [], - # Blog sidebars - # https://ablog.readthedocs.io/manual/ablog-configuration-options/#blog-sidebars - "blog/**": [ - # Information about the post. - "ablog/postcard.html", - # 5 most recent posts - "ablog/recentposts.html", - # Tag cloud and links. - "ablog/tagcloud.html", - # Categories -- we just use tags for now. - # "ablog/categories.html", - # Show all authors on the sidebar. - # "ablog/authors.html", - # Show all languages on the sidebar. - # "ablog/languages.html", - # Show all locations on the sidebar. - # "ablog/locations.html", - "ablog/archives.html", - ], - "[!blog]*/*": ["sidebar-nav-bs"], -} - -html_theme_options: Dict[str, Any] = { - # Setup external links. - # https://pydata-sphinx-theme.readthedocs.io/en/stable/user_guide/header-links.html - "icon_links": [ - { - "name": "GitHub", - "url": "https://github.com/kaskada-ai/kaskada", # required - "icon": "fa-brands fa-square-github", - "type": "fontawesome", - }, - { - "name": "Slack", - "url": "https://join.slack.com/t/kaskada-hq/shared_invite/zt-1t1lms085-bqs2jtGO2TYr9kuuam~c9w", - "icon": "fa-brands fa-slack", - }, - ], - # Setup edit buttons - # See https://pydata-sphinx-theme.readthedocs.io/en/stable/user_guide/source-buttons.html - "use_edit_page_button": True, - # Include indices. - # https://pydata-sphinx-theme.readthedocs.io/en/stable/user_guide/indices.html - "primary_sidebar_end": ["indices.html"], - # Provide an announcement at the top. - # https://pydata-sphinx-theme.readthedocs.io/en/stable/user_guide/announcements.html# - "announcement": ( - "This describes the next version of Kaskada. " - "It is currently available as an alpha release." - ), - # Branding / logos. - # https://pydata-sphinx-theme.readthedocs.io/en/stable/user_guide/branding.html - "logo": { - "image_light": "_static/kaskada-positive.svg", - "image_dark": "_static/kaskada-negative.svg", - }, - # Setup analytics. - # https://pydata-sphinx-theme.readthedocs.io/en/stable/user_guide/analytics.html - "analytics": { - "google_analytics_id": "G-HR9E2E6TG4", - }, - # TODO: Version switcher. - # This would require hosting multiple versions of the docs. - # https://pydata-sphinx-theme.readthedocs.io/en/stable/user_guide/version-dropdown.html -} - -templates_path = ["_templates"] -html_static_path = ["_static"] - -html_context = { - "github_user": "kaskada-ai", - "github_repo": "kaskada", - "github_version": "main", - "doc_path": "python/docs/source", -} - -# Setup links to other sphinx projects. -intersphinx_mapping: Dict[str, Any] = { - "python": ("http://docs.python.org/3", None), - "pandas": ("http://pandas.pydata.org/docs", None), - "pyarrow": ("https://arrow.apache.org/docs", None), -} - -# adds useful copy functionality to all the examples; also -# strips the '>>>' and '...' prompt/continuation prefixes. -copybutton_prompt_text = r">>> |\.\.\. " -copybutton_prompt_is_regexp = True - -# Options for Todos -todo_include_todos = True - -# Options for Myst (markdown) -# https://myst-parser.readthedocs.io/en/v0.17.1/syntax/optional.html -myst_enable_extensions = [ - "colon_fence", - "deflist", - "smartquotes", - "replacements", - "linkify", -] -myst_heading_anchors = 3 - -# -- Options for autodoc ---------------------------------------------------- -# https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#configuration - -# Automatically extract typehints when specified and place them in -# descriptions of the relevant function/method. -autodoc_typehints = "description" -autodoc_type_aliases = {"kaskada.Arg": "kaskada.Arg"} - -# Don't show class signature with the class' name. -autodoc_class_signature = "separated" - -autosummary_generate = True - -napoleon_preprocess_types = True -napoleon_attr_annotations = True -napoleon_use_rtype = False -typehints_use_rtype = False -typehints_document_rtype = False -typehints_defaults = "comma" - -suppress_warnings = ["mystnb.unknown_mime_type"] - -blog_path = "blog" -blog_authors = { - "ben": ("Ben Chambers", "https://github.com/bjchambers"), - "ryan": ("Ryan Michael", "https://github.com/kerinin"), -} -post_date_format = "%Y-%b-%d" -post_date_format_short = "%Y-%b-%d" -post_show_prev_next = False - -# Generate social cards for blog posts -social_cards = { - "site_url": "https://kaskada.io/kaskada", - "description": "Kaskada: Real-Time AI without the fuss.", - "cards_layout_dir": ["_layouts"], - "cards_layout_options": { - "background_color": "#26364a", - }, -} diff --git a/python/docs/source/examples/bluesky.md b/python/docs/source/examples/bluesky.md deleted file mode 100644 index 53b3936ee..000000000 --- a/python/docs/source/examples/bluesky.md +++ /dev/null @@ -1,73 +0,0 @@ -# Bluesky Firehose Example - -Bluesky is a "distributed social network" that aims to improve on some of the perceived shortcomings of X (nee Twitter). -Bluesky uses a distributed protocol name the [AT Protocol](https://atproto.com/) to exchange messages between users, and provides a "firehose" delivering every message sent over the protocol in real-time. - -In this example, we'll show how you can receive and process the firehose using Kaskada. - -You can see the full example in the file [bluesky.py](https://github.com/kaskada-ai/kaskada/blob/main/python/docs/source/examples/bluesky.py). - -## Setup the event data source - -Before we can receive events from Bluesky, we need to create a data source to tell Kaskada how to handle the events. -We'll provide a schema and configure the time and entity fields. - -```{literalinclude} bluesky.py -:language: python -:start-after: "[start_setup]" -:end-before: "[end_setup]" -:linenos: -:lineno-match: -:dedent: 4 -``` - -## Define the incoming event handler - -The `atproto` python library takes care of requesting and receiving events from Bluesky, all you need to do is create a handler to configure what to do with each event. -This handler parses the message to find [Commit](https://atproto.com/specs/repository#commit-objects) events. -For each Commit, we'll parse out any [Post](https://atproto.com/blog/create-post#post-record-structure) messages. -Finally we do some schema munging to get the Post into the event format we described when creating the data source. - -```{literalinclude} bluesky.py -:language: python -:start-after: "[start_incoming]" -:end-before: "[end_incoming]" -:linenos: -:lineno-match: -:dedent: 4 -``` - -## Construct a real-time query and result handler - -Now we can use Kaskada to transform the events as they arrive. -First we'll use `with_key` to regroup events by language, then we'll apply a simple `count` aggregation. -Finally, we create a handler for the transformed results - here just printing them out. - - -```{literalinclude} bluesky.py -:language: python -:start-after: "[start_result]" -:end-before: "[end_result]" -:linenos: -:lineno-match: -:dedent: 4 -``` - -## Final touches - -Now we just need to kick it all off by calling `asyncio.gather` on the two handler coroutines. This kicks off all the async processing. - -```{literalinclude} bluesky.py -:start-after: "[start_run]" -:end-before: "[end_run]" -:language: python -:linenos: -:lineno-match: -:dedent: 4 -``` - -Try running it yourself and playing different transformations! - -```bash -python bluesky.py -``` diff --git a/python/docs/source/examples/bluesky.py b/python/docs/source/examples/bluesky.py deleted file mode 100644 index c260fc960..000000000 --- a/python/docs/source/examples/bluesky.py +++ /dev/null @@ -1,184 +0,0 @@ -#!/usr/bin/env python -# -# Bluesky Kaskada Consumer -# -# This script demonstrates the use of Kaskada to consume and compute over -# the BlueSky firehose. - -import asyncio -import time - -import kaskada as kd -import pyarrow as pa -from atproto import CAR, AtUri, models -from atproto.firehose import ( - AsyncFirehoseSubscribeReposClient, - parse_subscribe_repos_message, -) -from atproto.xrpc_client.models import get_or_create, ids, is_record_type - - -async def main(): - # Initialize the Kaskada session so we can use it for stream processing - kd.init_session() - - # Create the BlueSky (At protocol) client. - # The firehose doesn't (currently) require authentication. - at_client = AsyncFirehoseSubscribeReposClient() - - # [start_setup] - # Setup the data source. - # This defintes (most of) the schema of the events we'll receive, - # and tells Kaskada which fields to use for time and initial entity. - # - # We'll push events into this source as they arrive in real-time. - posts = kd.sources.PyDict( - rows=[], - schema=pa.schema( - [ - pa.field( - "record", - pa.struct( - [ - pa.field("created_at", pa.string()), - pa.field("text", pa.string()), - # pa.field("embed", pa.struct([...])), - pa.field("entities", pa.string()), - # pa.field("facets", pa.list_(...)), - pa.field("labels", pa.float64()), - pa.field("langs", pa.list_(pa.string())), - # pa.field("reply", pa.struct([...])), - pa.field("py_type", pa.string()), - ] - ), - ), - pa.field("uri", pa.string()), - pa.field("cid", pa.string()), - pa.field("author", pa.string()), - pa.field("ts", pa.float64()), - ] - ), - time_column="ts", - key_column="author", - time_unit="s", - ) - # [end_setup] - - # [start_incoming] - # Handler for newly-arrived messages from BlueSky. - async def receive_at(message) -> None: - # Extract the contents of the message and bail if it's not a "commit" - commit = parse_subscribe_repos_message(message) - if not isinstance(commit, models.ComAtprotoSyncSubscribeRepos.Commit): - return - - # Get the operations included in the message - ops = _get_ops_by_type(commit) - for new_post in ops["posts"]["created"]: - # The atproto library's use of schemas is sort of confusing - # This isn't always the expected type and I'm not sure why... - if not isinstance(new_post["record"], models.app.bsky.feed.post.Main): - continue - - # The parsing produces a hot mess of incompatible types, so we build - # a dict from scratch to simplify. - posts.add_rows( - { - "record": dict(new_post["record"]), - "uri": new_post["uri"], - "cid": new_post["cid"], - "author": new_post["author"], - "ts": time.time(), - } - ) - - # [end_incoming] - - # [start_result] - # Handler for values emitted by Kaskada. - async def receive_outputs(): - # We'll perform a very simple aggregation - key by language and count. - posts_by_first_lang = posts.with_key(posts.col("record").col("langs").index(0)) - - # Consume outputs as they're generated and print to STDOUT. - async for row in posts_by_first_lang.count().run_iter(kind="row", mode="live"): - print(f"{row['_key']} has posted {row['result']} times since startup") - - # [end_result] - - # [start_run] - # Kickoff the two async processes concurrently. - await asyncio.gather(at_client.start(receive_at), receive_outputs()) - # [end_run] - - -# Copied from https://raw.githubusercontent.com/MarshalX/atproto/main/examples/firehose/process_commits.py -def _get_ops_by_type( # noqa: C901, E302 - commit: models.ComAtprotoSyncSubscribeRepos.Commit, -) -> dict: # noqa: C901, E302 - operation_by_type = { - "posts": {"created": [], "deleted": []}, - "reposts": {"created": [], "deleted": []}, - "likes": {"created": [], "deleted": []}, - "follows": {"created": [], "deleted": []}, - } - - car = CAR.from_bytes(commit.blocks) - for op in commit.ops: - uri = AtUri.from_str(f"at://{commit.repo}/{op.path}") - - if op.action == "update": - # not supported yet - continue - - if op.action == "create": - if not op.cid: - continue - - create_info = {"uri": str(uri), "cid": str(op.cid), "author": commit.repo} - - record_raw_data = car.blocks.get(op.cid) - if not record_raw_data: - continue - - record = get_or_create(record_raw_data, strict=False) - if uri.collection == ids.AppBskyFeedLike and is_record_type( - record, ids.AppBskyFeedLike - ): - operation_by_type["likes"]["created"].append( - {"record": record, **create_info} - ) - elif uri.collection == ids.AppBskyFeedPost and is_record_type( - record, ids.AppBskyFeedPost - ): - operation_by_type["posts"]["created"].append( - {"record": record, **create_info} - ) - elif uri.collection == ids.AppBskyFeedRepost and is_record_type( - record, ids.AppBskyFeedRepost - ): - operation_by_type["reposts"]["created"].append( - {"record": record, **create_info} - ) - elif uri.collection == ids.AppBskyGraphFollow and is_record_type( - record, ids.AppBskyGraphFollow - ): - operation_by_type["follows"]["created"].append( - {"record": record, **create_info} - ) - - if op.action == "delete": - if uri.collection == ids.AppBskyFeedLike: - operation_by_type["likes"]["deleted"].append({"uri": str(uri)}) - elif uri.collection == ids.AppBskyFeedPost: - operation_by_type["posts"]["deleted"].append({"uri": str(uri)}) - elif uri.collection == ids.AppBskyFeedRepost: - operation_by_type["reposts"]["deleted"].append({"uri": str(uri)}) - elif uri.collection == ids.AppBskyGraphFollow: - operation_by_type["follows"]["deleted"].append({"uri": str(uri)}) - - return operation_by_type - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/python/docs/source/examples/index.md b/python/docs/source/examples/index.md deleted file mode 100644 index 3c8fa7cbe..000000000 --- a/python/docs/source/examples/index.md +++ /dev/null @@ -1,17 +0,0 @@ -# Examples - -The [Time-Centric Calculations example](./time_centric.ipynb) shows how to work with time and produce past training examples and recent results for applying models. - -The [Reddit example](./reddit.md) shows how to read and aggregate live messages from Reddit. - -The [Bluesky Firehose example](./bluesky.md) shows how to read and aggregate messages from the Bluesky firehose. -This demonstrates how to use Kaskada to connect in real-time and parse messages as part of the query. - -```{toctree} -:hidden: -:maxdepth: 2 - -time_centric -reddit -bluesky -``` \ No newline at end of file diff --git a/python/docs/source/examples/reddit.md b/python/docs/source/examples/reddit.md deleted file mode 100644 index 9e7516f38..000000000 --- a/python/docs/source/examples/reddit.md +++ /dev/null @@ -1,73 +0,0 @@ -# Reddit Live Example - -In this example, we'll show how you can receive and process Reddit comments using Kaskada. - -You can see the full example in the file [reddit.py](https://github.com/kaskada-ai/kaskada/blob/main/python/docs/source/examples/reddit.py). - -## Setup Reddit credentials - -Follow Reddit's [First Steps](https://github.com/reddit-archive/reddit/wiki/OAuth2-Quick-Start-Example#first-steps) guide to create an App and obtain a client ID and secret. -The "script" type application is sufficient for this example. - -## Setup the event data source - -Before we can receive events from Reddit, we need to create a data source to tell Kaskada how to handle the events. -We'll provide a schema and configure the time and entity fields. - -```{literalinclude} reddit.py -:language: python -:start-after: "[start_setup]" -:end-before: "[end_setup]" -:linenos: -:lineno-match: -:dedent: 4 -``` - -## Define the incoming event handler - -The `asyncpraw` python library takes care of requesting and receiving events from Reddit, all you need to do is create a handler to configure what to do with each event. -This handler converts [Comment](https://praw.readthedocs.io/en/stable/code_overview/models/comment.html#praw.models.Comment) messages into a dict, and passes the dict to Kaskada. - -```{literalinclude} reddit.py -:language: python -:start-after: "[start_incoming]" -:end-before: "[end_incoming]" -:linenos: -:lineno-match: -:dedent: 4 -``` - -## Construct a real-time query and result handler - -Now we can use Kaskada to transform the events as they arrive. -First we'll use `with_key` to regroup events by author, then we'll apply a simple `count` aggregation. -Finally, we create a handler for the transformed results - here just printing them out. - - -```{literalinclude} reddit.py -:language: python -:start-after: "[start_result]" -:end-before: "[end_result]" -:linenos: -:lineno-match: -:dedent: 4 -``` - -## Final touches - -Now we just need to kick it all off by calling `asyncio.gather` on the two handler coroutines. This kicks off all the async processing. - -```{literalinclude} reddit.py -:start-after: "[start_run]" -:end-before: "[end_run]" -:language: python -:linenos: -:lineno-match: -:dedent: 4 -``` - -Try running it yourself and playing different transformations! - -```bash -python reddit.py -``` diff --git a/python/docs/source/examples/reddit.py b/python/docs/source/examples/reddit.py deleted file mode 100644 index 62a0d372f..000000000 --- a/python/docs/source/examples/reddit.py +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env python -# -# Reddit Kaskada Consumer -# -# This script demonstrates the use of Kaskada to consume and compute over -# Reddit updates. - -import asyncio -import os -import time - -import asyncpraw -import kaskada as kd -import pyarrow as pa - - -async def main(): - # Initialize the Kaskada session so we can use it for stream processing - kd.init_session() - - # Create the Reddit client. - reddit = asyncpraw.Reddit( - client_id=os.getenv("REDDIT_CLIENT_ID"), - client_secret=os.getenv("REDDIT_CLIENT_SECRET"), - user_agent=os.getenv("REDDIT_USER_AGENT", "kaskada-demo"), - ) - - # [start_setup] - # Setup the data source. - # This defintes (most of) the schema of the events we'll receive, - # and tells Kaskada which fields to use for time and initial entity. - # - # We'll push events into this source as they arrive in real-time. - comments = kd.sources.PyDict( - schema=pa.schema( - [ - pa.field("author", pa.string()), - pa.field("body", pa.string()), - pa.field("permalink", pa.string()), - pa.field("submission_id", pa.string()), - pa.field("subreddit", pa.string()), - pa.field("ts", pa.float64()), - ] - ), - time_column="ts", - key_column="submission_id", - time_unit="s", - ) - # [end_setup] - - # [start_incoming] - # Handler to receive new comments as they're created - async def receive_comments(): - # Creat the subreddit handle - sr = await reddit.subreddit(os.getenv("SUBREDDIT", "all")) - - # Consume the stream of new comments - async for comment in sr.stream.comments(): - # Add each comment to the Kaskada data source - await comments.add_rows( - { - "author": comment.author.name, - "body": comment.body, - "permalink": comment.permalink, - "submission_id": comment.submission.id, - "subreddit_id": comment.subreddit.display_name, - "ts": time.time(), - } - ) - - # [end_incoming] - - # [start_result] - # Handler for values emitted by Kaskada. - async def receive_outputs(): - # We'll perform a very simple aggregation - key by author and count. - comments_by_author = comments.with_key(comments.col("author")) - - # Consume outputs as they're generated and print to STDOUT. - async for row in comments_by_author.count().run_iter(kind="row", mode="live"): - print(f"{row['_key']} has posted {row['result']} times since startup") - - # [end_result] - - # [start_run] - # Kickoff the two async processes concurrently. - await asyncio.gather(receive_comments(), receive_outputs()) - # [end_run] - - -if __name__ == "__main__": - asyncio.run(main()) diff --git a/python/docs/source/examples/time_centric.ipynb b/python/docs/source/examples/time_centric.ipynb deleted file mode 100644 index 904e2203d..000000000 --- a/python/docs/source/examples/time_centric.ipynb +++ /dev/null @@ -1,344 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "id": "5a20a51f", - "metadata": { - "id": "5a20a51f" - }, - "source": [ - "# Time-centric Calculations\n", - "\n", - "Kaskada was built to process and perform temporal calculations on event streams,\n", - "with real-time analytics and machine learning in mind. It is not exclusively for\n", - "real-time applications, but Kaskada excels at time-centric computations and\n", - "aggregations on event-based data.\n", - "\n", - "For example, let's say you're building a user analytics dashboard at an\n", - "ecommerce retailer. You have event streams showing all actions the user has\n", - "taken, and you'd like to include in the dashboard:\n", - "* the total number of events the user has ever generated\n", - "* the total number of purchases the user has made\n", - "* the total revenue from the user\n", - "* the number of purchases made by the user today\n", - "* the total revenue from the user today\n", - "* the number of events the user has generated in the past hour\n", - "\n", - "Because the calculations needed here are a mix of hourly, daily, and over all of\n", - "history, more than one type of event aggregation needs to happen. Table-centric\n", - "tools like those based on SQL would require multiple JOINs and window functions,\n", - "which would be spread over multiple queries or CTEs. \n", - "\n", - "Kaskada was designed for these types of time-centric calculations, so we can do\n", - "each of the calculations in the list in one line:\n", - "\n", - "```python\n", - "record({\n", - " \"event_count_total\": DemoEvents.count(),\n", - " \"purchases_total_count\": DemoEvents.filter(DemoEvents.col(\"event_name\").eq(\"purchase\")).count(),\n", - " \"revenue_total\": DemoEvents.col(\"revenue\").sum(),\n", - " \"purchases_daily\": DemoEvents.filter(DemoEvents.col(\"event_name\").eq(\"purchase\")).count(window=Daily()),\n", - " \"revenue_daily\": DemoEvents.col(\"revenue\").sum(window=Daily()),\n", - " \"event_count_hourly\": DemoEvents.count(window=Hourly()),\n", - "})\n", - "```\n", - "\n", - "```{warning}\n", - "The previous example demonstrates the use of `Daily()` and `Hourly()` windowing which aren't yet part of the new Python library.\n", - "```\n", - "\n", - "Of course, a few more lines of code are needed to put these calculations to work,\n", - "but these six lines are all that is needed to specify the calculations\n", - "themselves. Each line may specify:\n", - "* the name of a calculation (e.g. `event_count_total`)\n", - "* the input data to start with (e.g. `DemoEvents`)\n", - "* selecting event fields (e.g. `DemoEvents.col(\"revenue\")`)\n", - "* function calls (e.g. `count()`)\n", - "* event filtering (e.g. `filter(DemoEvents.col(\"event_name\").eq(\"purchase\"))`)\n", - "* time windows to calculate over (e.g. `window=Daily()`)\n", - "\n", - "...with consecutive steps chained together in a familiar way.\n", - "\n", - "Because Kaskada was built for time-centric calculations on event-based data, a\n", - "calculation we might describe as \"total number of purchase events for the user\"\n", - "can be defined in Kaskada in roughly the same number of terms as the verbal\n", - "description itself.\n", - "\n", - "Continue through the demo below to find out how it works.\n", - "\n", - "See [the Kaskada documentation](../guide/index) for lots more information." - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "BJ2EE9mSGtGB", - "metadata": { - "id": "BJ2EE9mSGtGB" - }, - "source": [ - "## Kaskada Client Setup\n", - "\n", - "```\n", - "%pip install kaskada>=0.6.0-a.0\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "37db47ba", - "metadata": { - "tags": [ - "hide-output" - ] - }, - "outputs": [], - "source": [ - "import kaskada as kd\n", - "\n", - "kd.init_session()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "5b838eef", - "metadata": {}, - "source": [ - "## Example dataset\n", - "\n", - "For this demo, we'll use a very small example data set, which, for simplicity and portability of this demo notebook, we'll read from a string.\n", - "\n", - "```{note}\n", - "For simplicity, instead of a CSV file or other file format we read and then parse data from a CSV string.\n", - "You can load your own event data from many common sources, including Pandas DataFrames and Parquet files.\n", - "See {py:mod}`kaskada.sources` for more information on the available sources.\n", - "```" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ba4bb6b6", - "metadata": {}, - "outputs": [], - "source": [ - "import asyncio\n", - "\n", - "# For demo simplicity, instead of a CSV file, we read and then parse data from a\n", - "# CSV string. Kaskadaa\n", - "event_data_string = \"\"\"\n", - " event_id,event_at,entity_id,event_name,revenue\n", - " ev_00001,2022-01-01 22:01:00,user_001,login,0\n", - " ev_00002,2022-01-01 22:05:00,user_001,view_item,0\n", - " ev_00003,2022-01-01 22:20:00,user_001,view_item,0\n", - " ev_00004,2022-01-01 23:10:00,user_001,view_item,0\n", - " ev_00005,2022-01-01 23:20:00,user_001,view_item,0\n", - " ev_00006,2022-01-01 23:40:00,user_001,purchase,12.50\n", - " ev_00007,2022-01-01 23:45:00,user_001,view_item,0\n", - " ev_00008,2022-01-01 23:59:00,user_001,view_item,0\n", - " ev_00009,2022-01-02 05:30:00,user_001,login,0\n", - " ev_00010,2022-01-02 05:35:00,user_001,view_item,0\n", - " ev_00011,2022-01-02 05:45:00,user_001,view_item,0\n", - " ev_00012,2022-01-02 06:10:00,user_001,view_item,0\n", - " ev_00013,2022-01-02 06:15:00,user_001,view_item,0\n", - " ev_00014,2022-01-02 06:25:00,user_001,purchase,25\n", - " ev_00015,2022-01-02 06:30:00,user_001,view_item,0\n", - " ev_00016,2022-01-02 06:31:00,user_001,purchase,5.75\n", - " ev_00017,2022-01-02 07:01:00,user_001,view_item,0\n", - " ev_00018,2022-01-01 22:17:00,user_002,view_item,0\n", - " ev_00019,2022-01-01 22:18:00,user_002,view_item,0\n", - " ev_00020,2022-01-01 22:20:00,user_002,view_item,0\n", - "\"\"\"\n", - "\n", - "events = await kd.sources.CsvString.create(\n", - " event_data_string, time_column=\"event_at\", key_column=\"entity_id\"\n", - ")\n", - "\n", - "# Inspect the event data\n", - "events.preview()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "568d1272", - "metadata": {}, - "source": [ - "## Define queries and calculations" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "c2c5a298", - "metadata": {}, - "source": [ - "Kaskada queries are defined in Python, using the `{py}Timestream` class.\n", - "Sources are Timestreams generally containing [records](../guide/data_types.md#record-types).\n", - "\n", - "Let's do a simple query for events for a specific entity ID.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bce22e47", - "metadata": {}, - "outputs": [], - "source": [ - "events.filter(events.col(\"entity_id\").eq(\"user_002\")).preview()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "6b5f2725", - "metadata": {}, - "source": [ - "\n", - "Beyond querying for events, Kaskada has a powerful syntax for defining\n", - "calculations on events, temporally across history.\n", - "\n", - "The six calculations discussed at the top of this demo notebook are below.\n", - "\n", - "(Note that some functions return `NaN` if no events for that user have occurred\n", - "within the time window.)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3ad6d596", - "metadata": {}, - "outputs": [], - "source": [ - "purchases = events.filter(events.col(\"event_name\").eq(\"purchase\"))\n", - "\n", - "features = kd.record(\n", - " {\n", - " \"event_count_total\": events.count(),\n", - " # \"event_count_hourly\": events.count(window=Hourly()),\n", - " \"purchases_total_count\": purchases.count(),\n", - " # \"purchases_today\": purchases.count(window=Since(Daily()),\n", - " # \"revenue_today\": events.col(\"revenue\").sum(window=Since(Daily())),\n", - " \"revenue_total\": events.col(\"revenue\").sum(),\n", - " }\n", - ")\n", - "features.preview()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "1c315938", - "metadata": {}, - "source": [ - "## At Any Time\n", - "\n", - "A key feature of Kaskada's time-centric design is the ability to query for\n", - "calculation values at any point in time. Traditional query languages (e.g. SQL)\n", - "can only return data that already exists---if we want to return a row of\n", - "computed/aggregated data, we have to compute the row first, then return it. As a\n", - "specific example, suppose we have SQL queries that produce daily aggregations\n", - "over event data, and now we want to have the same aggregations on an hourly\n", - "basis. In SQL, we would need to write new queries for hourly aggregations; the\n", - "queries would look very similar to the daily ones, but they would still be\n", - "different queries.\n", - "\n", - "With Kaskada, we can define the calculations once, and then specify the points\n", - "in time at which we want to know the calculation values when we query them.\n", - "\n", - "In the examples so far, we have used `preview()` to get a DataFrame containing\n", - "some of the rows from the Timestreams we've defined. By default, this produces\n", - "a _history_ containing all the times the result changed. This is useful for\n", - "using past values to create training examples.\n", - "\n", - "We can also execute the query for the values at a specific point in time." - ] - }, - { - "cell_type": "markdown", - "id": "082e174d", - "metadata": { - "tags": [ - "hide-output" - ] - }, - "source": [ - "```\n", - "features.preview(at=\"2022-01-01 22:00\")\n", - "``````" - ] - }, - { - "cell_type": "markdown", - "id": "5a44c5f7", - "metadata": {}, - "source": [ - "You can also compose a query that produces values at specific points in time.\n", - "\n", - "```\n", - "features.when(hourly())\n", - "```\n", - "\n", - "Regardless of the time cadence of the calculations themselves, the query output\n", - "can contain rows for whatever time points you specify. You can define a set of\n", - "daily calculations and then get hourly updates during the day. Or, you can\n", - "publish the definitions of some features in a Python module and different users\n", - "can query those same calculations for hourly, daily, and monthly\n", - "values---without editing the calculation definitions themselves.\n", - "\n", - "## Adding more calculations to the query\n", - "\n", - "We can add two new calculations, also in one line each, representing:\n", - "* the time of the user's first event\n", - "* the time of the user's last event\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "id": "2ba09e77-0fdf-43f4-960b-50a126262ec7", - "metadata": { - "id": "2ba09e77-0fdf-43f4-960b-50a126262ec7" - }, - "source": [ - "This is only a small sample of possible Kaskada queries and capabilities. See\n", - "everything that's possible with [Timestreams](../reference/timestream/index.md)." - ] - } - ], - "metadata": { - "colab": { - "collapsed_sections": [ - "6924ca3e-28b3-4f93-b0cf-5f8afddc11d8", - "936700a9-e042-401c-9156-7bb18652e109", - "08f5921d-36dc-41d1-a2a6-ae800b7a11de" - ], - "private_outputs": true, - "provenance": [] - }, - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.11.4" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/python/docs/source/guide/aggregation.md b/python/docs/source/guide/aggregation.md deleted file mode 100644 index 0c5bb7687..000000000 --- a/python/docs/source/guide/aggregation.md +++ /dev/null @@ -1,41 +0,0 @@ -# Aggregation - -Aggregations are _cumulative_, _grouped_, and _windowed_. - -Cumulative -: They reflect all values up to and including the current time. - -Grouped -: They reflect the values for each entity separately. - -Windowed -: They reflect the values within a specific [window](../reference/windows.md). - -While most functions operate on specific points in the Timestream, aggregation functions operate on many points. -Generally, the result of an aggregation represents the result for each key up to and including the current time. - -## Windowing -Aggregations may be configured to operate in a specific time window by providing a `window` argument. -If no window is specified, the aggregation is over all rows for the entity, up to and including the current time. -If a window is provided, the result of an aggregation is the result for that entity in the current window up to and including the current time. -Aggregations produce cumulative results up to each point in time, so the result at a given point in time may represent an incomplete window. - -```{code-block} python -:caption: Cumulative aggregation since the start of the day. -Purchases.sum(window = kd.windows.Since.daily()) -``` - -The [windows reference](../reference/windows.md) has information on the supported kinds of windows. - -## Repeated Aggregation - -Events may be aggregated multiple times. -The events themselves are a sequence of timestamped data for each entity. -The result of the first aggregation is the same — a sequence of timestamped data for each entity. -Applying an additional aggregation simply aggregates over those times. -We can compute the maximum of the average purchase amounts. - -```{code-block} python -:caption: Repeated aggregation computing the maximum of the average purchases. -Purchases.col("amount").mean().max() -``` \ No newline at end of file diff --git a/python/docs/source/guide/data_types.md b/python/docs/source/guide/data_types.md deleted file mode 100644 index 6e25456e7..000000000 --- a/python/docs/source/guide/data_types.md +++ /dev/null @@ -1,118 +0,0 @@ -# Data Types - -Kaskada operates on typed Timestreams. -Similar to how every Pandas `DataFrame` has an associated `dtype`, every Kaskada `Timestream` has an associated [PyArrow data type](https://arrow.apache.org/docs/python/api/datatypes.html) returned by {py:attr}`kaskada.Timestream.data_type`. -The set of supported types is based on the types supported by [Apache Arrow](https://arrow.apache.org/). - -Each `Timestream` contains points of the corresponding type. -We'll often say that the "type" of a `Timestream` is the type of the values it contains. - -Kaskada's type system describes several kinds of values. -Scalar types correspond to simple values, such as the string `"hello"` or the integer `57`. -They correspond to a stream containing values of the given type, or `null`. -Composite types are created from other types. -For instance, records may be created using scalar and other composite types as fields. -An expression producing a record type is a stream that produces a value of the given record type or `null`. - -## Scalar Types - -Scalar types include booleans, numbers, strings, timestamps, durations and calendar intervals. - -:::{list-table} Scalar Types -:widths: 1, 3 -:header-rows: 1 - -- * Types - * Description -- * `bool` - * Booleans represent true or false. - - Examples: `true`, `false`. -- * `u8`, `u16`, `u32`, `u64` - * Unsigned integer numbers of the specified bit width. - - Examples: `0`, `1`, `1000` -- * `i8`, `i16`, `i32`, `i64` - * Signed integer numbers of the specified bit width. - - Examples: `0`, `1`, `-100` -- * `f32`, `f64` - * Floating point numbers of the specified bit width. - - Examples: `0`, `1`, `-100`, `1000`, `0.0`, `-1.0`, `-100837.631`. -- * `str` - * Unicode strings. - - Examples: `"hello", "hi 'bob'"`. - -- * `timestamp_s`, `timestamp_ms`, `timestamp_us`, `timestamp_ns` - * Points in time relative the Unix Epoch (00:00:00 UTC on January 1, 1970). - Time unit may be seconds (s), milliseconds (ms), microseconds (us) or nanoseconds (ns). - - Examples: `1639595174 as timestamp_s` -- * `duration_s`, `duration_ms`, `duration_us`, `duration_ns` - * A duration of a fixed amount of a specific time unit. - Time unit may be seconds (s), milliseconds (ms), microseconds (us) or nanoseconds (ns). - - Examples: `-100 as duration_ms` -- * `interval_days`, `interval_months` - * A calendar interval corresponding to the given amount of the corresponding time. - The length of an interval depends on the point in time it is added to. - For instance, adding 1 `interval_month` to a timestamp will shift to the same day of the next month. - - Examples: `1 as interval_days`, `-100 as interval_months` -::: - -## Record Types - -Records allow combining 1 or more values of potentially different types into a single value. -Records are unnamed - any two records with the same set of field names and value types are considered equal. Fields within a record may have different types. -Field names must start with a letter. - -For example, `{name: string, age: u32 }` is a record type with two fields and `{name: 'Ben', age: 33 }` is corresponding value. - -NOTE: Record types may be nested. - -## Collection Types - -Kaskada also supports collections -- lists and maps. - -The type `list` describes a list of elements of type `T`. -For example, `list` is a list of 64-bit integers. - -Similarly, `map` describes a map containing keys of type `K` and values of type `V`. -For example, `map` is a map from strings to 64-bit integers. - -## Type Coercion -Kaskada implicitly coerces numeric types when different kinds of numbers are combined. -For example adding a 64-bit signed integer value to a 32-bit floating point value produces a 64-point floating point value - -Type coercion will never produce an integer overflow or reduction in numeric precision. -If needed, such conversions must be explicitly specified using `as`. - -The coercion rules can be summarized with the following rules: - -1. Unsigned integers can be widened: `u8` ⇨ `u16` ⇨ `u32` ⇨ `u64`. -2. Integers can be widened: `i8` ⇨ `i16` ⇨ `i32` ⇨ `i64`. -3. Floating point numbers can be widened: `f16` ⇨ `f32` ⇨ `f64`. -4. Unsigned integers can be promoted to the next wider integer `u8` ⇨ `i16`, `u16` ⇨ `i32`, `u32` ⇨ `i64`. -5. All numbers may be converted to `f64`. -6. Strings may be implicitly converted to timestamps by attempting to parse them as RFC3339 values. -The timestamp will be null for strings that don't successfully parse. - -One aspect of the coercion rules is that when an operation is applied to two different numeric types the result may be a third type which they may both be coerced to. -The type promotion table shows the type resulting from a binary operation involving two different numeric types. - -| | `u8` | `u16` | `u32` | `u64` | `i8` | `i16` | `i32` | `i64` | `f16` | `f32` | `f64` | -| --------- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | -| **`u8`** | `u8` | `u16` | `u32` | `u64` | `i16` | `i16` | `i32` | `i64` | `f16` | `f32` | `f64` | -| **`u16`** | `u16` | `u16` | `u32` | `u64` | `i32` | `i32` | `i32` | `i64` | `f16` | `f32` | `f64` | -| **`u32`** | `u32` | `u32` | `u32` | `u64` | `i64` | `i64` | `i64` | `i64` | `f32` | `f32` | `f64` | -| **`u64`** | `u64` | `u64` | `u64` | `u64` | `f64` | `f64` | `f64` | `f64` | `f64` | `f64` | `f64` | -| **`i8`** | `i16` | `i32` | `i64` | `f64` | `i8` | `i16` | `i32` | `i64` | `f16` | `f32` | `f64` | -| **`i16`** | `i16` | `i32` | `i64` | `f64` | `i16` | `i16` | `i32` | `i64` | `f16` | `f32` | `f64` | -| **`i32`** | `i32` | `i32` | `i64` | `f64` | `i32` | `i32` | `i32` | `i64` | `f16` | `f32` | `f64` | -| **`i64`** | `i64` | `i64` | `i64` | `f64` | `i64` | `i64` | `i64` | `i64` | `f16` | `f32` | `f64` | -| **`f16`** | `f16` | `f16` | `f16` | `f16` | `f16` | `f16` | `f16` | `f16` | `f16` | `f32` | `f64` | -| **`f32`** | `f32` | `f32` | `f32` | `f32` | `f32` | `f32` | `f32` | `f32` | `f32` | `f32` | `f64` | -| **`f64`** | `f64` | `f64` | `f64` | `f64` | `f64` | `f64` | `f64` | `f64` | `f64` | `f64` | `f64` | \ No newline at end of file diff --git a/python/docs/source/guide/entities.md b/python/docs/source/guide/entities.md deleted file mode 100644 index 0b1285f35..000000000 --- a/python/docs/source/guide/entities.md +++ /dev/null @@ -1,109 +0,0 @@ ---- -file_format: mystnb -kernelspec: - name: python3 - disply_name: Python 3 -mystnb: - execution_mode: cache ---- - -# Entities and Grouping - -Entities organize data for use in feature engineering. -They describe the particular objects that a prediction will be made for. -The result of a feature computation is a _feature vector_ for each entity at various points in time. - -## What is an Entity? -Entities represent the categories or "nouns" associated with the data. -They can generally be thought of as any category of object related to the events being processed. -For example, when manipulating purchase events, there may be entities for the customers, vendors and items being purchased. -Each purchase event may be related to a customer, a vendor, and one or more items. - -If something can be given a name or other unique identifier, it can likely be used as an entity. -In a relational database, an entity would be anything that is identified by the same key in a set of tables. - -## What is an Entity Key? -An entity kind is a category of objects, for example customer or vendor. -An entity key identifies a unique instance of that category -- a `customer_id` or a `vendor_id`. - -One may think of an entity as a table containing instances -- or rows -- of that type of entity. -The entity key would be the primary key of that table. - -The following table shows some example entities and possible keys. -Many of the example instances may not be suitable for use as the entity key, for the same reason you wouldn't use them as a primary key. -For example, using `Vancouver` to identify cities would lead to ambiguity between Vancouver in British Columbia and Vancouver in Washington State. -In these cases, you'd likely use some other identifier for instances. -Others may be useful, such as using the airport code. - -:::{list-table} Example Entities and corresponding keys. -:header-rows: 1 - -* - Example Entity - - Example Entity Instance -* - Houses - - 1600 Pennsylvania Avenue -* - Airports - - SEA -* - Customers - - John Doe -* - City - - Vancouver -* - State - - Washington -::: - -## Entities and Aggregation - -Many, if not all, Kaskada queries involve aggregating events to produce values. -Entities provide an implicit grouping for the aggregation. -When we write `sum(Purchases.amount)` it is an aggregation that returns the sum of purchases made _by each entity_. -This is helpful since the _feature vector_ for an entity will depend only on events related to that entity. - -% The input for this needs to be hidden, not removed. It seems that plotly won't -% render the right height otherwise (possibly because it's not attached to the DOM?). -% We could see if this worked better using a different library such as `bokeh` or if -% there were better options to pass to plotly to avoid the problem. -```{code-cell} ---- -tags: [hide-input] ---- -import asyncio -import kaskada as kd -kd.init_session() -data = "\n".join( - [ - "time,key,m", - "1996-12-19T16:39:57,A,5", - "1996-12-19T17:42:57,B,8", - "1996-12-20T16:39:59,A,17", - "1996-12-23T12:18:57,B,6", - "1996-12-23T16:40:01,A,12", - ] -) -multi_entity = await kd.sources.CsvString.create(data, time_column="time", key_column="key") - -kd.plot.render( - kd.plot.Plot(multi_entity.col("m"), name="m"), - kd.plot.Plot(multi_entity.col("m").sum(), name="sum(m)") -) -``` - - -## Changing Keys - -The key associated with each point may be changed using {py:meth}`kaskada.Timestream.with_key`. -For example, given a stream of purchases associated with each user, we could create a Timestream associated with the purchased item: - -```{code-block} python -:caption: Using with-key to associate purchases with items -purchases_by_user.with_key(purchases_by_user.col("item_id")) -``` - -This is particularly useful with the ability to [lookup](joins.md#explicit-lookups) values from associated with other keys. -For instance, we could re-key purchases as shown above to count the total spent on each item (across all users) and then lookup that information for each user's purchases. - -## Joining - -Joining with the same entity happens automatically. -Joining with other entities (and even other kinds of entities) is done using `lookup`. -See [Joins](joins.md) for more information. \ No newline at end of file diff --git a/python/docs/source/guide/execution.md b/python/docs/source/guide/execution.md deleted file mode 100644 index 558c2d778..000000000 --- a/python/docs/source/guide/execution.md +++ /dev/null @@ -1,91 +0,0 @@ -# Execution - -A [Timestream](./timestreams.md) may be executed and written to a [destination](#destinations) in a variety of ways. -The things to consider when deciding how to execute the Timestream are: - -1. Whether you want the _history_ of points or the _snapshot_ of values for each entity at a given time. -2. Whether you want to run a query _once_ or start a _live_ process continually materializing. -3. Whether you want to limit the output to points in a specific time range (for history) or entities that have changed since a specific time (for snapshots). -4. Whether you want to stop at a given point in time. - -[State](#state) can be used to provide fault-tolerance and allow incremental processing of only new events. - -```{admonition} Preview during development -:class: tip - -While developing queries, it is often useful to view a few rows from the result. -Using {py:meth}`kaskada.Timestream.preview` you can retrieve a small set of rows from the result set as a Pandas DataFrame. -``` - -## History vs. Snapshot - -Executing a Timestream for the history outputs every point in the Timestream. -This means that each entity likely appears in the output multiple times. -This is particularly useful for creating training examples from past data points, or visualizing how the Timestream has changed over time. - -Executing a Timestream for a snapshot produces a value for each entity at a specific point in time. -This means that each entity appears at-most once in the results. -This is useful for maintaining a feature store based on the latest values. - -```{todo} -Expose the configuration for snapshots. -See https://github.com/kaskada-ai/kaskada/issues/719 -``` - -## Query vs. Materialize -Every Timestream may be executed as a single query or used to start a materialization. -Single queries are useful when you want the results for some later batch process, such as fine-tuning a model or populating an in-memory feature store. -Materialization is useful when you want to stream new results out as quickly as possible, such as maintaining an in-memory feature store or reacting to specific conditions. - - -## Changed Since - -Configuring the _changed since time_ lets you control the points or entities included in the output. - -For a historic query, only points occurring after the changed since time are included in the output. -This allows incrementally outputting the entire history to some external store, by repeatedly performing a "changed since" query. - -For a snapshot query, only entities that have changed after this time are included in the output. -This reduces the amount of data written when the past snapshot is already present in the destination. - -```{todo} -Expose the configuration for changed since. -See https://github.com/kaskada-ai/kaskada/issues/719 -``` - -## Up To - -Configuring the _up to time_ lets you control the maximum points output (and in the case of snapshots, the time represented in the snapshot). - -For a historic query, only points occurring before or at the up to time are included in the output. -For a snapshot query, this corresponds to the time at which the snapshot will be taken. - -```{note} -Currently when not specified, the up to time is determined from the maximum event present in the data. -We have plans to change this to a parameter to `run` defaulting to the current time. -``` - -```{todo} -Expose the configuration for up-to. -See https://github.com/kaskada-ai/kaskada/issues/719 -``` - -## State - -Kaskada checkpoints state during and after execution. -This provides fault-tolerance, incremental querying and automatic handling of late-data. - -When a query is executed, Kaskada determines whether it can use any of the available states to reduce the amount of processing needed. -For instance, when producing a snapshot Kaskada can use any persisted state before the earliest new event and before the time to snapshot. -Similarly, when producing a history, Kaskada can use any persisted state before the earliest new event and before the "changed since" time. - -## Destinations - -The methods {py:func}`Timestream.preview` and {py:func}`Timestream.to_pandas` provide the results of a query in a Pandas DataFrame for easy visualization and consumption within the Python process. - -The {py:func}`Timestream.run_iter` methods provides synchronous and asynchronous iterators over the results in a variety of formats including Pandas DataFrames, PyArrow RecordBatches, and rows as Python dictionaries. -This allows you to run the entire retrieve-evaluate-respond loop within a single Python process. - -The {py:func}`Timestream.write` function allows you to specify a destination from {py:mod}`kaskada.destinations` for results. -This supports both `once` and `live` queries -See the reference on [destinations](../reference/destinations.md) for more on the supported destinations. \ No newline at end of file diff --git a/python/docs/source/guide/index.md b/python/docs/source/guide/index.md deleted file mode 100644 index b7d28a79b..000000000 --- a/python/docs/source/guide/index.md +++ /dev/null @@ -1,51 +0,0 @@ -# User Guide - -Understanding and reacting to the world in real-time requires understanding what is happening _now_ in the context of what happened in the past. -You need the ability to understand if what just happened is unusual, how it relates to what happened previously, and how it relates to other things that are happening at the same time. - -Kaskada processes events from streams and historic data sources to answer these questions in real-time. - -The power and convenience of Kaskad comes from a new: the Timestream. -Timestreams provide a declarative API like dataframes over the complete temporal context. -Easily combine multiple streams and reason about the complete sequence of events. -Use time-travel to compute training examples from historic data and understand how results change over time. - -## What are "Timestreams"? - -A [Timestream](timestreams) describes how a value changes over time. -In the same way that SQL queries transform tables and graph queries transform nodes and edges, Kaskada queries transform Timestreams. - -In comparison to a timeseries which often contains simple values (e.g., numeric observations) defined at fixed, periodic times (i.e., every minute), a Timestream contains any kind of data (records or collections as well as primitives) and may be defined at arbitrary times corresponding to when the events occur. - -## Getting Started with Timestreams - -Getting started with Timestreams is as simple as `pip` installing the Python library, loading some data and running a query. - -```python -import kaskada as kd - -# Read data from a Parquet file. -data = kd.sources.Parquet( - path = "path_to_file.parquet", - time_column = "time", - key_column = "user") -# Get the count of events associated with each user over time, as a dataframe. -data.count().to_pandas() -``` - -```{toctree} -:hidden: -:maxdepth: 2 - -quickstart -tour -why -installation -timestreams -data_types -entities -aggregation -joins -sources -execution -``` \ No newline at end of file diff --git a/python/docs/source/guide/installation.md b/python/docs/source/guide/installation.md deleted file mode 100644 index a518c9334..000000000 --- a/python/docs/source/guide/installation.md +++ /dev/null @@ -1,23 +0,0 @@ -# Installation - -To install Kaskada, you need to be using Python >= 3.8. -We suggest using 3.11 or newer, since that provides more precise error locations. - -```{code-block} bash -:caption: Installing Kaskada -pip install kaskada>=0.6.0-a.3 -``` - -```{warning} -This version of Kaskada is currently a pre-release, as indicated by the `-a.0` suffix. -It will not be installed by default if you `pip install kaskada`. -You need to either use `pip install --pre kaskada` or specify a specific version, as shown in the example. -``` - -```{tip} -Depending on you Python installation and configuration you may have `pip3` instead of `pip` available in your terminal. -If you do have `pip3` replace pip with `pip3` in your command, i.e., `pip3 install kaskada`. - -If you get a permission error when running the `pip` command, you may need to run as an administrator using `sudo pip install kaskada`. -If you don't have administrator access (e.g., in Google Colab, or other hosted environments) you amy use `pip`’s `--user` flag to install the package in your user directory. -``` diff --git a/python/docs/source/guide/joins.md b/python/docs/source/guide/joins.md deleted file mode 100644 index 73d935342..000000000 --- a/python/docs/source/guide/joins.md +++ /dev/null @@ -1,34 +0,0 @@ -# Joins - -It is often necessary to use multiple Timestreams to define a query. -Understanding user behavior requires considering their activity across a variety of event streams. -Normalizing user behavior may require looking comparing the per-user values to the average values for the region. -Both of these are accomplished by joining the Timestreams. - -## Implicit Joins -Timestreams associated with the same kind of entity -- for instance, a user -- are automatically joined. -This makes it easy to write queries that consider multiple event streams in a single query. - -```{code-block} python -:caption: Joining two event streams to compute page-views per purchase - -page_views.count() / purchases.count() -``` - -### Domains - -It is sometimes useful to consider the _domain_ of an expression. -This corresponds to the points in time and entities associated with the points in the expression. -For discrete timestreams, this corresponds to the points at which those values occur. -For continuous timestreams, this corresponds to the points at which the value changes. - -Whenever expressions with two (or more) different domains are used in the same expression they are implicitly joined. -The join is an outer join that contains an event if either (any) of the input domains contained an event. -For any input table that is continuous, the join is `as of` the time of the output, taking the latest value from that input. - -## Explicit Lookups - -Values from associated with other entities may be retrieved using {py:meth}`kaskada.Timestream.lookup`. -`left.lookup(right)` does a left-join, looking up the value from `right` for each computed key in `left`. - -Lookups are _temporally correct_ -- the value retrieved corresponds to the `right` value at the time the key occurred in `left`. \ No newline at end of file diff --git a/python/docs/source/guide/quickstart.md b/python/docs/source/guide/quickstart.md deleted file mode 100644 index 42b140a95..000000000 --- a/python/docs/source/guide/quickstart.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -file_format: mystnb -kernelspec: - name: python3 - display_name: Python 3 -mystnb: - execution_mode: cache ---- - -# Quick Start - -This shows the bare minimum needed to get started with Kaskada. - -## Install - -Install the latest version. -This uses `kaskada>=0.6.0-a.3` to ensure the pre-release version is installed. - -``` -pip install kaskada>=0.6.0-a.3 -``` - -See the section on [installation](./installation.md) to learn more about installing Kaskada. - -## Write a query - -The following Python code imports the Kaskada library, creates a session, and loads some CSV data. -It then runs a query to produce a Pandas DataFrame. - -```{code-cell} -import asyncio -import kaskada as kd -kd.init_session() -content = "\n".join( - [ - "time,key,m,n", - "1996-12-19T16:39:57,A,5,10", - "1996-12-19T16:39:58,B,24,3", - "1996-12-19T16:39:59,A,17,6", - "1996-12-19T16:40:00,A,,9", - "1996-12-19T16:40:01,A,12,", - "1996-12-19T16:40:02,A,,", - ] -) -source = await kd.sources.CsvString.create(content, time_column="time", key_column="key") -source.select("m", "n").extend({"sum_m": source.col("m").sum() }).to_pandas() -``` diff --git a/python/docs/source/guide/sources.md b/python/docs/source/guide/sources.md deleted file mode 100644 index 6e82078e4..000000000 --- a/python/docs/source/guide/sources.md +++ /dev/null @@ -1,11 +0,0 @@ -# Sources - -Sources describe how events enter a Timestream. -Every source is a Timestream containing the events that have been read. -Most often, these events are [records](data_types.md#record-types). - -Each event from a source is associated with a specific time and entity key. -These define how the resulting Timestream is ordered and grouped. -Generally, the time and entity key are associated with a specific column from the source, using the `time_column` and `key_column` arguments. - -The [Sources Reference](../reference/sources.md) has more details on the supported sources. \ No newline at end of file diff --git a/python/docs/source/guide/timestreams.md b/python/docs/source/guide/timestreams.md deleted file mode 100644 index a6b61c488..000000000 --- a/python/docs/source/guide/timestreams.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -file_format: mystnb -kernelspec: - name: python3 - disply_name: Python 3 -mystnb: - execution_mode: cache ---- - -# Timestreams - -Kaskada is built on the concept of a _Timestream_. -Each Timestream is ordered by _time_ and partitioned by _entity_. -This makes it easy to focus on events happening over time and how aggregations change. - -% The input for this needs to be hidden, not removed. It seems that plotly won't -% render the right height otherwise (possibly because it's not attached to the DOM?). -% We could see if this worked better using a different library such as `bokeh` or if -% there were better options to pass to plotly to avoid the problem. -```{code-cell} ---- -tags: [hide-input] ---- -import asyncio -import kaskada as kd -kd.init_session() -data = "\n".join( - [ - "time,key,m", - "1996-12-19T16:39:57,A,5", - "1996-12-19T17:42:57,B,8", - "1996-12-20T16:39:59,A,17", - "1996-12-23T12:18:57,B,6", - "1996-12-23T16:40:01,A,12", - ] -) -multi_entity = await kd.sources.CsvString.create(data, time_column="time", key_column="key") - -kd.plot.render( - kd.plot.Plot(multi_entity.col("m"), name="m") -) -``` - -## Continuity - -It is useful to consider two kinds of timestreams -- _discrete_ and _continuous_. -Like the example we already saw, a discrete timestream consists of values at specific points in time. -On the other hand, a continuous timestream represents a value that continues until it changes. -While a discrete timestream contains values at specific points in time, a continuous timestream changes at specific points in time. - -For example, the result of aggregating a timestream produces a continuous stream that changes on each non-`null` input. - -```{code-cell} ---- -tags: [remove-input] ---- -kd.plot.render( - kd.plot.Plot(multi_entity.col("m").sum(), name="sum(m)") -) \ No newline at end of file diff --git a/python/docs/source/guide/tour.md b/python/docs/source/guide/tour.md deleted file mode 100644 index 487fa055a..000000000 --- a/python/docs/source/guide/tour.md +++ /dev/null @@ -1,124 +0,0 @@ ---- -file_format: mystnb -kernelspec: - name: python3 - display_name: Python 3 -mystnb: - execution_mode: cache ---- - -% Level: Beginner -% Goal: Overview of the key features of Kaskada focused on explaining *why* you want them. -% Audience: Someone who has read the landing page and wants to understand what Kaskada can do for them. - -# Tour of Kaskada - -This provides an overview of the key features in Kaskada that enable feature engineering on event-based data. -The [Quick Start](./quickstart.md) has details on how you can quickly get started running Kaskada queries. -For a more complete explanation, see the User Guide. - -This tour uses Kaskada and Plotly to render the illustrations. -The initial setup / data is below. - -```{code-cell} ---- -tags: [hide-cell] ---- -import asyncio -import kaskada as kd -kd.init_session() -single_entity = "\n".join( - [ - "time,key,m,n", - "1996-12-19T16:39:57,A,5,10", - "1996-12-20T16:39:59,A,17,6", - "1996-12-22T16:40:00,A,,9", - "1996-12-23T16:40:01,A,12,", - "1996-12-24T16:40:02,A,,", - ] -) -single_entity = await kd.sources.CsvString.create(single_entity, time_column="time", key_column="key") -``` - -## Events and Aggregations - -Every Kaskada query operates on one or more _sources_ containing events. -Every event in a source happens at a specific point in time and relates to a specific entity. -A source contains events with the same schema. -Often, each source represents a specific kind of event, such as a login event or purchase. - -It is often convenient to picture temporal data as a sequence of timestamped events. -A natural question to ask about the purchases is the total--or `sum`--of all purchases made. -This is accomplished by _aggregating_ the events. -The results of an aggregation change over time as additional events occur. - -```{code-cell} ---- -tags: [remove-input] ---- -kd.plot.render( - kd.plot.Plot(single_entity.col("m"), name="m"), - kd.plot.Plot(single_entity.col("m").sum(), name="sum of m") -) -``` - -The User Guide has [more details on aggregation](./aggregation.md), including how to use windows to control which events are aggregated. - -## Discrete and Continuous -We say that events (and values derived from them) are _discrete_ because they occur at specific in time. -and the results of the aggregation are [_continuous_](./timestreams.md#continuity). -In the example, after the purchase with amount 13 the sum was 20. -And it _continued_ to be 20 at every point in time until the next purchase was made, with amount 4. -A continuous value is inclusive of the event that causes the value to change and exclusive of the next change. - -Thus, an aggregation at a given point in time reflects all events that have happened up to (and including) that point in time. -The concept of continuity applies to many other operations in Kaskada, not just aggregations. -This is part of what we mean when we say that Kaskada is a temporal query language. - -## Grouping -Another property of Kaskada is that events are implicitly grouped by _entity_. -In the previous example, we assumed that all purchases were made by the same user. -When the purchases are made by multiple users, there is a natural grouping for the aggregation. -When computing a machine learning feature such as "total purchases", we usually wish to aggregate the events related to a specific user or entity. - -One way to understand this grouping is as a separate stream associated with each entity. -The stream of purchases for each user may be shown separately, as we do here, or it may be pictured flattened into a single stream keyed by user. -The idea of grouped streams as separate, per-entity streams is often useful for understanding the behavior of Kaskada Timestreams. - -```{todo} -Add example of multiple entity aggregation. -``` - -The User Guide has [more details on grouping](./entities.md), including how to change the grouping of a Timestream. - -## History and Snapshots - -Since the Timestream describes how values are computed at every point in time, there are several useful ways they may be output. - -For training a model, it is often useful to output historic values matching some `filter`. -These historic points can then be used as training examples, allowing the model to be trained on past points. -This historic output is also useful for visualizing a Timestream at multiple points. - -For serving a model, it is often useful to output the value of a Timestream for every entity at a specific point in time. -This is most often used to output a snapshot at the current time. - -For both kinds of output, it is also useful to be able to select only the points after a specific time. -This would filter out points from the history, or limit the snapshot to only those entities which have changed. - -## Windowed Aggregation - -```{todo} -Update to reflect actual syntax. Include example. -``` - -In addition to the default behavior of aggregating over all events up to a given time, aggregations may be performed over specific windows. -For example, `hourly()` describes periodic windows of an hour. -The aggregation, `sum(Purchases, window=hourly())` would produce the cumulative sum of purchases made since the beginning of the hour. -For example, if there were purchases at 8:45 AM, 9:15 AM and 9:25 AM and 10:02 AM, then the result at 9:25 AM is the sum from 9:00 AM to 9:25 AM, which would include only the events at 9:15 AM and 9:25 AM. - -A non-cumulative windowed aggregation produces values only at the end of a window. -For instance, `sum(Purchases, window=hourly(), cumulative=false)` will produce the sum for the past hour. -With the purchases in the previous example, this would mean that at 9:00 AM an event is produced containing the amount of the purchase at 8:45 AM, and at 10:00 AM an event is produced containing the sum of the purchases at 9:15 AM and 9:25 AM. -A window must be specified when using a non-cumulative aggregation. - -The section on [Aggregation](./aggregation.md#windowing) has more information on windowing. \ No newline at end of file diff --git a/python/docs/source/guide/why.md b/python/docs/source/guide/why.md deleted file mode 100644 index ff2e17b6d..000000000 --- a/python/docs/source/guide/why.md +++ /dev/null @@ -1,15 +0,0 @@ -# Why Kaskada? - -Kaskada is a library for executing temporal queries over event-based data. -An "event" can be any fact about the world associated with a time. -For example, a user signing up for a service, or a customer purchasing a product. -As additional events occur the computed values may change as well. - -Traditional data processing systems are designed to answer questions about the current state of a dataset. -For instance, "how many purchases has a given user made?" -Over time, the user makes additional purchases and the answer *should* change. -With these traditional data processing systems, the answer changes based on when it is asked. - -With Kaskada, the query "how many purchases has a given user made?" is expressed as a _Timestream_. -This represents how the result of that query changes over time for each user. -Kaskada makes it easy to combine Timestreams to produce a new Timestream -- joining points from each input as needed. \ No newline at end of file diff --git a/python/docs/source/index.md b/python/docs/source/index.md deleted file mode 100644 index 94ccd4ffc..000000000 --- a/python/docs/source/index.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -html_theme.sidebar_secondary.remove: true -sd_hide_title: true ---- - -# Real-Time AI without the fuss. - -
- - -

Real-Time AI without the fuss.

-
-

Kaskada is a next-generation streaming engine that connects AI models to real-time & historical data. -

-
-
- -## Kaskada completes the Real-Time AI stack, providing... - -```{gallery-grid} -:grid-columns: 1 2 2 3 - -- header: "{fas}`timeline;pst-color-primary` Real-time Aggregation" - content: "Precompute model inputs from streaming data with robust data connectors, transformations & aggregations." -- header: "{fas}`binoculars;pst-color-primary` Event Detection" - content: "Trigger pro-active AI behaviors by identifying important activities, as they happen." -- header: "{fas}`backward;pst-color-primary` History Replay" - content: "Backtest and fine-tune from historical data using per-example time travel and point-in-time joins." -``` - - -## Real-time AI in minutes - -Connect and compute over databases, streaming data, _and_ data loaded dynamically using Python. -Kaskada is seamlessly integrated with Python's ecosystem of AI/ML tooling so you can load data, process it, train and serve models all in the same place. - -There's no infrastructure to provision (and no JVM hiding under the covers), so you can jump right in - check out the [Quick Start](./guide/quickstart.md). - - -## Built for scale and reliability - -Implemented in [Rust](https://www.rust-lang.org/) using [Apache Arrow](https://arrow.apache.org/), Kaskada's compute engine uses columnar data to efficiently execute large historic and high-throughput streaming queries. -Every operation in Kaskada is implemented incrementally, allowing automatic recovery if the process is terminated or killed. - -With Kaskada, most jobs are fast enough to run locally, so it's easy to build and test your real-time queries. -As your needs grow, Kaskada's cloud-native design and support for partitioned execution gives you the volume and throughput you need to scale. -Kaskada was built by core contributors to [Apache Beam](https://beam.apache.org/), [Google Cloud Dataflow](https://cloud.google.com/dataflow), and [Apache Cassandra](https://cassandra.apache.org/), and is under active development - -* * * - -## Example Real-Time App: BeepGPT - -[BeepGPT](https://github.com/kaskada-ai/beep-gpt/tree/main) keeps you in the loop without disturbing your focus. Its personalized, intelligent AI continuously monitors your Slack workspace, alerting you to important conversations and freeing you to concentrate on what’s most important. - -The core of BeepGPT's real-time processing requires only a few lines of code using Kaskada: - -```python -import asyncio -import kaskada as kd -kd.init_session() - -# Bootstrap from historical data -messages = await kd.sources.PyDict.create( - rows = pyarrow.parquet.read_table("./messages.parquet") - .to_pylist(), - time_column = "ts", - key_column = "channel", -) - -# Send each Slack message to Kaskada -def handle_message(client, req): - messages.add_rows(req.payload["event"]) -slack.socket_mode_request_listeners.append(handle_message) -slack.connect() - -# Aggregate multiple messages into a "conversation" -conversations = ( messages - .select("user", "text") - .collect(max=20) -) - -# Handle each conversation as it occurs -async for row in conversations.run_iter(mode='live'): - - # Use a pre-trained model to identify interested users - prompt = "\n\n".join([f' {msg["user"]} --> {msg["text"]} ' for msg in row["result"]]) - res = openai.Completion.create( - model="davinci:ft-personal:coversation-users-full-kaskada-2023-08-05-14-25-30", - prompt=prompt + "\n\n###\n\n", - logprobs=5, - max_tokens=1, - stop=" end", - temperature=0.25, - ) - - # Notify interested users using the Slack API - for user_id in interested_users(res): - notify_user(row, user_id) -``` - -For more details, check out the [BeepGPT Github project](https://github.com/kaskada-ai/beep-gpt). - -* * * - -## Get Started - -Getting started with Kaskda is a `pip install kaskada` away. -Check out the [Quick Start](./guide/quickstart.md) now! - -```{toctree} -:hidden: -:maxdepth: 3 - -guide/index -examples/index -community/index -reference/index -blog/index -``` \ No newline at end of file diff --git a/python/docs/source/reference/destinations.md b/python/docs/source/reference/destinations.md deleted file mode 100644 index 4eb506273..000000000 --- a/python/docs/source/reference/destinations.md +++ /dev/null @@ -1,11 +0,0 @@ -# Destinations - -```{eval-rst} - -.. automodule:: kaskada.destinations - - .. autosummary:: - :toctree: apidocs/destinations - - Destination -``` \ No newline at end of file diff --git a/python/docs/source/reference/execution.md b/python/docs/source/reference/execution.md deleted file mode 100644 index 29b6ae883..000000000 --- a/python/docs/source/reference/execution.md +++ /dev/null @@ -1,11 +0,0 @@ -# Execution - -```{eval-rst} -.. currentmodule:: kaskada - -.. autosummary:: - :toctree: apidocs/ - - Execution - ResultIterator -``` \ No newline at end of file diff --git a/python/docs/source/reference/index.md b/python/docs/source/reference/index.md deleted file mode 100644 index 8ce92b2cb..000000000 --- a/python/docs/source/reference/index.md +++ /dev/null @@ -1,13 +0,0 @@ -# API - -```{toctree} -:hidden: -:maxdepth: 3 - -timestream/index -windows -sources -destinations -results -execution -``` diff --git a/python/docs/source/reference/results.md b/python/docs/source/reference/results.md deleted file mode 100644 index ce07a295c..000000000 --- a/python/docs/source/reference/results.md +++ /dev/null @@ -1,13 +0,0 @@ -# Results - -These classes allow configuring the results to be produced. - -```{eval-rst} -.. currentmodule:: kaskada.results - -.. autosummary:: - :toctree: apidocs/ - - History - Snapshot -``` \ No newline at end of file diff --git a/python/docs/source/reference/sources.md b/python/docs/source/reference/sources.md deleted file mode 100644 index 59a66a1be..000000000 --- a/python/docs/source/reference/sources.md +++ /dev/null @@ -1,17 +0,0 @@ -# Sources - -```{eval-rst} - -.. automodule:: kaskada.sources - - .. autosummary:: - :toctree: apidocs/sources - - Source - CsvString - JsonlFile - JsonlString - Pandas - Parquet - PyDict -``` \ No newline at end of file diff --git a/python/docs/source/reference/timestream/aggregation.md b/python/docs/source/reference/timestream/aggregation.md deleted file mode 100644 index 3adc384fe..000000000 --- a/python/docs/source/reference/timestream/aggregation.md +++ /dev/null @@ -1,28 +0,0 @@ -# Aggregation - -The User Guide has details on [aggregations in general](../../guide/aggregation.md). - -```{note} -It is important to remember that aggregations are partitioned by entity and windowed, with the default behavior being cumulative up to the current time. -``` - -## Aggregation Methods - -```{eval-rst} -.. currentmodule:: kaskada - -.. autosummary:: - :toctree: ../apidocs/ - - Timestream.collect - Timestream.count - Timestream.count_if - Timestream.first - Timestream.last - Timestream.max - Timestream.mean - Timestream.min - Timestream.stddev - Timestream.sum - Timestream.variance -``` \ No newline at end of file diff --git a/python/docs/source/reference/timestream/arithmetic.md b/python/docs/source/reference/timestream/arithmetic.md deleted file mode 100644 index 7f7a72564..000000000 --- a/python/docs/source/reference/timestream/arithmetic.md +++ /dev/null @@ -1,33 +0,0 @@ -# Arithmetic - -Timestreams support a variety of arithmetic operations. - -```{note} -Note: In addition to the chainable methods, standard operators are implemented where appropriate. -For instance, `a.add(b)` may be written as `a + b`. -See the notes on the specific functions for more information. -``` - -## Arithmetic Methods - -```{eval-rst} -.. currentmodule:: kaskada - -.. autosummary:: - :toctree: ../apidocs/ - - Timestream.add - Timestream.ceil - Timestream.clamp - Timestream.div - Timestream.exp - Timestream.floor - Timestream.greatest - Timestream.least - Timestream.mul - Timestream.neg - Timestream.powf - Timestream.round - Timestream.sqrt - Timestream.sub -``` \ No newline at end of file diff --git a/python/docs/source/reference/timestream/collection.md b/python/docs/source/reference/timestream/collection.md deleted file mode 100644 index 90da93a85..000000000 --- a/python/docs/source/reference/timestream/collection.md +++ /dev/null @@ -1,18 +0,0 @@ -# Collections - -Timestreams allow each point to contain a collection -- a `list` or `map` -- of elements. - -## Collection Methods - -```{eval-rst} -.. currentmodule:: kaskada - -.. autosummary:: - :toctree: ../apidocs/ - - Timestream.__getitem__ - Timestream.flatten - Timestream.index - Timestream.length - Timestream.union -``` \ No newline at end of file diff --git a/python/docs/source/reference/timestream/comparison.md b/python/docs/source/reference/timestream/comparison.md deleted file mode 100644 index bdf014ba9..000000000 --- a/python/docs/source/reference/timestream/comparison.md +++ /dev/null @@ -1,29 +0,0 @@ -# Comparison - -Comparison operations produce boolean Timestreams. - -```{note} -Note: In addition to the chainable methods, standard operators are implemented where appropriate. -For instance, `a.ge(b)` may be written as `a >= b`. -See the notes on the specific functions for more information. - -To respect the semantics of `__eq__` and `__ne__`, `a == b` and `a != b` are *not* overloaded. -``` - -## Comparison Methods - -```{eval-rst} -.. currentmodule:: kaskada - -.. autosummary:: - :toctree: ../apidocs/ - - Timestream.eq - Timestream.ge - Timestream.gt - Timestream.le - Timestream.lt - Timestream.ne - Timestream.is_null - Timestream.is_not_null -``` \ No newline at end of file diff --git a/python/docs/source/reference/timestream/execution.md b/python/docs/source/reference/timestream/execution.md deleted file mode 100644 index 32c87b574..000000000 --- a/python/docs/source/reference/timestream/execution.md +++ /dev/null @@ -1,13 +0,0 @@ -# Execution - -```{eval-rst} -.. currentmodule:: kaskada - -.. autosummary:: - :toctree: ../apidocs/ - - Timestream.preview - Timestream.to_pandas - Timestream.run_iter - Timestream.write -``` \ No newline at end of file diff --git a/python/docs/source/reference/timestream/grouping.md b/python/docs/source/reference/timestream/grouping.md deleted file mode 100644 index 47575a856..000000000 --- a/python/docs/source/reference/timestream/grouping.md +++ /dev/null @@ -1,11 +0,0 @@ -# Grouping - -```{eval-rst} -.. currentmodule:: kaskada - -.. autosummary:: - :toctree: ../apidocs/ - - Timestream.lookup - Timestream.with_key -``` \ No newline at end of file diff --git a/python/docs/source/reference/timestream/index.md b/python/docs/source/reference/timestream/index.md deleted file mode 100644 index eaf46a2d6..000000000 --- a/python/docs/source/reference/timestream/index.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -html_theme.sidebar_secondary.remove: ---- - -# Timestream - -```{eval-rst} -.. currentmodule:: kaskada - -.. autoclass:: kaskada.Timestream - :exclude-members: __init__ - - .. autoproperty:: data_type - -.. autoclass:: kaskada.Arg -.. autoclass:: kaskada.LiteralValue -``` - -```{toctree} -:hidden: - -aggregation -arithmetic -collection -comparison -execution -grouping -logical -misc -records -string -time -``` \ No newline at end of file diff --git a/python/docs/source/reference/timestream/logical.md b/python/docs/source/reference/timestream/logical.md deleted file mode 100644 index e2eeb9927..000000000 --- a/python/docs/source/reference/timestream/logical.md +++ /dev/null @@ -1,12 +0,0 @@ -# Logical - -```{eval-rst} -.. currentmodule:: kaskada - -.. autosummary:: - :toctree: ../apidocs/ - - Timestream.and_ - Timestream.or_ - Timestream.not_ -``` \ No newline at end of file diff --git a/python/docs/source/reference/timestream/misc.md b/python/docs/source/reference/timestream/misc.md deleted file mode 100644 index 609c29f4a..000000000 --- a/python/docs/source/reference/timestream/misc.md +++ /dev/null @@ -1,18 +0,0 @@ -# Miscellaneous - -```{eval-rst} -.. currentmodule:: kaskada - -.. autosummary:: - :toctree: ../apidocs/ - - Timestream.cast - Timestream.coalesce - Timestream.else_ - Timestream.filter - Timestream.hash - Timestream.if_ - Timestream.lag - Timestream.null_if - Timestream.pipe -``` \ No newline at end of file diff --git a/python/docs/source/reference/timestream/records.md b/python/docs/source/reference/timestream/records.md deleted file mode 100644 index 24a2b4743..000000000 --- a/python/docs/source/reference/timestream/records.md +++ /dev/null @@ -1,19 +0,0 @@ -# Records - -Record operations create, extract or manipulate Timestreams of records. - -## Record Methods - -```{eval-rst} -.. currentmodule:: kaskada - -.. autosummary:: - :toctree: ../apidocs/ - - Timestream.col - Timestream.select - Timestream.remove - Timestream.extend - Timestream.record - record -``` \ No newline at end of file diff --git a/python/docs/source/reference/timestream/string.md b/python/docs/source/reference/timestream/string.md deleted file mode 100644 index 6649e8ed5..000000000 --- a/python/docs/source/reference/timestream/string.md +++ /dev/null @@ -1,13 +0,0 @@ -# String - -```{eval-rst} -.. currentmodule:: kaskada - -.. autosummary:: - :toctree: ../apidocs/ - - Timestream.len - Timestream.lower - Timestream.substring - Timestream.upper -``` \ No newline at end of file diff --git a/python/docs/source/reference/timestream/time.md b/python/docs/source/reference/timestream/time.md deleted file mode 100644 index a1e2e3aab..000000000 --- a/python/docs/source/reference/timestream/time.md +++ /dev/null @@ -1,15 +0,0 @@ -# Time - -```{eval-rst} -.. currentmodule:: kaskada - -.. autosummary:: - :toctree: ../apidocs/ - - Timestream.shift_by - Timestream.shift_to - Timestream.shift_until - Timestream.time - Timestream.seconds_since - Timestream.seconds_since_previous -``` \ No newline at end of file diff --git a/python/docs/source/reference/windows.md b/python/docs/source/reference/windows.md deleted file mode 100644 index d14513a98..000000000 --- a/python/docs/source/reference/windows.md +++ /dev/null @@ -1,13 +0,0 @@ -# Windows - -```{eval-rst} -.. currentmodule:: kaskada.windows - -.. autosummary:: - :toctree: apidocs/windows/ - - Window - Since - Sliding - Trailing -``` \ No newline at end of file From 03017b838a9748186395462200c8c68c81d304d6 Mon Sep 17 00:00:00 2001 From: Eric Pinzur Date: Sun, 8 Oct 2023 08:43:13 -0500 Subject: [PATCH 02/14] added new docs --- python/docs/.gitignore | 18 + .../_extensions/machow/interlinks/.gitignore | 3 + .../machow/interlinks/_extension.yml | 7 + .../machow/interlinks/interlinks.lua | 254 ++ .../include-code-files/_extension.yml | 9 + .../include-code-files/include-code-files.lua | 63 + python/docs/_quarto.yml | 92 + python/docs/_reference.yml | 189 + python/docs/_scripts/builder.py | 282 ++ python/docs/_scripts/gen_reference.py | 20 + python/docs/_scripts/renderer.py | 483 +++ python/docs/_scripts/summarizer.py | 117 + python/docs/_static/css/design-style.css | 3183 +++++++++++++++++ python/docs/_static/css/root.css | 38 + python/docs/_static/css/styles.css | 87 + .../fonts/FontAwesome6Free-Solid-900.ttf | Bin 0 -> 384736 bytes .../fonts/FontAwesome6Free-Solid-900.woff2 | Bin 0 -> 133940 bytes python/docs/_static/images/favicon.png | Bin 0 -> 5056 bytes .../docs/_static/images/kaskada-negative.svg | 1 + .../docs/_static/images/kaskada-positive.svg | 1 + python/docs/_templates/card.ejs | 23 + python/docs/_templates/data_types_table.ejs | 44 + python/docs/blog/_metadata.yml | 4 + python/docs/blog/index.qmd | 12 + .../2023-03-28-announcing-kaskada-oss.qmd | 76 + .../blog/posts/2023-08-25-new-kaskada.qmd | 83 + python/docs/examples/_metadata.yml | 7 + python/docs/examples/bluesky.md | 54 + python/docs/examples/bluesky.py | 172 + python/docs/examples/index.qmd | 7 + python/docs/examples/reddit.md | 73 + python/docs/examples/reddit.py | 92 + python/docs/examples/time_centric.ipynb | 357 ++ python/docs/guide/_metadata.yml | 10 + python/docs/guide/aggregation.qmd | 41 + python/docs/guide/data_types.qmd | 84 + python/docs/guide/data_types.yml | 31 + python/docs/guide/entities.qmd | 96 + python/docs/guide/execution.qmd | 92 + python/docs/guide/index.qmd | 36 + python/docs/guide/installation.qmd | 24 + python/docs/guide/joins.qmd | 34 + python/docs/guide/quickstart.qmd | 40 + python/docs/guide/sources.qmd | 13 + python/docs/guide/timestreams.qmd | 54 + python/docs/guide/tour.qmd | 116 + python/docs/guide/why.qmd | 17 + python/docs/index.qmd | 117 + 48 files changed, 6656 insertions(+) create mode 100644 python/docs/.gitignore create mode 100644 python/docs/_extensions/machow/interlinks/.gitignore create mode 100644 python/docs/_extensions/machow/interlinks/_extension.yml create mode 100644 python/docs/_extensions/machow/interlinks/interlinks.lua create mode 100644 python/docs/_extensions/quarto-ext/include-code-files/_extension.yml create mode 100644 python/docs/_extensions/quarto-ext/include-code-files/include-code-files.lua create mode 100644 python/docs/_quarto.yml create mode 100644 python/docs/_reference.yml create mode 100644 python/docs/_scripts/builder.py create mode 100644 python/docs/_scripts/gen_reference.py create mode 100644 python/docs/_scripts/renderer.py create mode 100644 python/docs/_scripts/summarizer.py create mode 100644 python/docs/_static/css/design-style.css create mode 100644 python/docs/_static/css/root.css create mode 100644 python/docs/_static/css/styles.css create mode 100644 python/docs/_static/fonts/FontAwesome6Free-Solid-900.ttf create mode 100644 python/docs/_static/fonts/FontAwesome6Free-Solid-900.woff2 create mode 100644 python/docs/_static/images/favicon.png create mode 100644 python/docs/_static/images/kaskada-negative.svg create mode 100644 python/docs/_static/images/kaskada-positive.svg create mode 100644 python/docs/_templates/card.ejs create mode 100644 python/docs/_templates/data_types_table.ejs create mode 100644 python/docs/blog/_metadata.yml create mode 100644 python/docs/blog/index.qmd create mode 100644 python/docs/blog/posts/2023-03-28-announcing-kaskada-oss.qmd create mode 100644 python/docs/blog/posts/2023-08-25-new-kaskada.qmd create mode 100644 python/docs/examples/_metadata.yml create mode 100644 python/docs/examples/bluesky.md create mode 100644 python/docs/examples/bluesky.py create mode 100644 python/docs/examples/index.qmd create mode 100644 python/docs/examples/reddit.md create mode 100644 python/docs/examples/reddit.py create mode 100644 python/docs/examples/time_centric.ipynb create mode 100644 python/docs/guide/_metadata.yml create mode 100644 python/docs/guide/aggregation.qmd create mode 100644 python/docs/guide/data_types.qmd create mode 100644 python/docs/guide/data_types.yml create mode 100644 python/docs/guide/entities.qmd create mode 100644 python/docs/guide/execution.qmd create mode 100644 python/docs/guide/index.qmd create mode 100644 python/docs/guide/installation.qmd create mode 100644 python/docs/guide/joins.qmd create mode 100644 python/docs/guide/quickstart.qmd create mode 100644 python/docs/guide/sources.qmd create mode 100644 python/docs/guide/timestreams.qmd create mode 100644 python/docs/guide/tour.qmd create mode 100644 python/docs/guide/why.qmd create mode 100644 python/docs/index.qmd diff --git a/python/docs/.gitignore b/python/docs/.gitignore new file mode 100644 index 000000000..907d4ff4d --- /dev/null +++ b/python/docs/.gitignore @@ -0,0 +1,18 @@ +# quarto build cache +/.quarto/ + +# quartodoc interlink artifacts +/_inv/ +/objects.json + +# generated API docs +/reference/ + +# files that might remain if a quarto build is interrupted +*.html +index-listing.json +data_types-listing.json +/site_libs/ + +# output of the site from `nox -s docs-build` +/_site/ diff --git a/python/docs/_extensions/machow/interlinks/.gitignore b/python/docs/_extensions/machow/interlinks/.gitignore new file mode 100644 index 000000000..5a1bf0b4e --- /dev/null +++ b/python/docs/_extensions/machow/interlinks/.gitignore @@ -0,0 +1,3 @@ +*.html +*.pdf +*_files/ diff --git a/python/docs/_extensions/machow/interlinks/_extension.yml b/python/docs/_extensions/machow/interlinks/_extension.yml new file mode 100644 index 000000000..c8a812136 --- /dev/null +++ b/python/docs/_extensions/machow/interlinks/_extension.yml @@ -0,0 +1,7 @@ +title: Interlinks +author: Michael Chow +version: 1.1.0 +quarto-required: ">=1.2.0" +contributes: + filters: + - interlinks.lua diff --git a/python/docs/_extensions/machow/interlinks/interlinks.lua b/python/docs/_extensions/machow/interlinks/interlinks.lua new file mode 100644 index 000000000..47aa61fa6 --- /dev/null +++ b/python/docs/_extensions/machow/interlinks/interlinks.lua @@ -0,0 +1,254 @@ +local function read_inv_text(filename) + -- read file + local file = io.open(filename, "r") + if file == nil then + return nil + end + local str = file:read("a") + file:close() + + + local project = str:match("# Project: (%S+)") + local version = str:match("# Version: (%S+)") + + local data = {project = project, version = version, items = {}} + + local ptn_data = + "^" .. + "(.-)%s+" .. -- name + "([%S:]-):" .. -- domain + "([%S]+)%s+" .. -- role + "(%-?%d+)%s+" .. -- priority + "(%S*)%s+" .. -- uri + "(.-)\r?$" -- dispname + + + -- Iterate through each line in the file content + for line in str:gmatch("[^\r\n]+") do + if not line:match("^#") then + -- Match each line against the pattern + local name, domain, role, priority, uri, dispName = line:match(ptn_data) + + -- if name is nil, raise an error + if name == nil then + error("Error parsing line: " .. line) + end + + data.items[#data.items + 1] = { + name = name, + domain = domain, + role = role, + priority = priority, + uri = uri, + dispName = dispName + } + end + end + return data +end + +local function read_json(filename) + + local file = io.open(filename, "r") + if file == nil then + return nil + end + local str = file:read("a") + file:close() + + local decoded = quarto.json.decode(str) + return decoded +end + +local function read_inv_text_or_json(base_name) + local file = io.open(base_name .. ".txt", "r") + if file then + -- TODO: refactors so we don't just close the file immediately + io.close(file) + json = read_inv_text(base_name .. ".txt") + + else + json = read_json(base_name .. ".json") + end + + return json +end + +local inventory = {} + +local function lookup(search_object) + + local results = {} + for _, inv in ipairs(inventory) do + for _, item in ipairs(inv.items) do + -- e.g. :external+:::`` + if item.inv_name and item.inv_name ~= search_object.inv_name then + goto continue + end + + if item.name ~= search_object.name then + goto continue + end + + if search_object.role and item.role ~= search_object.role then + goto continue + end + + if search_object.domain and item.domain ~= search_object.domain then + goto continue + else + if search_object.domain or item.domain == "py" then + table.insert(results, item) + end + + goto continue + end + + ::continue:: + end + end + + if #results == 1 then + return results[1] + end + if #results > 1 then + quarto.log.warning("Found multiple matches for " .. search_object.name .. ", using the first match.") + return results[1] + end + if #results == 0 then + quarto.log.warning("Found no matches for object:\n", search_object) + end + + return nil +end + +local function mysplit (inputstr, sep) + if sep == nil then + sep = "%s" + end + local t={} + for str in string.gmatch(inputstr, "([^"..sep.."]+)") do + table.insert(t, str) + end + return t +end + +local function normalize_role(role) + if role == "func" then + return "function" + end + return role +end + +local function build_search_object(str) + local starts_with_colon = str:sub(1, 1) == ":" + local search = {} + if starts_with_colon then + local t = mysplit(str, ":") + if #t == 2 then + -- e.g. :py:func:`my_func` + search.role = normalize_role(t[1]) + search.name = t[2]:match("%%60(.*)%%60") + elseif #t == 3 then + -- e.g. :py:func:`my_func` + search.domain = t[1] + search.role = normalize_role(t[2]) + search.name = t[3]:match("%%60(.*)%%60") + elseif #t == 4 then + -- e.g. :ext+inv:py:func:`my_func` + search.external = true + + search.inv_name = t[1]:match("external%+(.*)") + search.domain = t[2] + search.role = normalize_role(t[3]) + search.name = t[4]:match("%%60(.*)%%60") + else + quarto.log.warning("couldn't parse this link: " .. str) + return {} + end + else + search.name = str:match("%%60(.*)%%60") + end + + if search.name == nil then + quarto.log.warning("couldn't parse this link: " .. str) + return {} + end + + if search.name:sub(1, 1) == "~" then + search.shortened = true + search.name = search.name:sub(2, -1) + end + return search +end + +local function report_broken_link(link, search_object, replacement) + -- TODO: how to unescape html elements like [? + return pandoc.Code(pandoc.utils.stringify(link.content)) +end + +function Link(link) + -- do not process regular links ---- + if not link.target:match("%%60") then + return link + end + + -- lookup item ---- + local search = build_search_object(link.target) + local item = lookup(search) + + -- determine replacement, used if no link text specified ---- + local original_text = pandoc.utils.stringify(link.content) + local replacement = search.name + if search.shortened then + local t = mysplit(search.name, ".") + replacement = t[#t] + end + + -- set link text ---- + if original_text == "" and replacement ~= nil then + link.content = pandoc.Code(replacement) + end + + -- report broken links ---- + if item == nil then + return report_broken_link(link, search) + end + link.target = item.uri:gsub("%$$", search.name) + + + return link +end + +local function fixup_json(json, prefix) + for _, item in ipairs(json.items) do + item.uri = prefix .. item.uri + end + table.insert(inventory, json) +end + +return { + { + Meta = function(meta) + local json + local prefix + if meta.interlinks and meta.interlinks.sources then + for k, v in pairs(meta.interlinks.sources) do + local base_name = quarto.project.offset .. "/_inv/" .. k .. "_objects" + json = read_inv_text_or_json(base_name) + prefix = pandoc.utils.stringify(v.url) + if json ~= nil then + fixup_json(json, prefix) + end + end + end + json = read_inv_text_or_json(quarto.project.offset .. "/objects") + if json ~= nil then + fixup_json(json, "/") + end + end + }, + { + Link = Link + } +} diff --git a/python/docs/_extensions/quarto-ext/include-code-files/_extension.yml b/python/docs/_extensions/quarto-ext/include-code-files/_extension.yml new file mode 100644 index 000000000..13c496060 --- /dev/null +++ b/python/docs/_extensions/quarto-ext/include-code-files/_extension.yml @@ -0,0 +1,9 @@ +title: Include Code Files +author: Bruno Beaufils +version: 1.0.0 +quarto-required: ">=1.2" +contributes: + filters: + - include-code-files.lua + + diff --git a/python/docs/_extensions/quarto-ext/include-code-files/include-code-files.lua b/python/docs/_extensions/quarto-ext/include-code-files/include-code-files.lua new file mode 100644 index 000000000..c5f5cbf66 --- /dev/null +++ b/python/docs/_extensions/quarto-ext/include-code-files/include-code-files.lua @@ -0,0 +1,63 @@ +--- include-code-files.lua – filter to include code from source files +--- +--- Copyright: © 2020 Bruno BEAUFILS +--- License: MIT – see LICENSE file for details + +--- Dedent a line +local function dedent (line, n) + return line:sub(1,n):gsub(" ","") .. line:sub(n+1) +end + +--- Filter function for code blocks +local function transclude (cb) + if cb.attributes.include then + local content = "" + local fh = io.open(cb.attributes.include) + if not fh then + io.stderr:write("Cannot open file " .. cb.attributes.include .. " | Skipping includes\n") + else + local number = 1 + local start = 1 + + -- change hyphenated attributes to PascalCase + for i,pascal in pairs({"startLine", "endLine"}) + do + local hyphen = pascal:gsub("%u", "-%0"):lower() + if cb.attributes[hyphen] then + cb.attributes[pascal] = cb.attributes[hyphen] + cb.attributes[hyphen] = nil + end + end + + if cb.attributes.startLine then + cb.attributes.startFrom = cb.attributes.startLine + start = tonumber(cb.attributes.startLine) + end + for line in fh:lines ("L") + do + if cb.attributes.dedent then + line = dedent(line, cb.attributes.dedent) + end + if number >= start then + if not cb.attributes.endLine or number <= tonumber(cb.attributes.endLine) then + content = content .. line + end + end + number = number + 1 + end + fh:close() + end + -- remove key-value pair for used keys + cb.attributes.include = nil + cb.attributes.startLine = nil + cb.attributes.endLine = nil + cb.attributes.dedent = nil + -- return final code block + return pandoc.CodeBlock(content, cb.attr) + end +end + +return { + { CodeBlock = transclude } +} + diff --git a/python/docs/_quarto.yml b/python/docs/_quarto.yml new file mode 100644 index 000000000..aa93147b1 --- /dev/null +++ b/python/docs/_quarto.yml @@ -0,0 +1,92 @@ +project: + type: website + output-dir: .quarto/_site + preview: + port: 4200 + browser: true # Open a web browser to view the preview + navigate: true # Navigate the browser automatically when outputs are updated + watch-inputs: true # Re-render input files when they change + +website: + favicon: "_static/images/favicon.png" + google-analytics: G-HR9E2E6TG4 + page-navigation: true + navbar: + background: primary + logo: "_static/images/kaskada-negative.svg" + logo-alt: "Kaskada logo." + title: false + left: + - href: guide/index.qmd + text: User Guide + - href: examples/index.qmd + text: Examples + - href: reference/index.qmd + text: API + - href: blog/index.qmd + text: Blog + right: + - icon: slack + href: https://join.slack.com/t/kaskada-hq/shared_invite/zt-1t1lms085-bqs2jtGO2TYr9kuuam~c9w + - icon: github + href: https://github.com/kaskada-ai/kaskada + sidebar: + - title: User Guide + style: docked + contents: + - guide/index.qmd + - guide/quickstart.qmd + - guide/tour.qmd + - guide/why.qmd + - guide/installation.qmd + - guide/timestreams.qmd + - guide/data_types.qmd + - guide/entities.qmd + - guide/aggregation.qmd + - guide/joins.qmd + - guide/sources.qmd + - guide/execution.qmd + - title: Examples + contents: examples + - title: API + style: docked + contents: reference + + page-footer: + border: true + left: "© Copyright 2023, Kaskada Contributors." + repo-url: https://github.com/kaskada-ai/kaskada/ + repo-subdir: python/docs + repo-actions: + - edit + - source + site-url: https://kaskada.io + title: Kaskada + +format: + html: + theme: + light: flatly + dark: darkly #vapor + css: + - _static/css/styles.css + include-in-header: _templates/announcement.html + toc: true + link-external-icon: false + link-external-newwindow: false + link-external-filter: '^(?:http:|https:)\/\/kaskada\.io\/' + +filters: + - interlinks + +interlinks: + fast: true + sources: + numpy: + url: https://numpy.org/doc/stable/ + pandas: + url: https://pandas.pydata.org/docs/ + pyarrow: + url: https://arrow.apache.org/docs/ + python: + url: https://docs.python.org/3/ diff --git a/python/docs/_reference.yml b/python/docs/_reference.yml new file mode 100644 index 000000000..ece4a7fbb --- /dev/null +++ b/python/docs/_reference.yml @@ -0,0 +1,189 @@ +quartodoc: + title: API + dir: reference + package: kaskada + source_dir: ../pysrc + options: + children: separate + include_empty: true + dynamic: true + + sections: + - title: Timestream + options: + children: flat + contents: + - name: Timestream + members: + - data_type + - _timestream.LiteralValue + - _timestream.Arg + - subtitle: Aggregation + desc: | + The User Guide has details on [aggregations in general](../../../guide/aggregation.qmd). + + ::: {.callout-important} + It is important to remember that aggregations are partitioned by entity and windowed, with the default behavior being cumulative up to the current time. + ::: + contents: + - Timestream.collect + - Timestream.count + - Timestream.count_if + - Timestream.first + - Timestream.last + - Timestream.max + - Timestream.mean + - Timestream.min + - Timestream.stddev + - Timestream.sum + - Timestream.variance + - subtitle: Arithmetic + desc: | + Timestreams support a variety of arithmetic operations. + + ::: {.callout-important} + In addition to the chainable methods, standard operators are implemented where appropriate. + For instance, `a.add(b)` may be written as `a + b`. + See the notes on the specific functions for more information. + ::: + contents: + - Timestream.add + - Timestream.ceil + - Timestream.clamp + - Timestream.div + - Timestream.exp + - Timestream.floor + - Timestream.greatest + - Timestream.least + - Timestream.mul + - Timestream.neg + - Timestream.powf + - Timestream.round + - Timestream.sqrt + - Timestream.sub + - subtitle: Collection + desc: | + Timestreams allow each point to contain a collection -- a `list` or `map` -- of elements. + contents: + - Timestream.__getitem__ + - Timestream.flatten + - Timestream.index + - Timestream.length + - Timestream.union + - subtitle: Comparison + desc: | + Comparison operations produce boolean Timestreams. + + ::: {.callout-important} + In addition to the chainable methods, standard operators are implemented where appropriate. + For instance, `a.ge(b)` may be written as `a >= b`. + See the notes on the specific functions for more information. + + To respect the semantics of `__eq__` and `__ne__`, `a == b` and `a != b` are *not* overloaded. + ::: + contents: + - Timestream.eq + - Timestream.ge + - Timestream.gt + - Timestream.le + - Timestream.lt + - Timestream.ne + - Timestream.is_null + - Timestream.is_not_null + - subtitle: Execution + contents: + - Timestream.preview + - Timestream.to_pandas + - Timestream.run_iter + - Timestream.write + - subtitle: Grouping + contents: + - Timestream.lookup + - Timestream.with_key + - subtitle: Logical + contents: + - Timestream.and_ + - Timestream.or_ + - Timestream.not_ + - subtitle: Misc + contents: + - Timestream.cast + - Timestream.coalesce + - Timestream.else_ + - Timestream.filter + - Timestream.hash + - Timestream.if_ + - Timestream.lag + - Timestream.null_if + - Timestream.pipe + - subtitle: Records + desc: | + Record operations create, extract or manipulate Timestreams of records. + contents: + - Timestream.col + - Timestream.select + - Timestream.remove + - Timestream.extend + - Timestream.record + - record + - subtitle: String + contents: + - Timestream.lower + - Timestream.upper + - subtitle: Time + contents: + - Timestream.shift_by + - Timestream.shift_to + - Timestream.shift_until + - Timestream.time + - Timestream.seconds_since + - Timestream.seconds_since_previous + - title: Windows + package: kaskada.windows + options: + children: embedded + contents: + - Window + - Since + - Sliding + - Trailing + - Tumbling + - title: Sources + package: kaskada.sources + options: + children: embedded + contents: + # - Source + - CsvString + - JsonlString + - Pandas + - Parquet + - PyDict + # - package: kaskada.sources.source + # name: TimeUnit + - subtitle: Source + package: kaskada.sources + options: + children: flat + contents: + - Source + - source.TimeUnit + - title: Destinations + package: kaskada.destinations + options: + children: embedded + contents: + - Destination + - title: Execution + options: + children: embedded + contents: + - Execution + - ResultIterator + - title: Results + package: kaskada.results + options: + children: embedded + contents: + - History + - Snapshot \ No newline at end of file diff --git a/python/docs/_scripts/builder.py b/python/docs/_scripts/builder.py new file mode 100644 index 000000000..f2e4055b5 --- /dev/null +++ b/python/docs/_scripts/builder.py @@ -0,0 +1,282 @@ +from __future__ import annotations + +import logging +import sys + +from pathlib import Path +from pydantic import ValidationError + +from quartodoc.inventory import create_inventory, convert_inventory +from quartodoc import layout, preview, blueprint, collect +from quartodoc.validation import fmt + +from typing import Any, Union + +from renderer import Renderer +from summarizer import Summarizer + + +_log = logging.getLogger("quartodoc") + + +class Builder: + """Base class for building API docs. + + Parameters + ---------- + package: str + The name of the package. + sections: ConfigSection + A list of sections, with items to document. + dir: + Name of API directory. + title: + Title of the API index page. + options: + Default options to set for all pieces of content (e.g. include_attributes). + rewrite_all_pages: + Whether to rewrite all rendered doc pages, or only those with changes. + source_dir: + A directory where source files to be documented live. This is only necessary + if you are not documenting a package, but collection of scripts. Use a "." + to refer to the current directory. + dynamic: + Whether to dynamically load all python objects. By default, objects are + loaded using static analysis. + parser: + Docstring parser to use. This correspond to different docstring styles, + and can be one of "google", "sphinx", and "numpy". Defaults to "numpy". + + """ + + # misc config + out_inventory: str = "objects.json" + out_index: str = "index.qmd" + out_page_suffix = ".qmd" + + package: str + dir: str + title: str + + page_map: {str: layout.Page} + item_map: {str: layout.Item} + items: [layout.Item] + + blueprint: layout.Layout + + def __init__( + self, + package: str, + sections: "list[Any]" = tuple(), + dir: str = "reference", + title: str = "Function reference", + options: "dict | None" = None, + rewrite_all_pages=False, + source_dir: "str | None" = None, + dynamic: bool | None = None, + parser="google", + ): + self.layout = self.load_layout( + sections=sections, package=package, options=options + ) + + self.package = package + self.dir = dir + self.title = title + self.rewrite_all_pages = rewrite_all_pages + self.renderer = Renderer() + self.summarizer = Summarizer() + + if source_dir: + self.source_dir = str(Path(source_dir).absolute()) + sys.path.append(self.source_dir) + + self.blueprint = blueprint(self.layout, dynamic=dynamic, parser=parser) + + pages, items = collect(self.blueprint, base_dir=self.dir) + + self.page_map = {} + for page in pages: + self.page_map[page.path] = page + + self.items = [] + self.item_map = {} + for item in items: + self.item_map[item.name] = item + + def load_layout(self, sections: dict, package: str, options=None): + # TODO: currently returning the list of sections, to make work with + # previous code. We should make Layout a first-class citizen of the + # process. + try: + return layout.Layout(sections=sections, package=package, options=options) + except ValidationError as e: + msg = "Configuration error for YAML:\n - " + errors = [fmt(err) for err in e.errors() if fmt(err)] + first_error = errors[ + 0 + ] # we only want to show one error at a time b/c it is confusing otherwise + msg += first_error + raise ValueError(msg) from None + + # building ---------------------------------------------------------------- + + def build(self): + """Build index page, sphinx inventory, and individual doc pages.""" + + # writing pages ---- + + _log.info("Writing pages") + self.write_pages() + + # inventory ---- + + _log.info("Creating inventory file") + inv = create_inventory(self.package, "0.0.9999", self.items) + convert_inventory(inv, self.out_inventory) + + def get_package(self, item: Union[layout.Section, layout.Page]) -> str: + if item.package and f'{item.package}' != "": + return item.package + else: + return self.package + + def write_pages(self): + root = layout.Section( + title=self.title, + desc="This is the API Reference", + ) + + root_text = self.renderer.render(root) + root_path = Path(self.dir) / self.out_index + self.write_page_if_not_exists(root_path, root_text) + + last_title = None + order = 1 + + for section in self.blueprint.sections: + if section.title: + last_title = section.title + section_text = self.renderer.render(section, order=order) + order += 1 + location = Path(self.dir) / section.title + elif section.subtitle: + section_text = self.renderer.render(section) + location = Path(self.dir) / last_title / section.subtitle + + section_path = location / self.out_index + self.write_page_if_not_exists(section_path, section_text) + + is_flat = section.options and section.options.children == layout.ChoicesChildren.flat + + for page in section.contents: + if isinstance(page, layout.Page): + # don't make separate pages for flat sections + if not is_flat: + _log.info(f"Rendering {page.path}") + # preview(page, max_depth=4) + page_text = self.renderer.render(page) + page_path = location / (page.path + self.out_page_suffix) + self.write_page_if_not_exists(page_path, page_text) + if page.path in self.page_map: + del self.page_map[page.path] + + self.update_page_items(page, location, is_flat) + else: + raise NotImplementedError(f"Unsupported section item: {type(page)}") + + if len(self.page_map.keys()) > 0: + _log.warning(f'Extra pages: {self.page_map.keys()}') + _log.error(f'Linking between pages may not work properly. Fix the issue and try again') + + if len(self.item_map.keys()) > 0: + _log.warning(f'Extra items: {self.item_map.keys()}') + _log.error(f'Linking between pages may not work properly. Fix the issue and try again') + + def update_page_items(self, page: layout.Page, location: Path, is_flat: bool): + for doc in page.contents: + if isinstance(doc, layout.Doc): + page_path = f'{location}/index.html' if is_flat else f'{location}/{page.path}.html' + self.update_items(doc, page_path) + else: + raise NotImplementedError(f"Unsupported page item: {type(doc)}") + + def update_items(self, doc: layout.Doc, page_path: str): + name = doc.obj.path + uri = f'{page_path}#{doc.anchor}' + + # item corresponding to the specified path ---- + # e.g. this might be a top-level import + if name in self.item_map: + item = self.item_map[name] + item.uri = uri + del self.item_map[name] + else: + item = layout.Item(uri=uri, name=name, obj=doc.obj, dispname=None) + _log.warning(f'Missing item, adding it: {item}') + self.items.append(item) + + canonical_path = doc.obj.canonical_path + if name != canonical_path: + # item corresponding to the canonical path ---- + # this is where the object is defined (which may be deep in a submodule) + if canonical_path in self.item_map: + item = self.item_map[canonical_path] + item.uri = uri + del self.item_map[canonical_path] + else: + item = layout.Item(uri=uri, name=canonical_path, obj=doc.obj, dispname=name) + _log.warning(f'Missing item, adding it: {item}') + self.items.append(item) + + # recurse in 😊 + if isinstance(doc, layout.DocClass): + for member in doc.members: + self.update_items(member, page_path) + + def write_index_old(self, bp: layout.Layout): + """Write API index page.""" + + _log.info("Summarizing docs for index page.") + content = self.summarizer.summarize(bp) + _log.info(f"Writing index to directory: {self.dir}") + + final = f"# {self.title}\n\n{content}" + + p_index = Path(self.dir) / self.out_index + p_index.parent.mkdir(exist_ok=True, parents=True) + p_index.write_text(final) + + return str(p_index) + + def write_page_if_not_exists(self, path: Path, content): + if ( + self.rewrite_all_pages + or (not path.exists()) + or (path.read_text() != content) + ): + _log.info(f"Writing: {path}") + path.parent.mkdir(exist_ok=True, parents=True) + path.write_text(content) + else: + _log.info("Skipping write (content unchanged)") + + # constructors ---- + + @classmethod + def from_quarto_config(cls, quarto_cfg: "str | dict"): + """Construct a Builder from a configuration object (or yaml file).""" + + # TODO: validation / config model loading + if isinstance(quarto_cfg, str): + import yaml + + quarto_cfg = yaml.safe_load(open(quarto_cfg)) + + cfg = quarto_cfg.get("quartodoc") + if cfg is None: + raise KeyError("No `quartodoc:` section found in your _quarto.yml.") + + return Builder( + **{k: v for k, v in cfg.items()}, + ) diff --git a/python/docs/_scripts/gen_reference.py b/python/docs/_scripts/gen_reference.py new file mode 100644 index 000000000..8141ee44d --- /dev/null +++ b/python/docs/_scripts/gen_reference.py @@ -0,0 +1,20 @@ +import logging +import sys + +from builder import Builder + + +if __name__ == "__main__": + root = logging.getLogger("quartodoc") + root.setLevel(logging.INFO) + + handler = logging.StreamHandler(sys.stdout) + handler.setLevel(logging.INFO) + formatter = logging.Formatter( + "%(asctime)s - %(name)s - %(levelname)s - %(message)s" + ) + handler.setFormatter(formatter) + root.addHandler(handler) + + b = Builder.from_quarto_config("_reference.yml") + b.build() diff --git a/python/docs/_scripts/renderer.py b/python/docs/_scripts/renderer.py new file mode 100644 index 000000000..2298ece9a --- /dev/null +++ b/python/docs/_scripts/renderer.py @@ -0,0 +1,483 @@ +from __future__ import annotations + +import quartodoc.ast as qast + +from griffe.docstrings import dataclasses as ds +from griffe import dataclasses as dc +from tabulate import tabulate +from plum import dispatch +from typing import Union, Optional +from quartodoc import layout + +from summarizer import Summarizer + +try: + # Name and Expression were moved to expressions in v0.28 + from griffe import expressions as expr +except ImportError: + from griffe import dataclasses as expr + +skip_annotation_types = [ + "kaskada", + "kaskada.destinations", + "kaskada.results", + "kaskada.windows", + "pyarrow", +] + + +def _has_attr_section(el: dc.Docstring | None): + if el is None: + return False + + return any([isinstance(x, ds.DocstringSectionAttributes) for x in el.parsed]) + + +def escape(val: str): + return f"`{val}`" + + +def sanitize(val: str, allow_markdown=False): + # sanitize common tokens that break tables + res = val.replace("\n", " ").replace("|", "\\|") + + # sanitize elements that can get interpreted as markdown links + # or citations + if not allow_markdown: + return res.replace("[", "\\[").replace("]", "\\]") + + return res + + +class Renderer(): + """Render docstrings to markdown.""" + + summarizer = Summarizer() + + def _get_display_name(self, el: "dc.Alias | dc.Object"): + parts = el.path.split(".")[1:] + name = parts.pop() + prefix = ".".join(parts) + display_name = f"**{prefix}.**[**{name}**]{{.red}}" + + if isinstance(el, dc.Object): + if 'staticmethod' in el.labels: + display_name = "***static*** " + display_name + + text = [display_name] + + # if isinstance(el, dc.Object) and el.kind == dc.Kind.CLASS: + # text.append(f"Bases: []({el.parent.name})") + + return "\n\n".join(text) + + def _fetch_method_parameters(self, el: dc.Function): + if el.parent and el.parent.is_class and len(el.parameters) > 0: + if el.parameters[0].name in {"self", "cls"}: + return dc.Parameters(*list(el.parameters)[1:]) + + return el.parameters + + def _render_definition_list(self, title: str, items: [str], title_class: Optional[str] = None) -> str: + rows = [title] + for item in items: + if len(rows) == 1: + rows.append(f'~ {item}') + else: + rows.append(f' {item}') + if title_class: + rows.insert(0, f':::{{.{title_class}}}') + rows.append(':::') + return "\n" + "\n".join(rows) + + def _render_header(self, title: str, order: Optional[int] = None) -> str: + text = ["---"] + text.append(f'title: {title}') + if order: + text.append(f'order: {order}') + text.append("---") + return "\n".join(text) + + def _render_table(self, rows, headers): + table = tabulate(rows, headers=headers, tablefmt="github") + + return table + + # render_annotation method -------------------------------------------------------- + + @dispatch + def render_annotation(self, el: str) -> str: + return sanitize(el) + + @dispatch + def render_annotation(self, el: None) -> str: + return "" + + @dispatch + def render_annotation(self, el: expr.Name) -> str: + if el.full not in skip_annotation_types: + return f"[{sanitize(el.source)}](`{el.full}`)" + return "" + + @dispatch + def render_annotation(self, el: expr.Expression) -> str: + text = "".join(map(self.render_annotation, el)) + return text.lstrip(".") + + # signature method -------------------------------------------------------- + + @dispatch + def signature(self, el: layout.Doc): + return self.signature(el.obj) + + @dispatch + def signature(self, el: dc.Alias, source: Optional[dc.Alias] = None): + """Return a string representation of an object's signature.""" + return self.signature(el.target, el) + + @dispatch + def signature(self, el: dc.Function, source: Optional[dc.Alias] = None) -> str: + name = self._get_display_name(source or el) + pars = self.render(self._fetch_method_parameters(el)) + return f"{name}([{pars}]{{.bold-italic}})" + + @dispatch + def signature(self, el: dc.Class, source: Optional[dc.Alias] = None) -> str: + name = self._get_display_name(source or el) + return f"***class*** {name}" + + @dispatch + def signature( + self, el: Union[dc.Module, dc.Attribute], source: Optional[dc.Alias] = None + ): + name = self._get_display_name(source or el) + return f"`{name}`" + + # render method ----------------------------------------------------------- + + @dispatch + def render(self, el): + """Return a string representation of an object, or layout element.""" + + raise NotImplementedError(f"Unsupported type: {type(el)}") + + @dispatch + def render(self, el: str): + return el + + # render layouts ========================================================== + + @dispatch + def render(self, el: layout.Section, order: Optional[int] = None) -> str: + rows = [self._render_header(el.title or el.subtitle, order=order)] + + if el.desc: + rows.append(el.desc) + + if el.options and el.options.children == layout.ChoicesChildren.flat: + for page in el.contents: + rows.append(self.render(page, is_flat=True)) + text = "\n\n".join(rows) + else: + text = "\n\n".join(rows) + text += "\n\n" + self.summarizer.summarize(el.contents) + + return text + + @dispatch + def render(self, el: layout.Page, is_flat: bool = False): + rows = [] + if el.summary: + if el.summary.name: + if is_flat: + rows.append(f'## {el.summary.name}') + else: + rows.append(self._render_header(el.summary.name)) + if el.summary.desc: + rows.append(sanitize(el.summary.desc, allow_markdown=True)) + + for item in el.contents: + rows.append(self.render(item, is_flat=is_flat)) + + return "\n\n".join(rows) + + @dispatch + def render(self, el: layout.Doc): + raise NotImplementedError(f"Unsupported Doc type: {type(el)}") + + @dispatch + def render(self, el: Union[layout.DocClass, layout.DocModule], is_flat: bool = False) -> str: + title = "" if is_flat else self._render_header(el.name) + + sig = self.signature(el) + body_rows = self.render(el.obj).split("\n") + + if el.members: + # add attributes + # skip if docstring has an attributes section + raw_attrs = [x for x in el.members if x.obj.is_attribute] + if raw_attrs and not _has_attr_section(el.obj.docstring): + attr_rows = map(self.render, raw_attrs) + attr_text = self._render_definition_list( + "Attributes:", attr_rows, title_class="highlight") + body_rows.extend(attr_text.split("\n")) + + # add classes + for raw_class in el.members: + if raw_class.obj.is_class and isinstance(raw_class, layout.Doc): + body_rows.extend(self.render(raw_class, is_flat=True).split("\n")) + + # add methods + for raw_method in el.members: + if raw_method.obj.is_function and isinstance(raw_method, layout.Doc): + body_rows.extend(self.render(raw_method, is_flat=True).split("\n")) + + text = self._render_definition_list(sig, body_rows) + + return "\n\n".join([title, text]) + + @dispatch + def render(self, el: layout.DocFunction, is_flat: bool = False): + title = "" if is_flat else self._render_header(el.name) + + sig = self.signature(el) + body_rows = self.render(el.obj).split("\n") + text = self._render_definition_list(sig, body_rows) + + return "\n\n".join([title, text]) + + @dispatch + def render(self, el: layout.DocAttribute, is_flat: bool = False): + link = f"[{el.name}](#{el.anchor})" + description = self.summarizer.summarize(el.obj) + + return " -- ".join([link, description]) + + # render griffe objects =================================================== + + @dispatch + def render(self, el: Union[dc.Object, dc.Alias]): + """Render high level objects representing functions, classes, etc..""" + + str_body = [] + if el.docstring is None: + pass + else: + patched_sections = qast.transform(el.docstring.parsed) + for section in patched_sections: + str_body.append(self.render(section)) + + parts = [*str_body] + + return "\n\n".join(parts) + + # signature parts ------------------------------------------------------------- + + @dispatch + def render(self, el: dc.Parameters): + # index for switch from positional to kw args (via an unnamed *) + try: + kw_only = [par.kind for par in el].index(dc.ParameterKind.keyword_only) + except ValueError: + kw_only = None + + # index for final positionly only args (via /) + try: + pos_only = max( + [ + ii + for ii, el in enumerate(el) + if el.kind == dc.ParameterKind.positional_only + ] + ) + except ValueError: + pos_only = None + + pars = list(map(self.render, el)) + + # insert a single `*,` argument to represent the shift to kw only arguments, + # only if the shift to kw_only was not triggered by *args (var_positional) + if ( + kw_only is not None + and kw_only > 0 + and el[kw_only - 1].kind != dc.ParameterKind.var_positional + ): + pars.insert(kw_only, sanitize("*")) + + # insert a single `/, ` argument to represent shift from positional only arguments + # note that this must come before a single *, so it's okay that both this + # and block above insert into pars + if pos_only is not None: + pars.insert(pos_only + 1, sanitize("/")) + + return ", ".join(pars) + + @dispatch + def render(self, el: dc.Parameter): + splats = {dc.ParameterKind.var_keyword, dc.ParameterKind.var_positional} + has_default = el.default and el.kind not in splats + + if el.kind == dc.ParameterKind.var_keyword: + glob = "**" + elif el.kind == dc.ParameterKind.var_positional: + glob = "*" + else: + glob = "" + + name = sanitize(el.name) + + if has_default: + res = f"{glob}{name}={el.default}" + else: + res = f"{glob}{name}" + return res + + # docstring parts ------------------------------------------------------------- + + # text ---- + # note this can be a number of things. for example, opening docstring text, + # or a section with a header not included in the numpydoc standard + @dispatch + def render(self, el: ds.DocstringSectionText): + new_el = qast.transform(el) + if isinstance(new_el, ds.DocstringSectionText): + # ensures we don't recurse forever + return el.value + + return self.render(new_el) + + # parameters ---- + + @dispatch + def render(self, el: ds.DocstringSectionParameters): + # if more than one param, render as un-ordered list + prefix = "* " if len(el.value) > 1 else "" + follow = " " if len(el.value) > 1 else "" + + rows = [] + for param in el.value: + name = sanitize(param.name) + anno = self.render_annotation(param.annotation) + default = f', default: {escape(param.default)}' if param.default else "" + + rows.append(f'{prefix}**{name}** ({anno}{default})') + rows.append("") + for row in param.description.split("\n"): + rows.append(f'{follow}{row}') + rows.append("") + + return self._render_definition_list("Parameters:", rows, title_class="highlight") + + # attributes ---- + + @dispatch + def render(self, el: ds.DocstringSectionAttributes): + # if more than one param, render as un-ordered list + prefix = "* " if len(el.value) > 1 else "" + follow = " " if len(el.value) > 1 else "" + + rows = [] + for attr in el.value: + name = sanitize(attr.name) + anno = self.render_annotation(attr.annotation) + rows.append(f'{prefix}**{name}** ({anno})') + rows.append("") + for row in attr.description.split("\n"): + rows.append(f'{follow}{row}') + rows.append("") + + return self._render_definition_list("Attributes:", rows, title_class="highlight") + + # examples ---- + + @dispatch + def render(self, el: ds.DocstringSectionExamples): + # its value is a tuple: DocstringSectionKind["text" | "examples"], str + data = map(qast.transform, el.value) + return "\n\n".join(list(map(self.render, data))) + + @dispatch + def render(self, el: qast.ExampleCode): + return f"""```python +{el.value} +```""" + + @dispatch + def render(self, el: qast.ExampleText): + return el.value + + # returns ---- + + @dispatch + def render(self, el: ds.DocstringSectionReturns): + # if more than one param, render as un-ordered list + prefix = "* " if len(el.value) > 1 else "" + follow = " " if len(el.value) > 1 else "" + + rows = [] + for item in el.value: + title = prefix + name = sanitize(item.name) + if name: + title += f'**{name}**' + + return_type = self.render_annotation(item.annotation) + if return_type: + title += return_type + + if title != prefix: + rows.append(title) + + if item.description: + rows.append("") + for row in item.description.split("\n"): + rows.append(f'{follow}{row}') + rows.append("") + + return self._render_definition_list("Returns:", rows, title_class="highlight") + + @dispatch + def render(self, el: ds.DocstringSectionRaises): + # if more than one param, render as un-ordered list + prefix = "* " if len(el.value) > 1 else "" + follow = " " if len(el.value) > 1 else "" + + rows = [] + for item in el.value: + # name = sanitize(item.name) + anno = self.render_annotation(item.annotation) + rows.append(f'{prefix}{anno}') + rows.append("") + for row in item.description.split("\n"): + rows.append(f'{follow}{row}') + rows.append("") + + return self._render_definition_list("Raises:", rows, title_class="highlight") + + @dispatch + def render(self, el: ds.DocstringSectionAdmonition) -> str: + rows = [] + if el.title.lower().startswith("note"): + rows.append(f'::: {{.callout-note title="{el.title}"}}') + elif el.title.lower().startswith("warn"): + rows.append(f'::: {{.callout-warning title="{el.title}"}}') + else: + rows.append(f'::: {{.callout-tip title="{el.title}"}}') + + rows.append(el.value.description) + rows.append(':::') + + return "\n".join(rows) + + # unsupported parts ---- + + @dispatch.multi( + (ds.DocstringAdmonition,), + (ds.DocstringDeprecated,), + (ds.DocstringWarn,), + (ds.DocstringYield,), + (ds.DocstringReceive,), + (ds.DocstringAttribute,), + ) + def render(self, el): + raise NotImplementedError(f"{type(el)}") diff --git a/python/docs/_scripts/summarizer.py b/python/docs/_scripts/summarizer.py new file mode 100644 index 000000000..cf643dbd4 --- /dev/null +++ b/python/docs/_scripts/summarizer.py @@ -0,0 +1,117 @@ +from __future__ import annotations + +from griffe.docstrings import dataclasses as ds +from griffe import dataclasses as dc +from plum import dispatch +from typing import Union, Optional +from quartodoc import layout + + +class Summarizer(): + """Summarize docstrings to markdown.""" + + @staticmethod + def _summary_row(link, description): + return f"| {link} | {description} |" + + @dispatch + def summarize(self, el): + raise NotImplementedError(f"Unsupported type: {type(el)}") + + @dispatch + def summarize(self, el: layout.Layout): + rendered_sections = list(map(self.summarize, el.sections)) + return "\n\n".join(rendered_sections) + + @dispatch + def summarize(self, el: layout.Section): + desc = f"\n\n{el.desc}" if el.desc is not None else "" + if el.title is not None: + header = f"## {el.title}{desc}" + elif el.subtitle is not None: + header = f"### {el.subtitle}{desc}" + else: + header = "" + + if el.contents: + return f"{header}\n\n{self.summarize(el.contents)}" + + return header + + @dispatch + def summarize(self, contents: layout.ContentList): + thead = "| | |\n| --- | --- |" + + rendered = [] + for child in contents: + rendered.append(self.summarize(child)) + + return "\n".join([thead, *rendered]) + + @dispatch + def summarize(self, el: layout.Page): + if el.summary is not None: + # TODO: assumes that files end with .qmd + return self._summary_row( + f"[{el.summary.name}]({el.path}.qmd)", el.summary.desc + ) + + if len(el.contents) > 1 and not el.flatten: + raise ValueError( + "Cannot summarize Page. Either set its `summary` attribute with name " + "and description details, or set `flatten` to True." + ) + + else: + rows = [self.summarize(entry, el.path) for entry in el.contents] + return "\n".join(rows) + + @dispatch + def summarize(self, el: layout.MemberPage): + # TODO: model should validate these only have a single entry + return self.summarize(el.contents[0], el.path, shorten=True) + + @dispatch + def summarize(self, el: layout.Interlaced, *args, **kwargs): + rows = [self.summarize(doc, *args, **kwargs) for doc in el.contents] + + return "\n".join(rows) + + @dispatch + def summarize( + self, el: layout.Doc, path: Optional[str] = None, shorten: bool = False + ): + # this is where summary page method links are created + if path is None: + link = f"[{el.name}](#{el.anchor})" + else: + # TODO: assumes that files end with .qmd + link = f"[{el.name}]({path}.qmd#{el.anchor})" + + description = self.summarize(el.obj) + return self._summary_row(link, description) + + @dispatch + def summarize(self, el: layout.Link): + description = self.summarize(el.obj) + return self._summary_row(f"[](`{el.name}`)", description) + + @dispatch + def summarize(self, obj: Union[dc.Object, dc.Alias]) -> str: + """Test""" + # get high-level description + doc = obj.docstring + if doc is None: + docstring_parts = [] + else: + docstring_parts = doc.parsed + + if len(docstring_parts) and isinstance( + docstring_parts[0], ds.DocstringSectionText + ): + description = docstring_parts[0].value + short = description.split("\n")[0] + + return short + + return "" diff --git a/python/docs/_static/css/design-style.css b/python/docs/_static/css/design-style.css new file mode 100644 index 000000000..d8fce0a7a --- /dev/null +++ b/python/docs/_static/css/design-style.css @@ -0,0 +1,3183 @@ +.sd-bg-primary { + background-color: var(--sd-color-primary) !important +} + +.sd-bg-text-primary { + color: var(--sd-color-primary-text) !important +} + +button.sd-bg-primary:focus,button.sd-bg-primary:hover { + background-color: var(--sd-color-primary-highlight) !important +} + +a.sd-bg-primary:focus,a.sd-bg-primary:hover { + background-color: var(--sd-color-primary-highlight) !important +} + +.sd-bg-secondary { + background-color: var(--sd-color-secondary) !important +} + +.sd-bg-text-secondary { + color: var(--sd-color-secondary-text) !important +} + +button.sd-bg-secondary:focus,button.sd-bg-secondary:hover { + background-color: var(--sd-color-secondary-highlight) !important +} + +a.sd-bg-secondary:focus,a.sd-bg-secondary:hover { + background-color: var(--sd-color-secondary-highlight) !important +} + +.sd-bg-success { + background-color: var(--sd-color-success) !important +} + +.sd-bg-text-success { + color: var(--sd-color-success-text) !important +} + +button.sd-bg-success:focus,button.sd-bg-success:hover { + background-color: var(--sd-color-success-highlight) !important +} + +a.sd-bg-success:focus,a.sd-bg-success:hover { + background-color: var(--sd-color-success-highlight) !important +} + +.sd-bg-info { + background-color: var(--sd-color-info) !important +} + +.sd-bg-text-info { + color: var(--sd-color-info-text) !important +} + +button.sd-bg-info:focus,button.sd-bg-info:hover { + background-color: var(--sd-color-info-highlight) !important +} + +a.sd-bg-info:focus,a.sd-bg-info:hover { + background-color: var(--sd-color-info-highlight) !important +} + +.sd-bg-warning { + background-color: var(--sd-color-warning) !important +} + +.sd-bg-text-warning { + color: var(--sd-color-warning-text) !important +} + +button.sd-bg-warning:focus,button.sd-bg-warning:hover { + background-color: var(--sd-color-warning-highlight) !important +} + +a.sd-bg-warning:focus,a.sd-bg-warning:hover { + background-color: var(--sd-color-warning-highlight) !important +} + +.sd-bg-danger { + background-color: var(--sd-color-danger) !important +} + +.sd-bg-text-danger { + color: var(--sd-color-danger-text) !important +} + +button.sd-bg-danger:focus,button.sd-bg-danger:hover { + background-color: var(--sd-color-danger-highlight) !important +} + +a.sd-bg-danger:focus,a.sd-bg-danger:hover { + background-color: var(--sd-color-danger-highlight) !important +} + +.sd-bg-light { + background-color: var(--sd-color-light) !important +} + +.sd-bg-text-light { + color: var(--sd-color-light-text) !important +} + +button.sd-bg-light:focus,button.sd-bg-light:hover { + background-color: var(--sd-color-light-highlight) !important +} + +a.sd-bg-light:focus,a.sd-bg-light:hover { + background-color: var(--sd-color-light-highlight) !important +} + +.sd-bg-muted { + background-color: var(--sd-color-muted) !important +} + +.sd-bg-text-muted { + color: var(--sd-color-muted-text) !important +} + +button.sd-bg-muted:focus,button.sd-bg-muted:hover { + background-color: var(--sd-color-muted-highlight) !important +} + +a.sd-bg-muted:focus,a.sd-bg-muted:hover { + background-color: var(--sd-color-muted-highlight) !important +} + +.sd-bg-dark { + background-color: var(--sd-color-dark) !important +} + +.sd-bg-text-dark { + color: var(--sd-color-dark-text) !important +} + +button.sd-bg-dark:focus,button.sd-bg-dark:hover { + background-color: var(--sd-color-dark-highlight) !important +} + +a.sd-bg-dark:focus,a.sd-bg-dark:hover { + background-color: var(--sd-color-dark-highlight) !important +} + +.sd-bg-black { + background-color: var(--sd-color-black) !important +} + +.sd-bg-text-black { + color: var(--sd-color-black-text) !important +} + +button.sd-bg-black:focus,button.sd-bg-black:hover { + background-color: var(--sd-color-black-highlight) !important +} + +a.sd-bg-black:focus,a.sd-bg-black:hover { + background-color: var(--sd-color-black-highlight) !important +} + +.sd-bg-white { + background-color: var(--sd-color-white) !important +} + +.sd-bg-text-white { + color: var(--sd-color-white-text) !important +} + +button.sd-bg-white:focus,button.sd-bg-white:hover { + background-color: var(--sd-color-white-highlight) !important +} + +a.sd-bg-white:focus,a.sd-bg-white:hover { + background-color: var(--sd-color-white-highlight) !important +} + +.sd-text-primary,.sd-text-primary>p { + color: var(--sd-color-primary) !important +} + +a.sd-text-primary:focus,a.sd-text-primary:hover { + color: var(--sd-color-primary-highlight) !important +} + +.sd-text-secondary,.sd-text-secondary>p { + color: var(--sd-color-secondary) !important +} + +a.sd-text-secondary:focus,a.sd-text-secondary:hover { + color: var(--sd-color-secondary-highlight) !important +} + +.sd-text-success,.sd-text-success>p { + color: var(--sd-color-success) !important +} + +a.sd-text-success:focus,a.sd-text-success:hover { + color: var(--sd-color-success-highlight) !important +} + +.sd-text-info,.sd-text-info>p { + color: var(--sd-color-info) !important +} + +a.sd-text-info:focus,a.sd-text-info:hover { + color: var(--sd-color-info-highlight) !important +} + +.sd-text-warning,.sd-text-warning>p { + color: var(--sd-color-warning) !important +} + +a.sd-text-warning:focus,a.sd-text-warning:hover { + color: var(--sd-color-warning-highlight) !important +} + +.sd-text-danger,.sd-text-danger>p { + color: var(--sd-color-danger) !important +} + +a.sd-text-danger:focus,a.sd-text-danger:hover { + color: var(--sd-color-danger-highlight) !important +} + +.sd-text-light,.sd-text-light>p { + color: var(--sd-color-light) !important +} + +a.sd-text-light:focus,a.sd-text-light:hover { + color: var(--sd-color-light-highlight) !important +} + +.sd-text-muted,.sd-text-muted>p { + color: var(--sd-color-muted) !important +} + +a.sd-text-muted:focus,a.sd-text-muted:hover { + color: var(--sd-color-muted-highlight) !important +} + +.sd-text-dark,.sd-text-dark>p { + color: var(--sd-color-dark) !important +} + +a.sd-text-dark:focus,a.sd-text-dark:hover { + color: var(--sd-color-dark-highlight) !important +} + +.sd-text-black,.sd-text-black>p { + color: var(--sd-color-black) !important +} + +a.sd-text-black:focus,a.sd-text-black:hover { + color: var(--sd-color-black-highlight) !important +} + +.sd-text-white,.sd-text-white>p { + color: var(--sd-color-white) !important +} + +a.sd-text-white:focus,a.sd-text-white:hover { + color: var(--sd-color-white-highlight) !important +} + +.sd-outline-primary { + border-color: var(--sd-color-primary) !important; + border-style: solid !important; + border-width: 1px !important +} + +a.sd-outline-primary:focus,a.sd-outline-primary:hover { + border-color: var(--sd-color-primary-highlight) !important +} + +.sd-outline-secondary { + border-color: var(--sd-color-secondary) !important; + border-style: solid !important; + border-width: 1px !important +} + +a.sd-outline-secondary:focus,a.sd-outline-secondary:hover { + border-color: var(--sd-color-secondary-highlight) !important +} + +.sd-outline-success { + border-color: var(--sd-color-success) !important; + border-style: solid !important; + border-width: 1px !important +} + +a.sd-outline-success:focus,a.sd-outline-success:hover { + border-color: var(--sd-color-success-highlight) !important +} + +.sd-outline-info { + border-color: var(--sd-color-info) !important; + border-style: solid !important; + border-width: 1px !important +} + +a.sd-outline-info:focus,a.sd-outline-info:hover { + border-color: var(--sd-color-info-highlight) !important +} + +.sd-outline-warning { + border-color: var(--sd-color-warning) !important; + border-style: solid !important; + border-width: 1px !important +} + +a.sd-outline-warning:focus,a.sd-outline-warning:hover { + border-color: var(--sd-color-warning-highlight) !important +} + +.sd-outline-danger { + border-color: var(--sd-color-danger) !important; + border-style: solid !important; + border-width: 1px !important +} + +a.sd-outline-danger:focus,a.sd-outline-danger:hover { + border-color: var(--sd-color-danger-highlight) !important +} + +.sd-outline-light { + border-color: var(--sd-color-light) !important; + border-style: solid !important; + border-width: 1px !important +} + +a.sd-outline-light:focus,a.sd-outline-light:hover { + border-color: var(--sd-color-light-highlight) !important +} + +.sd-outline-muted { + border-color: var(--sd-color-muted) !important; + border-style: solid !important; + border-width: 1px !important +} + +a.sd-outline-muted:focus,a.sd-outline-muted:hover { + border-color: var(--sd-color-muted-highlight) !important +} + +.sd-outline-dark { + border-color: var(--sd-color-dark) !important; + border-style: solid !important; + border-width: 1px !important +} + +a.sd-outline-dark:focus,a.sd-outline-dark:hover { + border-color: var(--sd-color-dark-highlight) !important +} + +.sd-outline-black { + border-color: var(--sd-color-black) !important; + border-style: solid !important; + border-width: 1px !important +} + +a.sd-outline-black:focus,a.sd-outline-black:hover { + border-color: var(--sd-color-black-highlight) !important +} + +.sd-outline-white { + border-color: var(--sd-color-white) !important; + border-style: solid !important; + border-width: 1px !important +} + +a.sd-outline-white:focus,a.sd-outline-white:hover { + border-color: var(--sd-color-white-highlight) !important +} + +.sd-bg-transparent { + background-color: transparent !important +} + +.sd-outline-transparent { + border-color: transparent !important +} + +.sd-text-transparent { + color: transparent !important +} + +.sd-p-0 { + padding: 0 !important +} + +.sd-pt-0,.sd-py-0 { + padding-top: 0 !important +} + +.sd-pr-0,.sd-px-0 { + padding-right: 0 !important +} + +.sd-pb-0,.sd-py-0 { + padding-bottom: 0 !important +} + +.sd-pl-0,.sd-px-0 { + padding-left: 0 !important +} + +.sd-p-1 { + padding: .25rem !important +} + +.sd-pt-1,.sd-py-1 { + padding-top: .25rem !important +} + +.sd-pr-1,.sd-px-1 { + padding-right: .25rem !important +} + +.sd-pb-1,.sd-py-1 { + padding-bottom: .25rem !important +} + +.sd-pl-1,.sd-px-1 { + padding-left: .25rem !important +} + +.sd-p-2 { + padding: .5rem !important +} + +.sd-pt-2,.sd-py-2 { + padding-top: .5rem !important +} + +.sd-pr-2,.sd-px-2 { + padding-right: .5rem !important +} + +.sd-pb-2,.sd-py-2 { + padding-bottom: .5rem !important +} + +.sd-pl-2,.sd-px-2 { + padding-left: .5rem !important +} + +.sd-p-3 { + padding: 1rem !important +} + +.sd-pt-3,.sd-py-3 { + padding-top: 1rem !important +} + +.sd-pr-3,.sd-px-3 { + padding-right: 1rem !important +} + +.sd-pb-3,.sd-py-3 { + padding-bottom: 1rem !important +} + +.sd-pl-3,.sd-px-3 { + padding-left: 1rem !important +} + +.sd-p-4 { + padding: 1.5rem !important +} + +.sd-pt-4,.sd-py-4 { + padding-top: 1.5rem !important +} + +.sd-pr-4,.sd-px-4 { + padding-right: 1.5rem !important +} + +.sd-pb-4,.sd-py-4 { + padding-bottom: 1.5rem !important +} + +.sd-pl-4,.sd-px-4 { + padding-left: 1.5rem !important +} + +.sd-p-5 { + padding: 3rem !important +} + +.sd-pt-5,.sd-py-5 { + padding-top: 3rem !important +} + +.sd-pr-5,.sd-px-5 { + padding-right: 3rem !important +} + +.sd-pb-5,.sd-py-5 { + padding-bottom: 3rem !important +} + +.sd-pl-5,.sd-px-5 { + padding-left: 3rem !important +} + +.sd-m-auto { + margin: auto !important +} + +.sd-mt-auto,.sd-my-auto { + margin-top: auto !important +} + +.sd-mr-auto,.sd-mx-auto { + margin-right: auto !important +} + +.sd-mb-auto,.sd-my-auto { + margin-bottom: auto !important +} + +.sd-ml-auto,.sd-mx-auto { + margin-left: auto !important +} + +.sd-m-0 { + margin: 0 !important +} + +.sd-mt-0,.sd-my-0 { + margin-top: 0 !important +} + +.sd-mr-0,.sd-mx-0 { + margin-right: 0 !important +} + +.sd-mb-0,.sd-my-0 { + margin-bottom: 0 !important +} + +.sd-ml-0,.sd-mx-0 { + margin-left: 0 !important +} + +.sd-m-1 { + margin: .25rem !important +} + +.sd-mt-1,.sd-my-1 { + margin-top: .25rem !important +} + +.sd-mr-1,.sd-mx-1 { + margin-right: .25rem !important +} + +.sd-mb-1,.sd-my-1 { + margin-bottom: .25rem !important +} + +.sd-ml-1,.sd-mx-1 { + margin-left: .25rem !important +} + +.sd-m-2 { + margin: .5rem !important +} + +.sd-mt-2,.sd-my-2 { + margin-top: .5rem !important +} + +.sd-mr-2,.sd-mx-2 { + margin-right: .5rem !important +} + +.sd-mb-2,.sd-my-2 { + margin-bottom: .5rem !important +} + +.sd-ml-2,.sd-mx-2 { + margin-left: .5rem !important +} + +.sd-m-3 { + margin: 1rem !important +} + +.sd-mt-3,.sd-my-3 { + margin-top: 1rem !important +} + +.sd-mr-3,.sd-mx-3 { + margin-right: 1rem !important +} + +.sd-mb-3,.sd-my-3 { + margin-bottom: 1rem !important +} + +.sd-ml-3,.sd-mx-3 { + margin-left: 1rem !important +} + +.sd-m-4 { + margin: 1.5rem !important +} + +.sd-mt-4,.sd-my-4 { + margin-top: 1.5rem !important +} + +.sd-mr-4,.sd-mx-4 { + margin-right: 1.5rem !important +} + +.sd-mb-4,.sd-my-4 { + margin-bottom: 1.5rem !important +} + +.sd-ml-4,.sd-mx-4 { + margin-left: 1.5rem !important +} + +.sd-m-5 { + margin: 3rem !important +} + +.sd-mt-5,.sd-my-5 { + margin-top: 3rem !important +} + +.sd-mr-5,.sd-mx-5 { + margin-right: 3rem !important +} + +.sd-mb-5,.sd-my-5 { + margin-bottom: 3rem !important +} + +.sd-ml-5,.sd-mx-5 { + margin-left: 3rem !important +} + +.sd-w-25 { + width: 25% !important +} + +.sd-w-50 { + width: 50% !important +} + +.sd-w-75 { + width: 75% !important +} + +.sd-w-100 { + width: 100% !important +} + +.sd-w-auto { + width: auto !important +} + +.sd-h-25 { + height: 25% !important +} + +.sd-h-50 { + height: 50% !important +} + +.sd-h-75 { + height: 75% !important +} + +.sd-h-100 { + height: 100% !important +} + +.sd-h-auto { + height: auto !important +} + +.sd-d-none { + display: none !important +} + +.sd-d-inline { + display: inline !important +} + +.sd-d-inline-block { + display: inline-block !important +} + +.sd-d-block { + display: block !important +} + +.sd-d-grid { + display: grid !important +} + +.sd-d-flex-row { + display: -ms-flexbox !important; + display: flex !important; + flex-direction: row !important +} + +.sd-d-flex-column { + display: -ms-flexbox !important; + display: flex !important; + flex-direction: column !important +} + +.sd-d-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important +} + +@media(min-width: 576px) { + .sd-d-sm-none { + display:none !important + } + + .sd-d-sm-inline { + display: inline !important + } + + .sd-d-sm-inline-block { + display: inline-block !important + } + + .sd-d-sm-block { + display: block !important + } + + .sd-d-sm-grid { + display: grid !important + } + + .sd-d-sm-flex { + display: -ms-flexbox !important; + display: flex !important + } + + .sd-d-sm-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important + } +} + +@media(min-width: 768px) { + .sd-d-md-none { + display:none !important + } + + .sd-d-md-inline { + display: inline !important + } + + .sd-d-md-inline-block { + display: inline-block !important + } + + .sd-d-md-block { + display: block !important + } + + .sd-d-md-grid { + display: grid !important + } + + .sd-d-md-flex { + display: -ms-flexbox !important; + display: flex !important + } + + .sd-d-md-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important + } +} + +@media(min-width: 992px) { + .sd-d-lg-none { + display:none !important + } + + .sd-d-lg-inline { + display: inline !important + } + + .sd-d-lg-inline-block { + display: inline-block !important + } + + .sd-d-lg-block { + display: block !important + } + + .sd-d-lg-grid { + display: grid !important + } + + .sd-d-lg-flex { + display: -ms-flexbox !important; + display: flex !important + } + + .sd-d-lg-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important + } +} + +@media(min-width: 1200px) { + .sd-d-xl-none { + display:none !important + } + + .sd-d-xl-inline { + display: inline !important + } + + .sd-d-xl-inline-block { + display: inline-block !important + } + + .sd-d-xl-block { + display: block !important + } + + .sd-d-xl-grid { + display: grid !important + } + + .sd-d-xl-flex { + display: -ms-flexbox !important; + display: flex !important + } + + .sd-d-xl-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important + } +} + +.sd-align-major-start { + justify-content: flex-start !important +} + +.sd-align-major-end { + justify-content: flex-end !important +} + +.sd-align-major-center { + justify-content: center !important +} + +.sd-align-major-justify { + justify-content: space-between !important +} + +.sd-align-major-spaced { + justify-content: space-evenly !important +} + +.sd-align-minor-start { + align-items: flex-start !important +} + +.sd-align-minor-end { + align-items: flex-end !important +} + +.sd-align-minor-center { + align-items: center !important +} + +.sd-align-minor-stretch { + align-items: stretch !important +} + +.sd-text-justify { + text-align: justify !important +} + +.sd-text-left { + text-align: left !important +} + +.sd-text-right { + text-align: right !important +} + +.sd-text-center { + text-align: center !important +} + +.sd-font-weight-light { + font-weight: 300 !important +} + +.sd-font-weight-lighter { + font-weight: lighter !important +} + +.sd-font-weight-normal { + font-weight: 400 !important +} + +.sd-font-weight-bold { + font-weight: 700 !important +} + +.sd-font-weight-bolder { + font-weight: bolder !important +} + +.sd-font-italic { + font-style: italic !important +} + +.sd-text-decoration-none { + text-decoration: none !important +} + +.sd-text-lowercase { + text-transform: lowercase !important +} + +.sd-text-uppercase { + text-transform: uppercase !important +} + +.sd-text-capitalize { + text-transform: capitalize !important +} + +.sd-text-wrap { + white-space: normal !important +} + +.sd-text-nowrap { + white-space: nowrap !important +} + +.sd-text-truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap +} + +.sd-fs-1,.sd-fs-1>p { + font-size: calc(1.375rem + 1.5vw) !important; + line-height: unset !important +} + +.sd-fs-2,.sd-fs-2>p { + font-size: calc(1.325rem + 0.9vw) !important; + line-height: unset !important +} + +.sd-fs-3,.sd-fs-3>p { + font-size: calc(1.3rem + 0.6vw) !important; + line-height: unset !important +} + +.sd-fs-4,.sd-fs-4>p { + font-size: calc(1.275rem + 0.3vw) !important; + line-height: unset !important +} + +.sd-fs-5,.sd-fs-5>p { + font-size: 1.25rem !important; + line-height: unset !important +} + +.sd-fs-6,.sd-fs-6>p { + font-size: 1rem !important; + line-height: unset !important +} + +.sd-border-0 { + border: 0 solid !important +} + +.sd-border-top-0 { + border-top: 0 solid !important +} + +.sd-border-bottom-0 { + border-bottom: 0 solid !important +} + +.sd-border-right-0 { + border-right: 0 solid !important +} + +.sd-border-left-0 { + border-left: 0 solid !important +} + +.sd-border-1 { + border: 1px solid !important +} + +.sd-border-top-1 { + border-top: 1px solid !important +} + +.sd-border-bottom-1 { + border-bottom: 1px solid !important +} + +.sd-border-right-1 { + border-right: 1px solid !important +} + +.sd-border-left-1 { + border-left: 1px solid !important +} + +.sd-border-2 { + border: 2px solid !important +} + +.sd-border-top-2 { + border-top: 2px solid !important +} + +.sd-border-bottom-2 { + border-bottom: 2px solid !important +} + +.sd-border-right-2 { + border-right: 2px solid !important +} + +.sd-border-left-2 { + border-left: 2px solid !important +} + +.sd-border-3 { + border: 3px solid !important +} + +.sd-border-top-3 { + border-top: 3px solid !important +} + +.sd-border-bottom-3 { + border-bottom: 3px solid !important +} + +.sd-border-right-3 { + border-right: 3px solid !important +} + +.sd-border-left-3 { + border-left: 3px solid !important +} + +.sd-border-4 { + border: 4px solid !important +} + +.sd-border-top-4 { + border-top: 4px solid !important +} + +.sd-border-bottom-4 { + border-bottom: 4px solid !important +} + +.sd-border-right-4 { + border-right: 4px solid !important +} + +.sd-border-left-4 { + border-left: 4px solid !important +} + +.sd-border-5 { + border: 5px solid !important +} + +.sd-border-top-5 { + border-top: 5px solid !important +} + +.sd-border-bottom-5 { + border-bottom: 5px solid !important +} + +.sd-border-right-5 { + border-right: 5px solid !important +} + +.sd-border-left-5 { + border-left: 5px solid !important +} + +.sd-rounded-0 { + border-radius: 0 !important +} + +.sd-rounded-1 { + border-radius: .2rem !important +} + +.sd-rounded-2 { + border-radius: .3rem !important +} + +.sd-rounded-3 { + border-radius: .5rem !important +} + +.sd-rounded-pill { + border-radius: 50rem !important +} + +.sd-rounded-circle { + border-radius: 50% !important +} + +.shadow-none { + box-shadow: none !important +} + +.sd-shadow-sm { + box-shadow: 0 .125rem .25rem var(--sd-color-shadow) !important +} + +.sd-shadow-md { + box-shadow: 0 .5rem 1rem var(--sd-color-shadow) !important +} + +.sd-shadow-lg { + box-shadow: 0 1rem 3rem var(--sd-color-shadow) !important +} + +@keyframes sd-slide-from-left { + 0% { + transform: translateX(-100%) + } + + 100% { + transform: translateX(0) + } +} + +@keyframes sd-slide-from-right { + 0% { + transform: translateX(200%) + } + + 100% { + transform: translateX(0) + } +} + +@keyframes sd-grow100 { + 0% { + transform: scale(0); + opacity: .5 + } + + 100% { + transform: scale(1); + opacity: 1 + } +} + +@keyframes sd-grow50 { + 0% { + transform: scale(0.5); + opacity: .5 + } + + 100% { + transform: scale(1); + opacity: 1 + } +} + +@keyframes sd-grow50-rot20 { + 0% { + transform: scale(0.5) rotateZ(-20deg); + opacity: .5 + } + + 75% { + transform: scale(1) rotateZ(5deg); + opacity: 1 + } + + 95% { + transform: scale(1) rotateZ(-1deg); + opacity: 1 + } + + 100% { + transform: scale(1) rotateZ(0); + opacity: 1 + } +} + +.sd-animate-slide-from-left { + animation: 1s ease-out 0s 1 normal none running sd-slide-from-left +} + +.sd-animate-slide-from-right { + animation: 1s ease-out 0s 1 normal none running sd-slide-from-right +} + +.sd-animate-grow100 { + animation: 1s ease-out 0s 1 normal none running sd-grow100 +} + +.sd-animate-grow50 { + animation: 1s ease-out 0s 1 normal none running sd-grow50 +} + +.sd-animate-grow50-rot20 { + animation: 1s ease-out 0s 1 normal none running sd-grow50-rot20 +} + +.sd-badge { + display: inline-block; + padding: .35em .65em; + font-size: .75em; + font-weight: 700; + line-height: 1; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25rem +} + +.sd-badge:empty { + display: none +} + +a.sd-badge { + text-decoration: none +} + +.sd-btn .sd-badge { + position: relative; + top: -1px +} + +.sd-btn { + background-color: transparent; + border: 1px solid transparent; + border-radius: .25rem; + cursor: pointer; + display: inline-block; + font-weight: 400; + font-size: 1rem; + line-height: 1.5; + padding: .375rem .75rem; + text-align: center; + text-decoration: none; + transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out; + vertical-align: middle; + user-select: none; + -moz-user-select: none; + -ms-user-select: none; + -webkit-user-select: none +} + +.sd-btn:hover { + text-decoration: none +} + +@media(prefers-reduced-motion: reduce) { + .sd-btn { + transition: none + } +} + +.sd-btn-primary,.sd-btn-outline-primary:hover,.sd-btn-outline-primary:focus { + color: var(--sd-color-primary-text) !important; + background-color: var(--sd-color-primary) !important; + border-color: var(--sd-color-primary) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-primary:hover,.sd-btn-primary:focus { + color: var(--sd-color-primary-text) !important; + background-color: var(--sd-color-primary-highlight) !important; + border-color: var(--sd-color-primary-highlight) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-outline-primary { + color: var(--sd-color-primary) !important; + border-color: var(--sd-color-primary) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-secondary,.sd-btn-outline-secondary:hover,.sd-btn-outline-secondary:focus { + color: var(--sd-color-secondary-text) !important; + background-color: var(--sd-color-secondary) !important; + border-color: var(--sd-color-secondary) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-secondary:hover,.sd-btn-secondary:focus { + color: var(--sd-color-secondary-text) !important; + background-color: var(--sd-color-secondary-highlight) !important; + border-color: var(--sd-color-secondary-highlight) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-outline-secondary { + color: var(--sd-color-secondary) !important; + border-color: var(--sd-color-secondary) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-success,.sd-btn-outline-success:hover,.sd-btn-outline-success:focus { + color: var(--sd-color-success-text) !important; + background-color: var(--sd-color-success) !important; + border-color: var(--sd-color-success) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-success:hover,.sd-btn-success:focus { + color: var(--sd-color-success-text) !important; + background-color: var(--sd-color-success-highlight) !important; + border-color: var(--sd-color-success-highlight) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-outline-success { + color: var(--sd-color-success) !important; + border-color: var(--sd-color-success) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-info,.sd-btn-outline-info:hover,.sd-btn-outline-info:focus { + color: var(--sd-color-info-text) !important; + background-color: var(--sd-color-info) !important; + border-color: var(--sd-color-info) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-info:hover,.sd-btn-info:focus { + color: var(--sd-color-info-text) !important; + background-color: var(--sd-color-info-highlight) !important; + border-color: var(--sd-color-info-highlight) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-outline-info { + color: var(--sd-color-info) !important; + border-color: var(--sd-color-info) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-warning,.sd-btn-outline-warning:hover,.sd-btn-outline-warning:focus { + color: var(--sd-color-warning-text) !important; + background-color: var(--sd-color-warning) !important; + border-color: var(--sd-color-warning) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-warning:hover,.sd-btn-warning:focus { + color: var(--sd-color-warning-text) !important; + background-color: var(--sd-color-warning-highlight) !important; + border-color: var(--sd-color-warning-highlight) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-outline-warning { + color: var(--sd-color-warning) !important; + border-color: var(--sd-color-warning) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-danger,.sd-btn-outline-danger:hover,.sd-btn-outline-danger:focus { + color: var(--sd-color-danger-text) !important; + background-color: var(--sd-color-danger) !important; + border-color: var(--sd-color-danger) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-danger:hover,.sd-btn-danger:focus { + color: var(--sd-color-danger-text) !important; + background-color: var(--sd-color-danger-highlight) !important; + border-color: var(--sd-color-danger-highlight) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-outline-danger { + color: var(--sd-color-danger) !important; + border-color: var(--sd-color-danger) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-light,.sd-btn-outline-light:hover,.sd-btn-outline-light:focus { + color: var(--sd-color-light-text) !important; + background-color: var(--sd-color-light) !important; + border-color: var(--sd-color-light) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-light:hover,.sd-btn-light:focus { + color: var(--sd-color-light-text) !important; + background-color: var(--sd-color-light-highlight) !important; + border-color: var(--sd-color-light-highlight) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-outline-light { + color: var(--sd-color-light) !important; + border-color: var(--sd-color-light) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-muted,.sd-btn-outline-muted:hover,.sd-btn-outline-muted:focus { + color: var(--sd-color-muted-text) !important; + background-color: var(--sd-color-muted) !important; + border-color: var(--sd-color-muted) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-muted:hover,.sd-btn-muted:focus { + color: var(--sd-color-muted-text) !important; + background-color: var(--sd-color-muted-highlight) !important; + border-color: var(--sd-color-muted-highlight) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-outline-muted { + color: var(--sd-color-muted) !important; + border-color: var(--sd-color-muted) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-dark,.sd-btn-outline-dark:hover,.sd-btn-outline-dark:focus { + color: var(--sd-color-dark-text) !important; + background-color: var(--sd-color-dark) !important; + border-color: var(--sd-color-dark) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-dark:hover,.sd-btn-dark:focus { + color: var(--sd-color-dark-text) !important; + background-color: var(--sd-color-dark-highlight) !important; + border-color: var(--sd-color-dark-highlight) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-outline-dark { + color: var(--sd-color-dark) !important; + border-color: var(--sd-color-dark) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-black,.sd-btn-outline-black:hover,.sd-btn-outline-black:focus { + color: var(--sd-color-black-text) !important; + background-color: var(--sd-color-black) !important; + border-color: var(--sd-color-black) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-black:hover,.sd-btn-black:focus { + color: var(--sd-color-black-text) !important; + background-color: var(--sd-color-black-highlight) !important; + border-color: var(--sd-color-black-highlight) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-outline-black { + color: var(--sd-color-black) !important; + border-color: var(--sd-color-black) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-white,.sd-btn-outline-white:hover,.sd-btn-outline-white:focus { + color: var(--sd-color-white-text) !important; + background-color: var(--sd-color-white) !important; + border-color: var(--sd-color-white) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-white:hover,.sd-btn-white:focus { + color: var(--sd-color-white-text) !important; + background-color: var(--sd-color-white-highlight) !important; + border-color: var(--sd-color-white-highlight) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-btn-outline-white { + color: var(--sd-color-white) !important; + border-color: var(--sd-color-white) !important; + border-width: 1px !important; + border-style: solid !important +} + +.sd-stretched-link::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1; + content: "" +} + +.sd-hide-link-text { + font-size: 0 +} + +.sd-octicon,.sd-material-icon { + display: inline-block; + fill: currentColor; + vertical-align: middle +} + +.sd-avatar-xs { + border-radius: 50%; + object-fit: cover; + object-position: center; + width: 1rem; + height: 1rem +} + +.sd-avatar-sm { + border-radius: 50%; + object-fit: cover; + object-position: center; + width: 3rem; + height: 3rem +} + +.sd-avatar-md { + border-radius: 50%; + object-fit: cover; + object-position: center; + width: 5rem; + height: 5rem +} + +.sd-avatar-lg { + border-radius: 50%; + object-fit: cover; + object-position: center; + width: 7rem; + height: 7rem +} + +.sd-avatar-xl { + border-radius: 50%; + object-fit: cover; + object-position: center; + width: 10rem; + height: 10rem +} + +.sd-avatar-inherit { + border-radius: 50%; + object-fit: cover; + object-position: center; + width: inherit; + height: inherit +} + +.sd-avatar-initial { + border-radius: 50%; + object-fit: cover; + object-position: center; + width: initial; + height: initial +} + +.sd-card { + background-clip: border-box; + background-color: var(--sd-color-card-background); + border: 1px solid var(--sd-color-card-border); + border-radius: .25rem; + color: var(--sd-color-card-text); + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + min-width: 0; + position: relative; + word-wrap: break-word +} + +.sd-card>hr { + margin-left: 0; + margin-right: 0 +} + +.sd-card-hover:hover { + border-color: var(--sd-color-card-border-hover); + transform: scale(1.01) +} + +.sd-card-body { + -ms-flex: 1 1 auto; + flex: 1 1 auto; + padding: 1rem 1rem +} + +.sd-card-title { + margin-bottom: .5rem +} + +.sd-card-subtitle { + margin-top: -0.25rem; + margin-bottom: 0 +} + +.sd-card-text:last-child { + margin-bottom: 0 +} + +.sd-card-link:hover { + text-decoration: none +} + +.sd-card-link+.card-link { + margin-left: 1rem +} + +.sd-card-header { + padding: .5rem 1rem; + margin-bottom: 0; + background-color: var(--sd-color-card-header); + border-bottom: 1px solid var(--sd-color-card-border) +} + +.sd-card-header:first-child { + border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0 +} + +.sd-card-footer { + padding: .5rem 1rem; + background-color: var(--sd-color-card-footer); + border-top: 1px solid var(--sd-color-card-border) +} + +.sd-card-footer:last-child { + border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px) +} + +.sd-card-header-tabs { + margin-right: -0.5rem; + margin-bottom: -0.5rem; + margin-left: -0.5rem; + border-bottom: 0 +} + +.sd-card-header-pills { + margin-right: -0.5rem; + margin-left: -0.5rem +} + +.sd-card-img-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + padding: 1rem; + border-radius: calc(0.25rem - 1px) +} + +.sd-card-img,.sd-card-img-bottom,.sd-card-img-top { + width: 100% +} + +.sd-card-img,.sd-card-img-top { + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px) +} + +.sd-card-img,.sd-card-img-bottom { + border-bottom-left-radius: calc(0.25rem - 1px); + border-bottom-right-radius: calc(0.25rem - 1px) +} + +.sd-cards-carousel { + width: 100%; + display: flex; + flex-wrap: nowrap; + -ms-flex-direction: row; + flex-direction: row; + overflow-x: hidden; + scroll-snap-type: x mandatory +} + +.sd-cards-carousel.sd-show-scrollbar { + overflow-x: auto +} + +.sd-cards-carousel:hover,.sd-cards-carousel:focus { + overflow-x: auto +} + +.sd-cards-carousel>.sd-card { + flex-shrink: 0; + scroll-snap-align: start +} + +.sd-cards-carousel>.sd-card:not(:last-child) { + margin-right: 3px +} + +.sd-card-cols-1>.sd-card { + width: 90% +} + +.sd-card-cols-2>.sd-card { + width: 45% +} + +.sd-card-cols-3>.sd-card { + width: 30% +} + +.sd-card-cols-4>.sd-card { + width: 22.5% +} + +.sd-card-cols-5>.sd-card { + width: 18% +} + +.sd-card-cols-6>.sd-card { + width: 15% +} + +.sd-card-cols-7>.sd-card { + width: 12.8571428571% +} + +.sd-card-cols-8>.sd-card { + width: 11.25% +} + +.sd-card-cols-9>.sd-card { + width: 10% +} + +.sd-card-cols-10>.sd-card { + width: 9% +} + +.sd-card-cols-11>.sd-card { + width: 8.1818181818% +} + +.sd-card-cols-12>.sd-card { + width: 7.5% +} + +.sd-container,.sd-container-fluid,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container-xl { + margin-left: auto; + margin-right: auto; + padding-left: var(--sd-gutter-x, 0.75rem); + padding-right: var(--sd-gutter-x, 0.75rem); + width: 100% +} + +@media(min-width: 576px) { + .sd-container-sm,.sd-container { + max-width:540px + } +} + +@media(min-width: 768px) { + .sd-container-md,.sd-container-sm,.sd-container { + max-width:720px + } +} + +@media(min-width: 992px) { + .sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container { + max-width:960px + } +} + +@media(min-width: 1200px) { + .sd-container-xl,.sd-container-lg,.sd-container-md,.sd-container-sm,.sd-container { + max-width:1140px + } +} + +.sd-row { + --sd-gutter-x: 1.5rem; + --sd-gutter-y: 0; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-top: calc(var(--sd-gutter-y) * -1); + margin-right: calc(var(--sd-gutter-x) * -0.5); + margin-left: calc(var(--sd-gutter-x) * -0.5) +} + +.sd-row>* { + box-sizing: border-box; + flex-shrink: 0; + width: 100%; + max-width: 100%; + padding-right: calc(var(--sd-gutter-x) * 0.5); + padding-left: calc(var(--sd-gutter-x) * 0.5); + margin-top: var(--sd-gutter-y) +} + +.sd-col { + flex: 1 0 0%; + -ms-flex: 1 0 0% +} + +.sd-row-cols-auto>* { + flex: 0 0 auto; + width: auto +} + +.sd-row-cols-1>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 100% +} + +.sd-row-cols-2>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 50% +} + +.sd-row-cols-3>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 33.3333333333% +} + +.sd-row-cols-4>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 25% +} + +.sd-row-cols-5>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 20% +} + +.sd-row-cols-6>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 16.6666666667% +} + +.sd-row-cols-7>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 14.2857142857% +} + +.sd-row-cols-8>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 12.5% +} + +.sd-row-cols-9>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 11.1111111111% +} + +.sd-row-cols-10>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 10% +} + +.sd-row-cols-11>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 9.0909090909% +} + +.sd-row-cols-12>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 8.3333333333% +} + +@media(min-width: 576px) { + .sd-col-sm { + flex:1 0 0%; + -ms-flex: 1 0 0% + } + + .sd-row-cols-sm-auto { + flex: 1 0 auto; + -ms-flex: 1 0 auto; + width: 100% + } + + .sd-row-cols-sm-1>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 100% + } + + .sd-row-cols-sm-2>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 50% + } + + .sd-row-cols-sm-3>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 33.3333333333% + } + + .sd-row-cols-sm-4>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 25% + } + + .sd-row-cols-sm-5>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 20% + } + + .sd-row-cols-sm-6>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 16.6666666667% + } + + .sd-row-cols-sm-7>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 14.2857142857% + } + + .sd-row-cols-sm-8>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 12.5% + } + + .sd-row-cols-sm-9>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 11.1111111111% + } + + .sd-row-cols-sm-10>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 10% + } + + .sd-row-cols-sm-11>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 9.0909090909% + } + + .sd-row-cols-sm-12>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 8.3333333333% + } +} + +@media(min-width: 768px) { + .sd-col-md { + flex:1 0 0%; + -ms-flex: 1 0 0% + } + + .sd-row-cols-md-auto { + flex: 1 0 auto; + -ms-flex: 1 0 auto; + width: 100% + } + + .sd-row-cols-md-1>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 100% + } + + .sd-row-cols-md-2>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 50% + } + + .sd-row-cols-md-3>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 33.3333333333% + } + + .sd-row-cols-md-4>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 25% + } + + .sd-row-cols-md-5>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 20% + } + + .sd-row-cols-md-6>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 16.6666666667% + } + + .sd-row-cols-md-7>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 14.2857142857% + } + + .sd-row-cols-md-8>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 12.5% + } + + .sd-row-cols-md-9>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 11.1111111111% + } + + .sd-row-cols-md-10>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 10% + } + + .sd-row-cols-md-11>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 9.0909090909% + } + + .sd-row-cols-md-12>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 8.3333333333% + } +} + +@media(min-width: 992px) { + .sd-col-lg { + flex:1 0 0%; + -ms-flex: 1 0 0% + } + + .sd-row-cols-lg-auto { + flex: 1 0 auto; + -ms-flex: 1 0 auto; + width: 100% + } + + .sd-row-cols-lg-1>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 100% + } + + .sd-row-cols-lg-2>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 50% + } + + .sd-row-cols-lg-3>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 33.3333333333% + } + + .sd-row-cols-lg-4>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 25% + } + + .sd-row-cols-lg-5>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 20% + } + + .sd-row-cols-lg-6>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 16.6666666667% + } + + .sd-row-cols-lg-7>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 14.2857142857% + } + + .sd-row-cols-lg-8>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 12.5% + } + + .sd-row-cols-lg-9>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 11.1111111111% + } + + .sd-row-cols-lg-10>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 10% + } + + .sd-row-cols-lg-11>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 9.0909090909% + } + + .sd-row-cols-lg-12>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 8.3333333333% + } +} + +@media(min-width: 1200px) { + .sd-col-xl { + flex:1 0 0%; + -ms-flex: 1 0 0% + } + + .sd-row-cols-xl-auto { + flex: 1 0 auto; + -ms-flex: 1 0 auto; + width: 100% + } + + .sd-row-cols-xl-1>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 100% + } + + .sd-row-cols-xl-2>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 50% + } + + .sd-row-cols-xl-3>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 33.3333333333% + } + + .sd-row-cols-xl-4>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 25% + } + + .sd-row-cols-xl-5>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 20% + } + + .sd-row-cols-xl-6>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 16.6666666667% + } + + .sd-row-cols-xl-7>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 14.2857142857% + } + + .sd-row-cols-xl-8>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 12.5% + } + + .sd-row-cols-xl-9>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 11.1111111111% + } + + .sd-row-cols-xl-10>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 10% + } + + .sd-row-cols-xl-11>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 9.0909090909% + } + + .sd-row-cols-xl-12>* { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 8.3333333333% + } +} + +.sd-col-auto { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: auto +} + +.sd-col-1 { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 8.3333333333% +} + +.sd-col-2 { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 16.6666666667% +} + +.sd-col-3 { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 25% +} + +.sd-col-4 { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 33.3333333333% +} + +.sd-col-5 { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 41.6666666667% +} + +.sd-col-6 { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 50% +} + +.sd-col-7 { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 58.3333333333% +} + +.sd-col-8 { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 66.6666666667% +} + +.sd-col-9 { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 75% +} + +.sd-col-10 { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 83.3333333333% +} + +.sd-col-11 { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 91.6666666667% +} + +.sd-col-12 { + flex: 0 0 auto; + -ms-flex: 0 0 auto; + width: 100% +} + +.sd-g-0,.sd-gy-0 { + --sd-gutter-y: 0 +} + +.sd-g-0,.sd-gx-0 { + --sd-gutter-x: 0 +} + +.sd-g-1,.sd-gy-1 { + --sd-gutter-y: 0.25rem +} + +.sd-g-1,.sd-gx-1 { + --sd-gutter-x: 0.25rem +} + +.sd-g-2,.sd-gy-2 { + --sd-gutter-y: 0.5rem +} + +.sd-g-2,.sd-gx-2 { + --sd-gutter-x: 0.5rem +} + +.sd-g-3,.sd-gy-3 { + --sd-gutter-y: 1rem +} + +.sd-g-3,.sd-gx-3 { + --sd-gutter-x: 1rem +} + +.sd-g-4,.sd-gy-4 { + --sd-gutter-y: 1.5rem +} + +.sd-g-4,.sd-gx-4 { + --sd-gutter-x: 1.5rem +} + +.sd-g-5,.sd-gy-5 { + --sd-gutter-y: 3rem +} + +.sd-g-5,.sd-gx-5 { + --sd-gutter-x: 3rem +} + +@media(min-width: 576px) { + .sd-col-sm-auto { + -ms-flex:0 0 auto; + flex: 0 0 auto; + width: auto + } + + .sd-col-sm-1 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 8.3333333333% + } + + .sd-col-sm-2 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 16.6666666667% + } + + .sd-col-sm-3 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 25% + } + + .sd-col-sm-4 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 33.3333333333% + } + + .sd-col-sm-5 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 41.6666666667% + } + + .sd-col-sm-6 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 50% + } + + .sd-col-sm-7 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 58.3333333333% + } + + .sd-col-sm-8 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 66.6666666667% + } + + .sd-col-sm-9 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 75% + } + + .sd-col-sm-10 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 83.3333333333% + } + + .sd-col-sm-11 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 91.6666666667% + } + + .sd-col-sm-12 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 100% + } + + .sd-g-sm-0,.sd-gy-sm-0 { + --sd-gutter-y: 0 + } + + .sd-g-sm-0,.sd-gx-sm-0 { + --sd-gutter-x: 0 + } + + .sd-g-sm-1,.sd-gy-sm-1 { + --sd-gutter-y: 0.25rem + } + + .sd-g-sm-1,.sd-gx-sm-1 { + --sd-gutter-x: 0.25rem + } + + .sd-g-sm-2,.sd-gy-sm-2 { + --sd-gutter-y: 0.5rem + } + + .sd-g-sm-2,.sd-gx-sm-2 { + --sd-gutter-x: 0.5rem + } + + .sd-g-sm-3,.sd-gy-sm-3 { + --sd-gutter-y: 1rem + } + + .sd-g-sm-3,.sd-gx-sm-3 { + --sd-gutter-x: 1rem + } + + .sd-g-sm-4,.sd-gy-sm-4 { + --sd-gutter-y: 1.5rem + } + + .sd-g-sm-4,.sd-gx-sm-4 { + --sd-gutter-x: 1.5rem + } + + .sd-g-sm-5,.sd-gy-sm-5 { + --sd-gutter-y: 3rem + } + + .sd-g-sm-5,.sd-gx-sm-5 { + --sd-gutter-x: 3rem + } +} + +@media(min-width: 768px) { + .sd-col-md-auto { + -ms-flex:0 0 auto; + flex: 0 0 auto; + width: auto + } + + .sd-col-md-1 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 8.3333333333% + } + + .sd-col-md-2 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 16.6666666667% + } + + .sd-col-md-3 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 25% + } + + .sd-col-md-4 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 33.3333333333% + } + + .sd-col-md-5 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 41.6666666667% + } + + .sd-col-md-6 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 50% + } + + .sd-col-md-7 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 58.3333333333% + } + + .sd-col-md-8 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 66.6666666667% + } + + .sd-col-md-9 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 75% + } + + .sd-col-md-10 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 83.3333333333% + } + + .sd-col-md-11 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 91.6666666667% + } + + .sd-col-md-12 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 100% + } + + .sd-g-md-0,.sd-gy-md-0 { + --sd-gutter-y: 0 + } + + .sd-g-md-0,.sd-gx-md-0 { + --sd-gutter-x: 0 + } + + .sd-g-md-1,.sd-gy-md-1 { + --sd-gutter-y: 0.25rem + } + + .sd-g-md-1,.sd-gx-md-1 { + --sd-gutter-x: 0.25rem + } + + .sd-g-md-2,.sd-gy-md-2 { + --sd-gutter-y: 0.5rem + } + + .sd-g-md-2,.sd-gx-md-2 { + --sd-gutter-x: 0.5rem + } + + .sd-g-md-3,.sd-gy-md-3 { + --sd-gutter-y: 1rem + } + + .sd-g-md-3,.sd-gx-md-3 { + --sd-gutter-x: 1rem + } + + .sd-g-md-4,.sd-gy-md-4 { + --sd-gutter-y: 1.5rem + } + + .sd-g-md-4,.sd-gx-md-4 { + --sd-gutter-x: 1.5rem + } + + .sd-g-md-5,.sd-gy-md-5 { + --sd-gutter-y: 3rem + } + + .sd-g-md-5,.sd-gx-md-5 { + --sd-gutter-x: 3rem + } +} + +@media(min-width: 992px) { + .sd-col-lg-auto { + -ms-flex:0 0 auto; + flex: 0 0 auto; + width: auto + } + + .sd-col-lg-1 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 8.3333333333% + } + + .sd-col-lg-2 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 16.6666666667% + } + + .sd-col-lg-3 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 25% + } + + .sd-col-lg-4 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 33.3333333333% + } + + .sd-col-lg-5 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 41.6666666667% + } + + .sd-col-lg-6 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 50% + } + + .sd-col-lg-7 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 58.3333333333% + } + + .sd-col-lg-8 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 66.6666666667% + } + + .sd-col-lg-9 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 75% + } + + .sd-col-lg-10 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 83.3333333333% + } + + .sd-col-lg-11 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 91.6666666667% + } + + .sd-col-lg-12 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 100% + } + + .sd-g-lg-0,.sd-gy-lg-0 { + --sd-gutter-y: 0 + } + + .sd-g-lg-0,.sd-gx-lg-0 { + --sd-gutter-x: 0 + } + + .sd-g-lg-1,.sd-gy-lg-1 { + --sd-gutter-y: 0.25rem + } + + .sd-g-lg-1,.sd-gx-lg-1 { + --sd-gutter-x: 0.25rem + } + + .sd-g-lg-2,.sd-gy-lg-2 { + --sd-gutter-y: 0.5rem + } + + .sd-g-lg-2,.sd-gx-lg-2 { + --sd-gutter-x: 0.5rem + } + + .sd-g-lg-3,.sd-gy-lg-3 { + --sd-gutter-y: 1rem + } + + .sd-g-lg-3,.sd-gx-lg-3 { + --sd-gutter-x: 1rem + } + + .sd-g-lg-4,.sd-gy-lg-4 { + --sd-gutter-y: 1.5rem + } + + .sd-g-lg-4,.sd-gx-lg-4 { + --sd-gutter-x: 1.5rem + } + + .sd-g-lg-5,.sd-gy-lg-5 { + --sd-gutter-y: 3rem + } + + .sd-g-lg-5,.sd-gx-lg-5 { + --sd-gutter-x: 3rem + } +} + +@media(min-width: 1200px) { + .sd-col-xl-auto { + -ms-flex:0 0 auto; + flex: 0 0 auto; + width: auto + } + + .sd-col-xl-1 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 8.3333333333% + } + + .sd-col-xl-2 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 16.6666666667% + } + + .sd-col-xl-3 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 25% + } + + .sd-col-xl-4 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 33.3333333333% + } + + .sd-col-xl-5 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 41.6666666667% + } + + .sd-col-xl-6 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 50% + } + + .sd-col-xl-7 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 58.3333333333% + } + + .sd-col-xl-8 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 66.6666666667% + } + + .sd-col-xl-9 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 75% + } + + .sd-col-xl-10 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 83.3333333333% + } + + .sd-col-xl-11 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 91.6666666667% + } + + .sd-col-xl-12 { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: 100% + } + + .sd-g-xl-0,.sd-gy-xl-0 { + --sd-gutter-y: 0 + } + + .sd-g-xl-0,.sd-gx-xl-0 { + --sd-gutter-x: 0 + } + + .sd-g-xl-1,.sd-gy-xl-1 { + --sd-gutter-y: 0.25rem + } + + .sd-g-xl-1,.sd-gx-xl-1 { + --sd-gutter-x: 0.25rem + } + + .sd-g-xl-2,.sd-gy-xl-2 { + --sd-gutter-y: 0.5rem + } + + .sd-g-xl-2,.sd-gx-xl-2 { + --sd-gutter-x: 0.5rem + } + + .sd-g-xl-3,.sd-gy-xl-3 { + --sd-gutter-y: 1rem + } + + .sd-g-xl-3,.sd-gx-xl-3 { + --sd-gutter-x: 1rem + } + + .sd-g-xl-4,.sd-gy-xl-4 { + --sd-gutter-y: 1.5rem + } + + .sd-g-xl-4,.sd-gx-xl-4 { + --sd-gutter-x: 1.5rem + } + + .sd-g-xl-5,.sd-gy-xl-5 { + --sd-gutter-y: 3rem + } + + .sd-g-xl-5,.sd-gx-xl-5 { + --sd-gutter-x: 3rem + } +} + +.sd-flex-row-reverse { + flex-direction: row-reverse !important +} + +details.sd-dropdown { + position: relative +} + +details.sd-dropdown .sd-summary-title { + font-weight: 700; + padding-right: 3em !important; + -moz-user-select: none; + -ms-user-select: none; + -webkit-user-select: none; + user-select: none +} + +details.sd-dropdown:hover { + cursor: pointer +} + +details.sd-dropdown .sd-summary-content { + cursor: default +} + +details.sd-dropdown summary { + list-style: none; + padding: 1em +} + +details.sd-dropdown summary .sd-octicon.no-title { + vertical-align: middle +} + +details.sd-dropdown[open] summary .sd-octicon.no-title { + visibility: hidden +} + +details.sd-dropdown summary::-webkit-details-marker { + display: none +} + +details.sd-dropdown summary:focus { + outline: none +} + +details.sd-dropdown .sd-summary-icon { + margin-right: .5em +} + +details.sd-dropdown .sd-summary-icon svg { + opacity: .8 +} + +details.sd-dropdown summary:hover .sd-summary-up svg,details.sd-dropdown summary:hover .sd-summary-down svg { + opacity: 1; + transform: scale(1.1) +} + +details.sd-dropdown .sd-summary-up svg,details.sd-dropdown .sd-summary-down svg { + display: block; + opacity: .6 +} + +details.sd-dropdown .sd-summary-up,details.sd-dropdown .sd-summary-down { + pointer-events: none; + position: absolute; + right: 1em; + top: 1em +} + +details.sd-dropdown[open]>.sd-summary-title .sd-summary-down { + visibility: hidden +} + +details.sd-dropdown:not([open])>.sd-summary-title .sd-summary-up { + visibility: hidden +} + +details.sd-dropdown:not([open]).sd-card { + border: none +} + +details.sd-dropdown:not([open])>.sd-card-header { + border: 1px solid var(--sd-color-card-border); + border-radius: .25rem +} + +details.sd-dropdown.sd-fade-in[open] summary~* { + -moz-animation: sd-fade-in .5s ease-in-out; + -webkit-animation: sd-fade-in .5s ease-in-out; + animation: sd-fade-in .5s ease-in-out +} + +details.sd-dropdown.sd-fade-in-slide-down[open] summary~* { + -moz-animation: sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out; + -webkit-animation: sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out; + animation: sd-fade-in .5s ease-in-out,sd-slide-down .5s ease-in-out +} + +.sd-col>.sd-dropdown { + width: 100% +} + +.sd-summary-content>.sd-tab-set:first-child { + margin-top: 0 +} + +@keyframes sd-fade-in { + 0% { + opacity: 0 + } + + 100% { + opacity: 1 + } +} + +@keyframes sd-slide-down { + 0% { + transform: translate(0, -10px) + } + + 100% { + transform: translate(0, 0) + } +} + +.sd-tab-set { + border-radius: .125rem; + display: flex; + flex-wrap: wrap; + margin: 1em 0; + position: relative +} + +.sd-tab-set>input { + opacity: 0; + position: absolute +} + +.sd-tab-set>input:checked+label { + border-color: var(--sd-color-tabs-underline-active); + color: var(--sd-color-tabs-label-active) +} + +.sd-tab-set>input:checked+label+.sd-tab-content { + display: block +} + +.sd-tab-set>input:not(:checked)+label:hover { + color: var(--sd-color-tabs-label-hover); + border-color: var(--sd-color-tabs-underline-hover) +} + +.sd-tab-set>input:focus+label { + outline-style: auto +} + +.sd-tab-set>input:not(.focus-visible)+label { + outline: none; + -webkit-tap-highlight-color: transparent +} + +.sd-tab-set>label { + border-bottom: .125rem solid transparent; + margin-bottom: 0; + color: var(--sd-color-tabs-label-inactive); + border-color: var(--sd-color-tabs-underline-inactive); + cursor: pointer; + font-size: var(--sd-fontsize-tabs-label); + font-weight: 700; + padding: 1em 1.25em .5em; + transition: color 250ms; + width: auto; + z-index: 1 +} + +html .sd-tab-set>label:hover { + color: var(--sd-color-tabs-label-active) +} + +.sd-col>.sd-tab-set { + width: 100% +} + +.sd-tab-content { + box-shadow: 0 -0.0625rem var(--sd-color-tabs-overline),0 .0625rem var(--sd-color-tabs-underline); + display: none; + order: 99; + padding-bottom: .75rem; + padding-top: .75rem; + width: 100% +} + +.sd-tab-content>:first-child { + margin-top: 0 !important +} + +.sd-tab-content>:last-child { + margin-bottom: 0 !important +} + +.sd-tab-content>.sd-tab-set { + margin: 0 +} + +.sd-sphinx-override,.sd-sphinx-override * { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box +} + +.sd-sphinx-override p { + margin-top: 0 +} + +:root { + --sd-color-primary: #0071bc; + --sd-color-secondary: #6c757d; + --sd-color-success: #28a745; + --sd-color-info: #17a2b8; + --sd-color-warning: #f0b37e; + --sd-color-danger: #dc3545; + --sd-color-light: #f8f9fa; + --sd-color-muted: #6c757d; + --sd-color-dark: #212529; + --sd-color-black: black; + --sd-color-white: white; + --sd-color-primary-highlight: #0060a0; + --sd-color-secondary-highlight: #5c636a; + --sd-color-success-highlight: #228e3b; + --sd-color-info-highlight: #148a9c; + --sd-color-warning-highlight: #cc986b; + --sd-color-danger-highlight: #bb2d3b; + --sd-color-light-highlight: #d3d4d5; + --sd-color-muted-highlight: #5c636a; + --sd-color-dark-highlight: #1c1f23; + --sd-color-black-highlight: black; + --sd-color-white-highlight: #d9d9d9; + --sd-color-primary-text: #fff; + --sd-color-secondary-text: #fff; + --sd-color-success-text: #fff; + --sd-color-info-text: #fff; + --sd-color-warning-text: #212529; + --sd-color-danger-text: #fff; + --sd-color-light-text: #212529; + --sd-color-muted-text: #fff; + --sd-color-dark-text: #fff; + --sd-color-black-text: #fff; + --sd-color-white-text: #212529; + --sd-color-shadow: rgba(0, 0, 0, 0.15); + --sd-color-card-border: rgba(0, 0, 0, 0.125); + --sd-color-card-border-hover: hsla(231, 99%, 66%, 1); + --sd-color-card-background: transparent; + --sd-color-card-text: inherit; + --sd-color-card-header: transparent; + --sd-color-card-footer: transparent; + --sd-color-tabs-label-active: hsla(231, 99%, 66%, 1); + --sd-color-tabs-label-hover: hsla(231, 99%, 66%, 1); + --sd-color-tabs-label-inactive: hsl(0, 0%, 66%); + --sd-color-tabs-underline-active: hsla(231, 99%, 66%, 1); + --sd-color-tabs-underline-hover: rgba(178, 206, 245, 0.62); + --sd-color-tabs-underline-inactive: transparent; + --sd-color-tabs-overline: rgb(222, 222, 222); + --sd-color-tabs-underline: rgb(222, 222, 222); + --sd-fontsize-tabs-label: 1rem +} diff --git a/python/docs/_static/css/root.css b/python/docs/_static/css/root.css new file mode 100644 index 000000000..388f018c3 --- /dev/null +++ b/python/docs/_static/css/root.css @@ -0,0 +1,38 @@ +/*! + * Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com + * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) + * Copyright 2023 Fonticons, Inc. + */ + +.fas { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + display: var(--fa-display, inline-block); + font-family: 'Font Awesome 6 Free'; + font-style: normal; + font-weight: 900; + font-variant: normal; + line-height: 1; + text-rendering: auto; +} + +@font-face { + font-family: 'Font Awesome 6 Free'; + font-display: block; + font-weight: 900; + src: + url("../fonts/FontAwesome6Free-Solid-900.woff2") format("woff2"), + url("../fonts/FontAwesome6Free-Solid-900.ttf") format("truetype"); +} + +.fa-binoculars::before { + content: "\f1e5"; +} + +.fa-timeline::before { + content: "\e29c"; +} + +.fa-backward::before { + content: "\f04a"; +} \ No newline at end of file diff --git a/python/docs/_static/css/styles.css b/python/docs/_static/css/styles.css new file mode 100644 index 000000000..2b9bf8b30 --- /dev/null +++ b/python/docs/_static/css/styles.css @@ -0,0 +1,87 @@ +/* css styles */ + +.navbar-brand-logo img { + max-width: 100%; + width: auto; + height: 36px; + max-height: 36px; + vertical-align: middle; +} + +body.quarto-light nav.navbar { + box-shadow: 0 0.125rem 0.25rem 0 var(--bs-gray-400); +} + +body.quarto-light .only-dark { + display: none !important; +} + +body.quarto-dark .only-light { + display: none !important; +} + +.announcement { + align-items: center; + display: flex; + justify-content: center; + min-height: 3rem; + padding: 0.5rem 12.5%; + position: relative; + text-align: center; + width: 100%; +} + +body.quarto-light .announcement { + background-color: rgb(208, 231, 233); +} + +body.quarto-dark .announcement { + background-color: rgb(73, 73, 110); +} + +h2 { + border-bottom: none; +} + +body.quarto-dark .sd-card { + border: 1px solid white; +} + +body.quarto-dark .sd-card-header { + border-bottom: 1px solid white; +} + +th> :last-child, +td> :last-child { + margin-bottom: 0px; +} + +dd { + margin-bottom: 10px; + margin-left: 30px; + margin-top: 3px; +} + +.red { + color: #e83e8c +} + +.highlight dt { + padding-bottom: 4px; + padding-left: 8px; + padding-right: 8px; + padding-top: 2px; +} + +body.quarto-light .highlight dt { + background-color: #f5f5f5; +} + +body.quarto-dark .highlight dt { + background-color: #2f2f2f; +} + +.bold-italic { + font-weight: bolder; + font-style: italic; +} \ No newline at end of file diff --git a/python/docs/_static/fonts/FontAwesome6Free-Solid-900.ttf b/python/docs/_static/fonts/FontAwesome6Free-Solid-900.ttf new file mode 100644 index 0000000000000000000000000000000000000000..deab676ff9d908d8023782116fc4affa93ecede4 GIT binary patch literal 384736 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

BmFx3;X;of;ZS^E^Ji-ilCCh#LMnCj%N76v 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 W<%7kilPt>s0000r}h literal 0 HcmV?d00001 diff --git a/python/docs/_static/images/kaskada-negative.svg b/python/docs/_static/images/kaskada-negative.svg new file mode 100644 index 000000000..6b78c25fc --- /dev/null +++ b/python/docs/_static/images/kaskada-negative.svg @@ -0,0 +1 @@ +Kaskada Logo Horizontal Negative RGB \ No newline at end of file diff --git a/python/docs/_static/images/kaskada-positive.svg b/python/docs/_static/images/kaskada-positive.svg new file mode 100644 index 000000000..ccfae84e2 --- /dev/null +++ b/python/docs/_static/images/kaskada-positive.svg @@ -0,0 +1 @@ +Kaskada Logo Horizontal Positive RGB \ No newline at end of file diff --git a/python/docs/_templates/card.ejs b/python/docs/_templates/card.ejs new file mode 100644 index 000000000..691f296ea --- /dev/null +++ b/python/docs/_templates/card.ejs @@ -0,0 +1,23 @@ +```{=html} +

+``` \ No newline at end of file diff --git a/python/docs/_templates/data_types_table.ejs b/python/docs/_templates/data_types_table.ejs new file mode 100644 index 000000000..142b808f5 --- /dev/null +++ b/python/docs/_templates/data_types_table.ejs @@ -0,0 +1,44 @@ +```{=html} + + + + + + + + + + + + + <% for (const item of items) { %> + + + + + <% } %> + +
+

Types

+
+

Description

+
+

+ <% for (const index in item.types) { %> + <%= item.types[index] %> + <% if (index < item.types.length - 1) { %>,<% } %> + <% } %> +

+
+

+ <%= item.desc %> +

+

+ Examples: + <% for (const index in item.examples) { %> + <%= item.examples[index] %> + <% if (index < item.examples.length - 1) { %>,<% } %> + <% } %> +

+
+``` \ No newline at end of file diff --git a/python/docs/blog/_metadata.yml b/python/docs/blog/_metadata.yml new file mode 100644 index 000000000..954e649d0 --- /dev/null +++ b/python/docs/blog/_metadata.yml @@ -0,0 +1,4 @@ +format: + html: + link-external-icon: true + link-external-newwindow: true diff --git a/python/docs/blog/index.qmd b/python/docs/blog/index.qmd new file mode 100644 index 000000000..e2c74b6fd --- /dev/null +++ b/python/docs/blog/index.qmd @@ -0,0 +1,12 @@ +--- +title: Blog +listing: + contents: posts + sort: "date desc" + type: default + categories: true + sort-ui: true + filter-ui: true + fields: ["title", "date", "author", "subtitle", "description", "reading-time", "categories"] # "image", "image-alt", +page-layout: full +--- diff --git a/python/docs/blog/posts/2023-03-28-announcing-kaskada-oss.qmd b/python/docs/blog/posts/2023-03-28-announcing-kaskada-oss.qmd new file mode 100644 index 000000000..d925cf241 --- /dev/null +++ b/python/docs/blog/posts/2023-03-28-announcing-kaskada-oss.qmd @@ -0,0 +1,76 @@ +--- +author: Ben Chambers +date: 2023-Mar-28 +categories: + - releases +title: Announcing Kaskada OSS +subtitle: From Startup to Open Source Project +--- + +# Announcing Kaskada OSS + +Today, we’re announcing the open-source release of Kaskada – a modern, open-source event processing engine. + +# How it began: Simplifying ML + +Kaskada technology has evolved a lot since we began developing it three years ago. Initially, we were laser focused on the machine learning (ML) space. We saw many companies working on different approaches to the same ML problems -- managing computed feature values (what is now called a feature store), applying existing algorithms to train a model from those values, and serving that model by applying it to computed feature values. We saw a different problem. + +With our background in the data processing space we identified a critical gap -- no one was looking at the process of going from raw, event-based, data to computed feature values. This meant that users had to choose – use SQL and treat the events as a table, losing important information in the process, or use lower-level data pipeline APIs and worry about all the details. Our experience working on data processing systems at Google and as part of Apache Beam led us to create a compute engine designed for the needs of feature engineering — we called it a feature engine. + +We are extremely proud of where Kaskada technology is today. Unlike a feature store, it focuses on computing the features a user described using a simple, declarative language. Unlike existing data processing systems, it delivers on the needs of machine learning – expressing sophisticated, temporal features without leakage, working with raw events without pre-processing, and scalability that just worked for training and serving. + +The unique characteristics of Kaskada make it ideal for the time-based event processing required for accurate, real-time machine learning. While we see that ML will always be a great use case for Kaskada, we’ve realized it can be used for so much more. + +# Modern, Open-Source Event Processing + +When [DataStax acquired Kaskada](https://www.datastax.com/press-release/datastax-acquires-machine-learning-company-kaskada-to-unlock-real-time-ai) a few months ago, we began the process of open-sourcing the core Kaskada technology. In the conversations that followed, we realized that the capabilities of Kaskada that make it ideal for real-time ML – easy to use, high-performance columnar computations over event-based data – also make it great for general event processing. These features include: + +1. **Rich, Temporal Operations**: The ability to easily express computations over time beyond windowed aggregations. For instance, when computing training data it was often necessary to compute values at a point in time in the past and combine those with a label value computed at a later point in time. This led to a powerful set of operations for working with time. +2. **Events all the way down**: The ability to run a query both to get all results over time and just the final results. This means that Kaskada operates directly on the events – turning a sequence of events into a sequence of changes, which may be observed directly or materialized to a table. By treating everything as events, the temporal operations are always available and you never need to think about the difference between streams and tables, nor do you need to use different APIs for each. +3. **Modern and easy to use**: Kaskada is built in Rust and uses Apache Arrow for high-performance, columnar computations. It consists of a single binary which makes for easy local and cloud deployments. + + +This led to the decision to open source Kaskada as a modern, open-source event-processing language and native engine. Machine learning is still a great use case of Kaskada, but we didn’t want the feature engine label to constrain community creativity and innovation. It’s all available today in the [GitHub repository](https://github.com/kaskada-ai/kaskada) under the Apache 2.0 License. + +# Why use Kaskada? + +Kaskada is for you if… + +1. **You want to compute the results of your query over time.** +Operating over time all the way down means that Kaskada makes it easy to compute the result of any query over time. + +2. **You want to express temporal computations without writing pages of SQL.** +Kaskada provides a declarative language for event-processing. Because of the focus on temporal computations and composability, it is much easier and shorter than comparable SQL queries. + +3. **You want to process events today without setting up other tools.** +The columnar event-processing engine within Kaskada scales to X million events/second running on a single machine. This lets you get started and iterate quickly without becoming an expert in cluster management or big-data tools. + + +# What’s coming next? + +Our first goal was getting the project released. Now that it is, we are excited to see where the project goes! + +Some improvements on our mind are shown below. We look forward to hearing your thoughts on what would help you process events. + +1. **Increase extensibility and participate in the larger open-source community.** + - Introduce extension points for I/O connectors and contribute connectors for a larger set of supported formats. + - Expose a logical execution plan after the language constructs have been compiled away, so that other executors may be developed using the same parsing and type-checking rules. + - Introduce extension points for custom schema catalogs, allowing Kaskada queries to be compiled against existing data catalogs. + +2. **Align query capabilities with more general, event-processing use cases.** + - Ability to create composite events from patterns of existing events and subsequently process those composite events (“CEP”). + - Improvements to the declarative language to reduce surprises, make it more familiar to new users, and make it even easier to express temporal computations over events. + +3. **Continue to improve local performance and usability.** + - Make it possible to use the engine more easily in a variety of ways – via a command line REPL, via an API, etc. + - Improve performance and latency of real-time and partitioned execution within the native engine. + +# How can I contribute? + +Give it a try – [download one of the releases](https://github.com/kaskada-ai/kaskada/releases) and run some computations on your event data. Let us know how it works for you, and what you’d like to see improved! + +We’d love to hear what you think - please comment or ask on our [Kaskada GitHub discussions page](https://github.com/kaskada-ai/kaskada/discussions). + +Help spread the word – Star and Follow the project on GitHub! + +Please file issues, start discussions or join us on GitHub to chat about the project or event-processing in general. \ No newline at end of file diff --git a/python/docs/blog/posts/2023-08-25-new-kaskada.qmd b/python/docs/blog/posts/2023-08-25-new-kaskada.qmd new file mode 100644 index 000000000..c89e3754a --- /dev/null +++ b/python/docs/blog/posts/2023-08-25-new-kaskada.qmd @@ -0,0 +1,83 @@ +--- +date: 2023-Aug-25 +author: Ryan Michael +categories: + - releases +title: Introducing the New Kaskada +subtitle: Embedded in Python for accessible Real-Time AI +--- + +We started Kaskada with the goal of simplifying the real-time AI/ML lifecycle, and in the past year AI has exploded in usefulness and accessibility. Generative models and Large Language Models (LLMs) have revolutionized how we approach AI. Their accessibility and incredible capabilities have made AI more valuable than it has ever been and democratized the practice of AI. + +Still, a challenge remains: building and managing real-time AI applications. + +## The Challenge of using Real-Time Data in AI Applications + +Real-time data for AI Applications has always been surrounded by an array of challenges. For example: + +1. **Infrastructure Hurdles**: Accessing real-time data often means struggling to acquire data and deploying complex infrastructure, requiring significant time and expertise to get right. + +2. **Cumbersome Tools**: Traditional tools for streaming data are bulky, with steep learning curves and complex JVM-based setups. + +3. **Analysis Disconnect**: AI models thrive on historical data, but the tools designed for bulk historical analysis are often worlds apart from those made for real-time or streaming data processing. + +4. **Challenges of Time-Travel**: AI applications frequently require a unique kind of historical analysis – one that can time-travel through your data. Expressing such analyses is challenging with conventional analytic tools that weren’t designed with time in mind. + +These challenges have made it difficult for all but the largest companies with the deepest development budgets to deliver on the promise of real-time AI, and these are the challenges we built Kaskada to solve. + +## Welcome to the New Kaskada + +We originally built Kaskada as a managed service. Earlier this year, we [released Kaskada as an open-source, self-managed service](./2023-03-28-announcing-kaskada-oss.qmd), simplifying data onboarding and allowing Kaskada to be deployed anywhere. + +Today, we take the next step in improving Kaskada’s usability by providing its core compute engine as an embedded Python library. Because Kaskada is written in Rust, we’re able to leverage the excellent [PyO3](https://pyo3.rs/) project to compile Python-native bindings for our compute engine and support Python-defined UDF’s. Additionally, Kaskada is built using [Apache Arrow](https://arrow.apache.org/), which allows zero-copy data transfers between Kaskada and other Python libraries such as [Pandas](https://pandas.pydata.org/), allowing you to operate on your data in-place. + +We’re also changing how you query Kaskada by implementing our query DSL as Python functions. This change makes it easier to get started by eliminating the learning curve of a new language and improving integration with code editors, syntax highlighters, and AI coding assistants. + +The result is an easy-to-use Python-native library with all the efficiency and performance of our low-level Rust implementation, fully integrated with the rich Python ecosystem of AI/ML tools, visualization libraries etc. + +## Features for Real-Time AI Applications + +Real-Time AI is easier today than it's ever been: + +* Foundation models built by OpenAI, Facebook and others can be used as a starting point, allowing sophisticated applications to be built with a fraction of the data that would otherwise be necessary. +* Services such as OpenAI eliminate the need to manage complex infrastructure. +* Platforms like HuggingFace have made it easier than ever to share and collaborate on open LLMs. + +The New Kaskada complements these resources, making it easier than ever to utilize real-time data by providing several key components: + +### 1. Real-time Aggregation + +In a world where data is continuously flowing, being able to efficiently precompute model inputs is invaluable. With Kaskada's real-time aggregation, you can effortlessly: + +- Connect with multiple data streams using our robust data connectors. +- Transform data on-the-go, ensuring that the model receives the most relevant inputs. +- Perform complex aggregations to derive meaningful insights from streams of data, making sure your AI models always have the most pertinent information. +- Pause and resume aggregations in the event of process termination. + +The result? Faster decision-making, timely insights, and AI models that are always a step ahead. + +### 2. Event Detection + +Real-time event detection can mean the difference between catching an anomaly and letting it slip through the cracks. The New Kaskada’s event detection system is designed to: + +- Expressively describe complex cross-event and cross-entity conditions to use as triggers. +- Identify important activities and patterns as they occur, ensuring nothing goes unnoticed. +- Trigger proactive AI behaviors, allowing for immediate actions or notifications based on the detected events. + +From spotting fraudulent activities to identifying high-priority user behaviors, Kaskada ensures that important activities are always on your radar. + +### 3. History Replay + +Past data holds the keys to effective future decisions. With Kaskada's history replay, you can: + +- Backtest AI models by revisiting historical data points. +- Fine-tune models using per-example time travel, ensuring your models are always optimized based on past and present data. +- Use point-in-time joins to seamlessly merge data from different data sources at a single point in history, unlocking deeper insights and more accurate predictions. + +Kaskada ties together the modern real-time AI stack, providing a data foundation for developing and operating AI applications. + +## Join the Community + +We believe in the transformative power of real-time AI and the possibilities it holds. We believe that real-time data will allow AI to go beyond question-answering to provide proactive, intelligent applications. We want to hear what excites you about real-time and generative AI - [Join our Slack community](https://kaskada.io/community/) and share your use cases, insights and experiences with the New Kaskada. + +*"Real-Time AI without the fuss."* Embrace the future with Kaskada. \ No newline at end of file diff --git a/python/docs/examples/_metadata.yml b/python/docs/examples/_metadata.yml new file mode 100644 index 000000000..dc16c1f14 --- /dev/null +++ b/python/docs/examples/_metadata.yml @@ -0,0 +1,7 @@ +filters: + - include-code-files + +format: + html: + link-external-icon: true + link-external-newwindow: true diff --git a/python/docs/examples/bluesky.md b/python/docs/examples/bluesky.md new file mode 100644 index 000000000..4b6b97081 --- /dev/null +++ b/python/docs/examples/bluesky.md @@ -0,0 +1,54 @@ +--- +title: Bluesky Firehose Example +subtitle: | + Read and aggregate messages from the Bluesky firehose. Use Kaskada to connect in real-time and parse messages as part of the query. +order: 2 +--- + +Bluesky is a "distributed social network" that aims to improve on some of the perceived shortcomings of X (nee Twitter). +Bluesky uses a distributed protocol name the [AT Protocol](https://atproto.com/) to exchange messages between users, and provides a "firehose" delivering every message sent over the protocol in real-time. + +In this example, we'll show how you can receive and process the firehose using Kaskada. + +You can see the full example in the file [bluesky.py](https://github.com/kaskada-ai/kaskada/blob/main/python/docs/source/examples/bluesky.py). + +## Setup the event data source + +Before we can receive events from Bluesky, we need to create a data source to tell Kaskada how to handle the events. +We'll provide a schema and configure the time and entity fields. + +```{.python include="bluesky.py" code-line-numbers="true" start-line=26 end-line=53 dedent=4} +``` + +## Define the incoming event handler + +The `atproto` python library takes care of requesting and receiving events from Bluesky, all you need to do is create a handler to configure what to do with each event. +This handler parses the message to find [Commit](https://atproto.com/specs/repository#commit-objects) events. +For each Commit, we'll parse out any [Post](https://atproto.com/blog/create-post#post-record-structure) messages. +Finally we do some schema munging to get the Post into the event format we described when creating the data source. + +```{.python include="bluesky.py" code-line-numbers="true" start-line=55 end-line=79 dedent=4} +``` + +## Construct a real-time query and result handler + +Now we can use Kaskada to transform the events as they arrive. +First we'll use `with_key` to regroup events by language, then we'll apply a simple `count` aggregation. +Finally, we create a handler for the transformed results - here just printing them out. + + +```{.python include="bluesky.py" code-line-numbers="true" start-line=81 end-line=89 dedent=4} +``` + +## Final touches + +Now we just need to kick it all off by calling `asyncio.gather` on the two handler coroutines. This kicks off all the async processing. + +```{.python include="bluesky.py" code-line-numbers="true" start-line=91 end-line=92 dedent=4} +``` + +Try running it yourself and playing different transformations! + +```bash +python bluesky.py +``` diff --git a/python/docs/examples/bluesky.py b/python/docs/examples/bluesky.py new file mode 100644 index 000000000..447b2dd8a --- /dev/null +++ b/python/docs/examples/bluesky.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python +# +# Bluesky Kaskada Consumer +# +# This script demonstrates the use of Kaskada to consume and compute over +# the BlueSky firehose. + +import asyncio +import time + +import kaskada as kd +import pyarrow as pa +from atproto import CAR, AtUri, models +from atproto.firehose import ( + AsyncFirehoseSubscribeReposClient, + parse_subscribe_repos_message, +) +from atproto.xrpc_client.models import get_or_create, ids, is_record_type + + +async def main(): + # Initialize the Kaskada session so we can use it for stream processing + kd.init_session() + + # Create the BlueSky (At protocol) client. + # The firehose doesn't (currently) require authentication. + at_client = AsyncFirehoseSubscribeReposClient() + + # Setup the data source. + # This defintes (most of) the schema of the events we'll receive, + # and tells Kaskada which fields to use for time and initial entity. + # + # We'll push events into this source as they arrive in real-time. + posts = kd.sources.PyDict( + rows=[], + schema=pa.schema( + [ + pa.field( + "record", + pa.struct( + [ + pa.field("created_at", pa.string()), + pa.field("text", pa.string()), + # pa.field("embed", pa.struct([...])), + pa.field("entities", pa.string()), + # pa.field("facets", pa.list_(...)), + pa.field("labels", pa.float64()), + pa.field("langs", pa.list_(pa.string())), + # pa.field("reply", pa.struct([...])), + pa.field("py_type", pa.string()), + ] + ), + ), + pa.field("uri", pa.string()), + pa.field("cid", pa.string()), + pa.field("author", pa.string()), + pa.field("ts", pa.float64()), + ] + ), + time_column="ts", + key_column="author", + time_unit="s", + ) + + # Handler for newly-arrived messages from BlueSky. + async def receive_at(message) -> None: + # Extract the contents of the message and bail if it's not a "commit" + commit = parse_subscribe_repos_message(message) + if not isinstance(commit, models.ComAtprotoSyncSubscribeRepos.Commit): + return + + # Get the operations included in the message + ops = _get_ops_by_type(commit) + for new_post in ops["posts"]["created"]: + # The atproto library's use of schemas is sort of confusing + # This isn't always the expected type and I'm not sure why... + if not isinstance(new_post["record"], models.app.bsky.feed.post.Main): + continue + + # The parsing produces a hot mess of incompatible types, so we build + # a dict from scratch to simplify. + posts.add_rows({ + "record": dict(new_post["record"]), + "uri": new_post["uri"], + "cid": new_post["cid"], + "author": new_post["author"], + "ts": time.time(), + }) + + # Handler for values emitted by Kaskada. + async def receive_outputs(): + # We'll perform a very simple aggregation - key by language and count. + posts_by_first_lang = posts.with_key(posts.col("record").col("langs").index(0)) + + # Consume outputs as they're generated and print to STDOUT. + async for row in posts_by_first_lang.count().run_iter(kind="row", mode="live"): + print(f"{row['_key']} has posted {row['result']} times since startup") + + # Kickoff the two async processes concurrently. + await asyncio.gather(at_client.start(receive_at), receive_outputs()) + + +# Copied from https://raw.githubusercontent.com/MarshalX/atproto/main/examples/firehose/process_commits.py +def _get_ops_by_type( # noqa: C901, E302 + commit: models.ComAtprotoSyncSubscribeRepos.Commit, +) -> dict: # noqa: C901, E302 + operation_by_type = { + "posts": {"created": [], "deleted": []}, + "reposts": {"created": [], "deleted": []}, + "likes": {"created": [], "deleted": []}, + "follows": {"created": [], "deleted": []}, + } + + car = CAR.from_bytes(commit.blocks) + for op in commit.ops: + uri = AtUri.from_str(f"at://{commit.repo}/{op.path}") + + if op.action == "update": + # not supported yet + continue + + if op.action == "create": + if not op.cid: + continue + + create_info = {"uri": str(uri), "cid": str(op.cid), "author": commit.repo} + + record_raw_data = car.blocks.get(op.cid) + if not record_raw_data: + continue + + record = get_or_create(record_raw_data, strict=False) + if uri.collection == ids.AppBskyFeedLike and is_record_type( + record, ids.AppBskyFeedLike + ): + operation_by_type["likes"]["created"].append( + {"record": record, **create_info} + ) + elif uri.collection == ids.AppBskyFeedPost and is_record_type( + record, ids.AppBskyFeedPost + ): + operation_by_type["posts"]["created"].append( + {"record": record, **create_info} + ) + elif uri.collection == ids.AppBskyFeedRepost and is_record_type( + record, ids.AppBskyFeedRepost + ): + operation_by_type["reposts"]["created"].append( + {"record": record, **create_info} + ) + elif uri.collection == ids.AppBskyGraphFollow and is_record_type( + record, ids.AppBskyGraphFollow + ): + operation_by_type["follows"]["created"].append( + {"record": record, **create_info} + ) + + if op.action == "delete": + if uri.collection == ids.AppBskyFeedLike: + operation_by_type["likes"]["deleted"].append({"uri": str(uri)}) + elif uri.collection == ids.AppBskyFeedPost: + operation_by_type["posts"]["deleted"].append({"uri": str(uri)}) + elif uri.collection == ids.AppBskyFeedRepost: + operation_by_type["reposts"]["deleted"].append({"uri": str(uri)}) + elif uri.collection == ids.AppBskyGraphFollow: + operation_by_type["follows"]["deleted"].append({"uri": str(uri)}) + + return operation_by_type + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/python/docs/examples/index.qmd b/python/docs/examples/index.qmd new file mode 100644 index 000000000..b325ba517 --- /dev/null +++ b/python/docs/examples/index.qmd @@ -0,0 +1,7 @@ +--- +title: Examples +listing: + type: default + sort: order + fields: [title, subtitle, reading-time, categories] +--- diff --git a/python/docs/examples/reddit.md b/python/docs/examples/reddit.md new file mode 100644 index 000000000..9e7516f38 --- /dev/null +++ b/python/docs/examples/reddit.md @@ -0,0 +1,73 @@ +# Reddit Live Example + +In this example, we'll show how you can receive and process Reddit comments using Kaskada. + +You can see the full example in the file [reddit.py](https://github.com/kaskada-ai/kaskada/blob/main/python/docs/source/examples/reddit.py). + +## Setup Reddit credentials + +Follow Reddit's [First Steps](https://github.com/reddit-archive/reddit/wiki/OAuth2-Quick-Start-Example#first-steps) guide to create an App and obtain a client ID and secret. +The "script" type application is sufficient for this example. + +## Setup the event data source + +Before we can receive events from Reddit, we need to create a data source to tell Kaskada how to handle the events. +We'll provide a schema and configure the time and entity fields. + +```{literalinclude} reddit.py +:language: python +:start-after: "[start_setup]" +:end-before: "[end_setup]" +:linenos: +:lineno-match: +:dedent: 4 +``` + +## Define the incoming event handler + +The `asyncpraw` python library takes care of requesting and receiving events from Reddit, all you need to do is create a handler to configure what to do with each event. +This handler converts [Comment](https://praw.readthedocs.io/en/stable/code_overview/models/comment.html#praw.models.Comment) messages into a dict, and passes the dict to Kaskada. + +```{literalinclude} reddit.py +:language: python +:start-after: "[start_incoming]" +:end-before: "[end_incoming]" +:linenos: +:lineno-match: +:dedent: 4 +``` + +## Construct a real-time query and result handler + +Now we can use Kaskada to transform the events as they arrive. +First we'll use `with_key` to regroup events by author, then we'll apply a simple `count` aggregation. +Finally, we create a handler for the transformed results - here just printing them out. + + +```{literalinclude} reddit.py +:language: python +:start-after: "[start_result]" +:end-before: "[end_result]" +:linenos: +:lineno-match: +:dedent: 4 +``` + +## Final touches + +Now we just need to kick it all off by calling `asyncio.gather` on the two handler coroutines. This kicks off all the async processing. + +```{literalinclude} reddit.py +:start-after: "[start_run]" +:end-before: "[end_run]" +:language: python +:linenos: +:lineno-match: +:dedent: 4 +``` + +Try running it yourself and playing different transformations! + +```bash +python reddit.py +``` diff --git a/python/docs/examples/reddit.py b/python/docs/examples/reddit.py new file mode 100644 index 000000000..62a0d372f --- /dev/null +++ b/python/docs/examples/reddit.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# +# Reddit Kaskada Consumer +# +# This script demonstrates the use of Kaskada to consume and compute over +# Reddit updates. + +import asyncio +import os +import time + +import asyncpraw +import kaskada as kd +import pyarrow as pa + + +async def main(): + # Initialize the Kaskada session so we can use it for stream processing + kd.init_session() + + # Create the Reddit client. + reddit = asyncpraw.Reddit( + client_id=os.getenv("REDDIT_CLIENT_ID"), + client_secret=os.getenv("REDDIT_CLIENT_SECRET"), + user_agent=os.getenv("REDDIT_USER_AGENT", "kaskada-demo"), + ) + + # [start_setup] + # Setup the data source. + # This defintes (most of) the schema of the events we'll receive, + # and tells Kaskada which fields to use for time and initial entity. + # + # We'll push events into this source as they arrive in real-time. + comments = kd.sources.PyDict( + schema=pa.schema( + [ + pa.field("author", pa.string()), + pa.field("body", pa.string()), + pa.field("permalink", pa.string()), + pa.field("submission_id", pa.string()), + pa.field("subreddit", pa.string()), + pa.field("ts", pa.float64()), + ] + ), + time_column="ts", + key_column="submission_id", + time_unit="s", + ) + # [end_setup] + + # [start_incoming] + # Handler to receive new comments as they're created + async def receive_comments(): + # Creat the subreddit handle + sr = await reddit.subreddit(os.getenv("SUBREDDIT", "all")) + + # Consume the stream of new comments + async for comment in sr.stream.comments(): + # Add each comment to the Kaskada data source + await comments.add_rows( + { + "author": comment.author.name, + "body": comment.body, + "permalink": comment.permalink, + "submission_id": comment.submission.id, + "subreddit_id": comment.subreddit.display_name, + "ts": time.time(), + } + ) + + # [end_incoming] + + # [start_result] + # Handler for values emitted by Kaskada. + async def receive_outputs(): + # We'll perform a very simple aggregation - key by author and count. + comments_by_author = comments.with_key(comments.col("author")) + + # Consume outputs as they're generated and print to STDOUT. + async for row in comments_by_author.count().run_iter(kind="row", mode="live"): + print(f"{row['_key']} has posted {row['result']} times since startup") + + # [end_result] + + # [start_run] + # Kickoff the two async processes concurrently. + await asyncio.gather(receive_comments(), receive_outputs()) + # [end_run] + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/python/docs/examples/time_centric.ipynb b/python/docs/examples/time_centric.ipynb new file mode 100644 index 000000000..5935cba1a --- /dev/null +++ b/python/docs/examples/time_centric.ipynb @@ -0,0 +1,357 @@ +{ + "cells": [ + { + "cell_type": "raw", + "id": "cbf72170", + "metadata": {}, + "source": [ + "---\n", + "title: \"Time-centric Calculations\"\n", + "subtitle: \"Work with time and produce past training examples and recent results for applying models.\"\n", + "order: 1\n", + "---" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "5a20a51f", + "metadata": { + "id": "5a20a51f" + }, + "source": [ + "Kaskada was built to process and perform temporal calculations on event streams,\n", + "with real-time analytics and machine learning in mind. It is not exclusively for\n", + "real-time applications, but Kaskada excels at time-centric computations and\n", + "aggregations on event-based data.\n", + "\n", + "For example, let's say you're building a user analytics dashboard at an\n", + "ecommerce retailer. You have event streams showing all actions the user has\n", + "taken, and you'd like to include in the dashboard:\n", + "\n", + "* the total number of events the user has ever generated\n", + "* the total number of purchases the user has made\n", + "* the total revenue from the user\n", + "* the number of purchases made by the user today\n", + "* the total revenue from the user today\n", + "* the number of events the user has generated in the past hour\n", + "\n", + "Because the calculations needed here are a mix of hourly, daily, and over all of\n", + "history, more than one type of event aggregation needs to happen. Table-centric\n", + "tools like those based on SQL would require multiple JOINs and window functions,\n", + "which would be spread over multiple queries or CTEs. \n", + "\n", + "Kaskada was designed for these types of time-centric calculations, so we can do\n", + "each of the calculations in the list in one line:\n", + "\n", + "```python\n", + "record({\n", + " \"event_count_total\": DemoEvents.count(),\n", + " \"purchases_total_count\": DemoEvents.filter(DemoEvents.col(\"event_name\").eq(\"purchase\")).count(),\n", + " \"revenue_total\": DemoEvents.col(\"revenue\").sum(),\n", + " \"purchases_daily\": DemoEvents.filter(DemoEvents.col(\"event_name\").eq(\"purchase\")).count(window=Daily()),\n", + " \"revenue_daily\": DemoEvents.col(\"revenue\").sum(window=Daily()),\n", + " \"event_count_hourly\": DemoEvents.count(window=Hourly()),\n", + "})\n", + "```\n", + "\n", + "::: {.callout-warning}\n", + "The previous example demonstrates the use of `Daily()` and `Hourly()` windowing which aren't yet part of the new Python library.\n", + ":::\n", + "\n", + "Of course, a few more lines of code are needed to put these calculations to work,\n", + "but these six lines are all that is needed to specify the calculations\n", + "themselves. Each line may specify:\n", + "\n", + "* the name of a calculation (e.g. `event_count_total`)\n", + "* the input data to start with (e.g. `DemoEvents`)\n", + "* selecting event fields (e.g. `DemoEvents.col(\"revenue\")`)\n", + "* function calls (e.g. `count()`)\n", + "* event filtering (e.g. `filter(DemoEvents.col(\"event_name\").eq(\"purchase\"))`)\n", + "* time windows to calculate over (e.g. `window=Daily()`)\n", + "\n", + "...with consecutive steps chained together in a familiar way.\n", + "\n", + "Because Kaskada was built for time-centric calculations on event-based data, a\n", + "calculation we might describe as \"total number of purchase events for the user\"\n", + "can be defined in Kaskada in roughly the same number of terms as the verbal\n", + "description itself.\n", + "\n", + "Continue through the demo below to find out how it works.\n", + "\n", + "See [the Kaskada documentation](../guide/index) for lots more information." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "BJ2EE9mSGtGB", + "metadata": { + "id": "BJ2EE9mSGtGB" + }, + "source": [ + "## Kaskada Client Setup\n", + "\n", + "```\n", + "%pip install kaskada>=0.6.0-a.0\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "37db47ba", + "metadata": { + "tags": [ + "hide-output" + ] + }, + "outputs": [], + "source": [ + "import kaskada as kd\n", + "\n", + "kd.init_session()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "5b838eef", + "metadata": {}, + "source": [ + "## Example dataset\n", + "\n", + "For this demo, we'll use a very small example data set, which, for simplicity and portability of this demo notebook, we'll read from a string.\n", + "\n", + "```{note}\n", + "For simplicity, instead of a CSV file or other file format we read and then parse data from a CSV string.\n", + "You can load your own event data from many common sources, including Pandas DataFrames and Parquet files.\n", + "See {py:mod}`kaskada.sources` for more information on the available sources.\n", + "```" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ba4bb6b6", + "metadata": {}, + "outputs": [], + "source": [ + "import asyncio\n", + "\n", + "# For demo simplicity, instead of a CSV file, we read and then parse data from a\n", + "# CSV string. Kaskada\n", + "event_data_string = \"\"\"\n", + " event_id,event_at,entity_id,event_name,revenue\n", + " ev_00001,2022-01-01 22:01:00,user_001,login,0\n", + " ev_00002,2022-01-01 22:05:00,user_001,view_item,0\n", + " ev_00003,2022-01-01 22:20:00,user_001,view_item,0\n", + " ev_00004,2022-01-01 23:10:00,user_001,view_item,0\n", + " ev_00005,2022-01-01 23:20:00,user_001,view_item,0\n", + " ev_00006,2022-01-01 23:40:00,user_001,purchase,12.50\n", + " ev_00007,2022-01-01 23:45:00,user_001,view_item,0\n", + " ev_00008,2022-01-01 23:59:00,user_001,view_item,0\n", + " ev_00009,2022-01-02 05:30:00,user_001,login,0\n", + " ev_00010,2022-01-02 05:35:00,user_001,view_item,0\n", + " ev_00011,2022-01-02 05:45:00,user_001,view_item,0\n", + " ev_00012,2022-01-02 06:10:00,user_001,view_item,0\n", + " ev_00013,2022-01-02 06:15:00,user_001,view_item,0\n", + " ev_00014,2022-01-02 06:25:00,user_001,purchase,25\n", + " ev_00015,2022-01-02 06:30:00,user_001,view_item,0\n", + " ev_00016,2022-01-02 06:31:00,user_001,purchase,5.75\n", + " ev_00017,2022-01-02 07:01:00,user_001,view_item,0\n", + " ev_00018,2022-01-01 22:17:00,user_002,view_item,0\n", + " ev_00019,2022-01-01 22:18:00,user_002,view_item,0\n", + " ev_00020,2022-01-01 22:20:00,user_002,view_item,0\n", + "\"\"\"\n", + "\n", + "events = await kd.sources.CsvString.create(\n", + " event_data_string, time_column=\"event_at\", key_column=\"entity_id\"\n", + ")\n", + "\n", + "# Inspect the event data\n", + "events.preview()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "568d1272", + "metadata": {}, + "source": [ + "## Define queries and calculations" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "c2c5a298", + "metadata": {}, + "source": [ + "Kaskada queries are defined in Python, using the `{py}Timestream` class.\n", + "Sources are Timestreams generally containing [records](../guide/data_types.qmd#record-types).\n", + "\n", + "Let's do a simple query for events for a specific entity ID.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bce22e47", + "metadata": {}, + "outputs": [], + "source": [ + "events.filter(events.col(\"entity_id\").eq(\"user_002\")).preview()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "6b5f2725", + "metadata": {}, + "source": [ + "\n", + "Beyond querying for events, Kaskada has a powerful syntax for defining\n", + "calculations on events, temporally across history.\n", + "\n", + "The six calculations discussed at the top of this demo notebook are below.\n", + "\n", + "(Note that some functions return `NaN` if no events for that user have occurred\n", + "within the time window.)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3ad6d596", + "metadata": {}, + "outputs": [], + "source": [ + "purchases = events.filter(events.col(\"event_name\").eq(\"purchase\"))\n", + "\n", + "features = kd.record(\n", + " {\n", + " \"event_count_total\": events.count(),\n", + " # \"event_count_hourly\": events.count(window=Hourly()),\n", + " \"purchases_total_count\": purchases.count(),\n", + " # \"purchases_today\": purchases.count(window=Since(Daily()),\n", + " # \"revenue_today\": events.col(\"revenue\").sum(window=Since(Daily())),\n", + " \"revenue_total\": events.col(\"revenue\").sum(),\n", + " }\n", + ")\n", + "features.preview()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "1c315938", + "metadata": {}, + "source": [ + "## At Any Time\n", + "\n", + "A key feature of Kaskada's time-centric design is the ability to query for\n", + "calculation values at any point in time. Traditional query languages (e.g. SQL)\n", + "can only return data that already exists---if we want to return a row of\n", + "computed/aggregated data, we have to compute the row first, then return it. As a\n", + "specific example, suppose we have SQL queries that produce daily aggregations\n", + "over event data, and now we want to have the same aggregations on an hourly\n", + "basis. In SQL, we would need to write new queries for hourly aggregations; the\n", + "queries would look very similar to the daily ones, but they would still be\n", + "different queries.\n", + "\n", + "With Kaskada, we can define the calculations once, and then specify the points\n", + "in time at which we want to know the calculation values when we query them.\n", + "\n", + "In the examples so far, we have used `preview()` to get a DataFrame containing\n", + "some of the rows from the Timestreams we've defined. By default, this produces\n", + "a _history_ containing all the times the result changed. This is useful for\n", + "using past values to create training examples.\n", + "\n", + "We can also execute the query for the values at a specific point in time." + ] + }, + { + "cell_type": "markdown", + "id": "082e174d", + "metadata": { + "tags": [ + "hide-output" + ] + }, + "source": [ + "```\n", + "features.preview(at=\"2022-01-01 22:00\")\n", + "``````" + ] + }, + { + "cell_type": "markdown", + "id": "5a44c5f7", + "metadata": {}, + "source": [ + "You can also compose a query that produces values at specific points in time.\n", + "\n", + "```\n", + "features.when(hourly())\n", + "```\n", + "\n", + "Regardless of the time cadence of the calculations themselves, the query output\n", + "can contain rows for whatever time points you specify. You can define a set of\n", + "daily calculations and then get hourly updates during the day. Or, you can\n", + "publish the definitions of some features in a Python module and different users\n", + "can query those same calculations for hourly, daily, and monthly\n", + "values---without editing the calculation definitions themselves.\n", + "\n", + "## Adding more calculations to the query\n", + "\n", + "We can add two new calculations, also in one line each, representing:\n", + "\n", + "* the time of the user's first event\n", + "* the time of the user's last event\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "2ba09e77-0fdf-43f4-960b-50a126262ec7", + "metadata": { + "id": "2ba09e77-0fdf-43f4-960b-50a126262ec7" + }, + "source": [ + "This is only a small sample of possible Kaskada queries and capabilities. See\n", + "everything that's possible with [Timestreams](../reference/Timestream/index.qmd)." + ] + } + ], + "metadata": { + "colab": { + "collapsed_sections": [ + "6924ca3e-28b3-4f93-b0cf-5f8afddc11d8", + "936700a9-e042-401c-9156-7bb18652e109", + "08f5921d-36dc-41d1-a2a6-ae800b7a11de" + ], + "private_outputs": true, + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/python/docs/guide/_metadata.yml b/python/docs/guide/_metadata.yml new file mode 100644 index 000000000..ffbf12790 --- /dev/null +++ b/python/docs/guide/_metadata.yml @@ -0,0 +1,10 @@ +execute: + daemon: false + warning: false + +format: + html: + link-external-icon: true + link-external-newwindow: true + +jupyter: python3 \ No newline at end of file diff --git a/python/docs/guide/aggregation.qmd b/python/docs/guide/aggregation.qmd new file mode 100644 index 000000000..86a8f4c84 --- /dev/null +++ b/python/docs/guide/aggregation.qmd @@ -0,0 +1,41 @@ +--- +title: Aggregations +--- + +Aggregations are _cumulative_, _grouped_, and _windowed_. + +Cumulative +: They reflect all values up to and including the current time. + +Grouped +: They reflect the values for each entity separately. + +Windowed +: They reflect the values within a specific [](`kaskada.windows.Window`). + +While most functions operate on specific points in the Timestream, aggregation functions operate on many points. +Generally, the result of an aggregation represents the result for each key up to and including the current time. + +## Windowing +Aggregations may be configured to operate in a specific time window by providing a `window` argument. +If no window is specified, the aggregation is over all rows for the entity, up to and including the current time. +If a window is provided, the result of an aggregation is the result for that entity in the current window up to and including the current time. +Aggregations produce cumulative results up to each point in time, so the result at a given point in time may represent an incomplete window. + +```{.python filename="Cumulative aggregation since the start of the day."} +Purchases.sum(window = kd.windows.Since.daily()) +``` + +The [windows reference](../reference/Windows/index.qmd) has information on the supported kinds of windows. + +## Repeated Aggregation + +Events may be aggregated multiple times. +The events themselves are a sequence of timestamped data for each entity. +The result of the first aggregation is the same — a sequence of timestamped data for each entity. +Applying an additional aggregation simply aggregates over those times. +We can compute the maximum of the average purchase amounts. + +```{.python filename="Repeated aggregation computing the maximum of the average purchases."} +Purchases.col("amount").mean().max() +``` \ No newline at end of file diff --git a/python/docs/guide/data_types.qmd b/python/docs/guide/data_types.qmd new file mode 100644 index 000000000..c33cbce55 --- /dev/null +++ b/python/docs/guide/data_types.qmd @@ -0,0 +1,84 @@ +--- +title: Data Types + +listing: + - id: types + template: ../_templates/data_types_table.ejs + contents: + - data_types.yml +--- + +Kaskada operates on typed Timestreams. +Similar to how every Pandas `DataFrame` has an associated `dtype`, every Kaskada `Timestream` has an associated [PyArrow data type](https://arrow.apache.org/docs/python/api/datatypes.html) returned by [](`kaskada.Timestream.data_type`). +The set of supported types is based on the types supported by [Apache Arrow](https://arrow.apache.org/). + +Each `Timestream` contains points of the corresponding type. +We'll often say that the "type" of a `Timestream` is the type of the values it contains. + +Kaskada's type system describes several kinds of values. +Scalar types correspond to simple values, such as the string `"hello"` or the integer `57`. +They correspond to a stream containing values of the given type, or `null`. +Composite types are created from other types. +For instance, records may be created using scalar and other composite types as fields. +An expression producing a record type is a stream that produces a value of the given record type or `null`. + +## Scalar Types + +Scalar types include booleans, numbers, strings, timestamps, durations and calendar intervals. + +::: {#types} +::: + +## Record Types + +Records allow combining 1 or more values of potentially different types into a single value. +Records are unnamed - any two records with the same set of field names and value types are considered equal. Fields within a record may have different types. +Field names must start with a letter. + +For example, `{name: string, age: u32 }` is a record type with two fields and `{name: 'Ben', age: 33 }` is corresponding value. + +NOTE: Record types may be nested. + +## Collection Types + +Kaskada also supports collections -- lists and maps. + +The type `list` describes a list of elements of type `T`. +For example, `list` is a list of 64-bit integers. + +Similarly, `map` describes a map containing keys of type `K` and values of type `V`. +For example, `map` is a map from strings to 64-bit integers. + +## Type Coercion +Kaskada implicitly coerces numeric types when different kinds of numbers are combined. +For example adding a 64-bit signed integer value to a 32-bit floating point value produces a 64-point floating point value + +Type coercion will never produce an integer overflow or reduction in numeric precision. +If needed, such conversions must be explicitly specified using `as`. + +The coercion rules can be summarized with the following rules: + +1. Unsigned integers can be widened: `u8` ⇨ `u16` ⇨ `u32` ⇨ `u64`. +2. Integers can be widened: `i8` ⇨ `i16` ⇨ `i32` ⇨ `i64`. +3. Floating point numbers can be widened: `f16` ⇨ `f32` ⇨ `f64`. +4. Unsigned integers can be promoted to the next wider integer `u8` ⇨ `i16`, `u16` ⇨ `i32`, `u32` ⇨ `i64`. +5. All numbers may be converted to `f64`. +6. Strings may be implicitly converted to timestamps by attempting to parse them as RFC3339 values. +The timestamp will be null for strings that don't successfully parse. + +One aspect of the coercion rules is that when an operation is applied to two different numeric types the result may be a third type which they may both be coerced to. +The type promotion table shows the type resulting from a binary operation involving two different numeric types. + +| | `u8` | `u16` | `u32` | `u64` | `i8` | `i16` | `i32` | `i64` | `f16` | `f32` | `f64` | +| --------- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | ----- | +| **`u8`** | `u8` | `u16` | `u32` | `u64` | `i16` | `i16` | `i32` | `i64` | `f16` | `f32` | `f64` | +| **`u16`** | `u16` | `u16` | `u32` | `u64` | `i32` | `i32` | `i32` | `i64` | `f16` | `f32` | `f64` | +| **`u32`** | `u32` | `u32` | `u32` | `u64` | `i64` | `i64` | `i64` | `i64` | `f32` | `f32` | `f64` | +| **`u64`** | `u64` | `u64` | `u64` | `u64` | `f64` | `f64` | `f64` | `f64` | `f64` | `f64` | `f64` | +| **`i8`** | `i16` | `i32` | `i64` | `f64` | `i8` | `i16` | `i32` | `i64` | `f16` | `f32` | `f64` | +| **`i16`** | `i16` | `i32` | `i64` | `f64` | `i16` | `i16` | `i32` | `i64` | `f16` | `f32` | `f64` | +| **`i32`** | `i32` | `i32` | `i64` | `f64` | `i32` | `i32` | `i32` | `i64` | `f16` | `f32` | `f64` | +| **`i64`** | `i64` | `i64` | `i64` | `f64` | `i64` | `i64` | `i64` | `i64` | `f16` | `f32` | `f64` | +| **`f16`** | `f16` | `f16` | `f16` | `f16` | `f16` | `f16` | `f16` | `f16` | `f16` | `f32` | `f64` | +| **`f32`** | `f32` | `f32` | `f32` | `f32` | `f32` | `f32` | `f32` | `f32` | `f32` | `f32` | `f64` | +| **`f64`** | `f64` | `f64` | `f64` | `f64` | `f64` | `f64` | `f64` | `f64` | `f64` | `f64` | `f64` | \ No newline at end of file diff --git a/python/docs/guide/data_types.yml b/python/docs/guide/data_types.yml new file mode 100644 index 000000000..7a5baceb8 --- /dev/null +++ b/python/docs/guide/data_types.yml @@ -0,0 +1,31 @@ +- types: [bool] + desc: Booleans represent true or false. + examples: [true, false] +- types: [u8, u16, u32, u64] + desc: Unsigned integer numbers of the specified bit width. + examples: [0, 1, 1000] +- types: [i8, i16, i32, i64] + desc: Signed integer numbers of the specified bit width. + examples: [0, 1, -100] +- types: [f32, f64] + desc: Floating point numbers of the specified bit width. + examples: [0, 1, -100, 1000, 0.0, -1.0, -100837.631] +- types: [str] + desc: Unicode strings. + examples: ["hello", "hi 'bob'"] +- types: [timestamp_s, timestamp_ms, timestamp_us, timestamp_ns] + desc: | + Points in time relative the Unix Epoch (00:00:00 UTC on January 1, 1970). + Time unit may be seconds (s), milliseconds (ms), microseconds (us) or nanoseconds (ns). + examples: [1639595174 as timestamp_s] +- types: [duration_s, duration_ms, duration_us, duration_ns] + desc: | + A duration of a fixed amount of a specific time unit. + Time unit may be seconds (s), milliseconds (ms), microseconds (us) or nanoseconds (ns). + examples: [-100 as duration_ms] +- types: [interval_days, interval_months] + desc: | + A calendar interval corresponding to the given amount of the corresponding time. + The length of an interval depends on the point in time it is added to. + For instance, adding 1 `interval_month` to a timestamp will shift to the same day of the next month. + examples: [1 as interval_days, -100 as interval_months] diff --git a/python/docs/guide/entities.qmd b/python/docs/guide/entities.qmd new file mode 100644 index 000000000..70c0c7c1c --- /dev/null +++ b/python/docs/guide/entities.qmd @@ -0,0 +1,96 @@ +--- +title: Entities and Grouping +--- + +Entities organize data for use in feature engineering. +They describe the particular objects that a prediction will be made for. +The result of a feature computation is a _feature vector_ for each entity at various points in time. + +## What is an Entity? +Entities represent the categories or "nouns" associated with the data. +They can generally be thought of as any category of object related to the events being processed. +For example, when manipulating purchase events, there may be entities for the customers, vendors and items being purchased. +Each purchase event may be related to a customer, a vendor, and one or more items. + +If something can be given a name or other unique identifier, it can likely be used as an entity. +In a relational database, an entity would be anything that is identified by the same key in a set of tables. + +## What is an Entity Key? +An entity kind is a category of objects, for example customer or vendor. +An entity key identifies a unique instance of that category -- a `customer_id` or a `vendor_id`. + +One may think of an entity as a table containing instances -- or rows -- of that type of entity. +The entity key would be the primary key of that table. + +The following table shows some example entities and possible keys. +Many of the example instances may not be suitable for use as the entity key, for the same reason you wouldn't use them as a primary key. +For example, using `Vancouver` to identify cities would lead to ambiguity between Vancouver in British Columbia and Vancouver in Washington State. +In these cases, you'd likely use some other identifier for instances. +Others may be useful, such as using the airport code. + +| Example Entity | Example Entity Instance | +|-|-| +|Houses|1600 Pennsylvania Avenue| +|Airports|SEA| +|Customers|John Doe| +|City|Vancouver| +|State|Washington| + +: Example Entities and corresponding keys. + +## Entities and Aggregation + +Many, if not all, Kaskada queries involve aggregating events to produce values. +Entities provide an implicit grouping for the aggregation. +When we write `sum(Purchases.amount)` it is an aggregation that returns the sum of purchases made _by each entity_. +This is helpful since the _feature vector_ for an entity will depend only on events related to that entity. + + + +```{python} +# | code-fold: true + +import asyncio +import kaskada as kd +kd.init_session() +data = "\n".join( + [ + "time,key,m", + "1996-12-19T16:39:57,A,5", + "1996-12-19T17:42:57,B,8", + "1996-12-20T16:39:59,A,17", + "1996-12-23T12:18:57,B,6", + "1996-12-23T16:40:01,A,12", + ] +) +multi_entity = await kd.sources.CsvString.create(data, time_column="time", key_column="key") + +kd.plot.render( + kd.plot.Plot(multi_entity.col("m"), name="m"), + kd.plot.Plot(multi_entity.col("m").sum(), name="sum(m)") +) +``` + + +## Changing Keys + +The key associated with each point may be changed using [](`kaskada.Timestream.with_key`). +For example, given a stream of purchases associated with each user, we could create a Timestream associated with the purchased item: + +```{.python filename="Using with-key to associate purchases with items"} +purchases_by_user.with_key(purchases_by_user.col("item_id")) +``` + +This is particularly useful with the ability to [lookup](joins.qmd#explicit-lookups) values from associated with other keys. +For instance, we could re-key purchases as shown above to count the total spent on each item (across all users) and then lookup that information for each user's purchases. + +## Joining + +Joining with the same entity happens automatically. +Joining with other entities (and even other kinds of entities) is done using `lookup`. +See [Joins](joins.qmd) for more information. \ No newline at end of file diff --git a/python/docs/guide/execution.qmd b/python/docs/guide/execution.qmd new file mode 100644 index 000000000..0e5180403 --- /dev/null +++ b/python/docs/guide/execution.qmd @@ -0,0 +1,92 @@ +--- +title: Execution +--- + +A [Timestream](./timestreams.qmd) may be executed and written to a [destination](#destinations) in a variety of ways. +The things to consider when deciding how to execute the Timestream are: + +1. Whether you want the _history_ of points or the _snapshot_ of values for each entity at a given time. +2. Whether you want to run a query _once_ or start a _live_ process continually materializing. +3. Whether you want to limit the output to points in a specific time range (for history) or entities that have changed since a specific time (for snapshots). +4. Whether you want to stop at a given point in time. + +[State](#state) can be used to provide fault-tolerance and allow incremental processing of only new events. + +::: {.callout-tip title="Preview during development"} +While developing queries, it is often useful to view a few rows from the result. +Using [](`kaskada.Timestream.preview`) you can retrieve a small set of rows from the result set as a Pandas DataFrame. +::: + +## History vs. Snapshot + +Executing a Timestream for the history outputs every point in the Timestream. +This means that each entity likely appears in the output multiple times. +This is particularly useful for creating training examples from past data points, or visualizing how the Timestream has changed over time. + +Executing a Timestream for a snapshot produces a value for each entity at a specific point in time. +This means that each entity appears at-most once in the results. +This is useful for maintaining a feature store based on the latest values. + +::: {.callout-note title=Todo} +Expose the configuration for snapshots. +See https://github.com/kaskada-ai/kaskada/issues/719 +::: + + +## Query vs. Materialize +Every Timestream may be executed as a single query or used to start a materialization. +Single queries are useful when you want the results for some later batch process, such as fine-tuning a model or populating an in-memory feature store. +Materialization is useful when you want to stream new results out as quickly as possible, such as maintaining an in-memory feature store or reacting to specific conditions. + + +## Changed Since + +Configuring the _changed since time_ lets you control the points or entities included in the output. + +For a historic query, only points occurring after the changed since time are included in the output. +This allows incrementally outputting the entire history to some external store, by repeatedly performing a "changed since" query. + +For a snapshot query, only entities that have changed after this time are included in the output. +This reduces the amount of data written when the past snapshot is already present in the destination. + +::: {.callout-note title=Todo} +Expose the configuration for changed since. +See https://github.com/kaskada-ai/kaskada/issues/719 +::: + +## Up To + +Configuring the _up to time_ lets you control the maximum points output (and in the case of snapshots, the time represented in the snapshot). + +For a historic query, only points occurring before or at the up to time are included in the output. +For a snapshot query, this corresponds to the time at which the snapshot will be taken. + +::: {.callout-note title=Todo} +Currently when not specified, the up to time is determined from the maximum event present in the data. +We have plans to change this to a parameter to `run` defaulting to the current time. +::: + +::: {.callout-note title=Todo} +Expose the configuration for up-to. +See https://github.com/kaskada-ai/kaskada/issues/719 +::: + +## State + +Kaskada checkpoints state during and after execution. +This provides fault-tolerance, incremental querying and automatic handling of late-data. + +When a query is executed, Kaskada determines whether it can use any of the available states to reduce the amount of processing needed. +For instance, when producing a snapshot Kaskada can use any persisted state before the earliest new event and before the time to snapshot. +Similarly, when producing a history, Kaskada can use any persisted state before the earliest new event and before the "changed since" time. + +## Destinations + +The methods [](`kaskada.Timestream.preview`) and [](`kaskada.Timestream.to_pandas`) provide the results of a query in a Pandas DataFrame for easy visualization and consumption within the Python process. + +The [](`kaskada.Timestream.run_iter`) methods provides synchronous and asynchronous iterators over the results in a variety of formats including Pandas DataFrames, PyArrow RecordBatches, and rows as Python dictionaries. +This allows you to run the entire retrieve-evaluate-respond loop within a single Python process. + +The [](`kaskada.Timestream.write`) function allows you to specify a destination from [`kaskada.destinations`](../reference/Destinations/index.qmd) for results. This supports both `once` and `live` queries. + +See the reference on [destinations](../reference/Destinations/index.qmd) for more on the supported destinations. diff --git a/python/docs/guide/index.qmd b/python/docs/guide/index.qmd new file mode 100644 index 000000000..96d5cc4a5 --- /dev/null +++ b/python/docs/guide/index.qmd @@ -0,0 +1,36 @@ +--- +title: User Guide +--- + +Understanding and reacting to the world in real-time requires understanding what is happening _now_ in the context of what happened in the past. +You need the ability to understand if what just happened is unusual, how it relates to what happened previously, and how it relates to other things that are happening at the same time. + +Kaskada processes events from streams and historic data sources to answer these questions in real-time. + +The power and convenience of Kaskad comes from a new: the Timestream. +Timestreams provide a declarative API like dataframes over the complete temporal context. +Easily combine multiple streams and reason about the complete sequence of events. +Use time-travel to compute training examples from historic data and understand how results change over time. + +## What are "Timestreams"? + +A [Timestream](timestreams.qmd) describes how a value changes over time. +In the same way that SQL queries transform tables and graph queries transform nodes and edges, Kaskada queries transform Timestreams. + +In comparison to a timeseries which often contains simple values (e.g., numeric observations) defined at fixed, periodic times (i.e., every minute), a Timestream contains any kind of data (records or collections as well as primitives) and may be defined at arbitrary times corresponding to when the events occur. + +## Getting Started with Timestreams + +Getting started with Timestreams is as simple as `pip` installing the Python library, loading some data and running a query. + +```python +import kaskada as kd + +# Read data from a Parquet file. +data = kd.sources.Parquet( + path = "path_to_file.parquet", + time_column = "time", + key_column = "user") +# Get the count of events associated with each user over time, as a dataframe. +data.count().to_pandas() +``` diff --git a/python/docs/guide/installation.qmd b/python/docs/guide/installation.qmd new file mode 100644 index 000000000..d745dd4fb --- /dev/null +++ b/python/docs/guide/installation.qmd @@ -0,0 +1,24 @@ +--- +title: Installation +--- + +To install Kaskada, you need to be using Python >= 3.8. +We suggest using 3.11 or newer, since that provides more precise error locations. + +```{.bash filename="Installing Kaskada"} +pip install kaskada>=0.6.0-a.3 +``` + +::: {.callout-warning} +This version of Kaskada is currently a pre-release, as indicated by the `-a.0` suffix. +It will not be installed by default if you `pip install kaskada`. +You need to either use `pip install --pre kaskada` or specify a specific version, as shown in the example. +::: + +::: {.callout-tip} +Depending on you Python installation and configuration you may have `pip3` instead of `pip` available in your terminal. +If you do have `pip3` replace pip with `pip3` in your command, i.e., `pip3 install kaskada`. + +If you get a permission error when running the `pip` command, you may need to run as an administrator using `sudo pip install kaskada`. +If you don't have administrator access (e.g., in Google Colab, or other hosted environments) you amy use `pip`’s `--user` flag to install the package in your user directory. +::: diff --git a/python/docs/guide/joins.qmd b/python/docs/guide/joins.qmd new file mode 100644 index 000000000..476379c00 --- /dev/null +++ b/python/docs/guide/joins.qmd @@ -0,0 +1,34 @@ +--- +title: Joins +--- + +It is often necessary to use multiple Timestreams to define a query. +Understanding user behavior requires considering their activity across a variety of event streams. +Normalizing user behavior may require looking comparing the per-user values to the average values for the region. +Both of these are accomplished by joining the Timestreams. + +## Implicit Joins +Timestreams associated with the same kind of entity -- for instance, a user -- are automatically joined. +This makes it easy to write queries that consider multiple event streams in a single query. + +```{.python filename="Joining two event streams to compute page-views per purchase"} +page_views.count() / purchases.count() +``` + +### Domains + +It is sometimes useful to consider the _domain_ of an expression. +This corresponds to the points in time and entities associated with the points in the expression. +For discrete timestreams, this corresponds to the points at which those values occur. +For continuous timestreams, this corresponds to the points at which the value changes. + +Whenever expressions with two (or more) different domains are used in the same expression they are implicitly joined. +The join is an outer join that contains an event if either (any) of the input domains contained an event. +For any input table that is continuous, the join is `as of` the time of the output, taking the latest value from that input. + +## Explicit Lookups + +Values from associated with other entities may be retrieved using [](`kaskada.Timestream.lookup`). +`left.lookup(right)` does a left-join, looking up the value from `right` for each computed key in `left`. + +Lookups are _temporally correct_ -- the value retrieved corresponds to the `right` value at the time the key occurred in `left`. \ No newline at end of file diff --git a/python/docs/guide/quickstart.qmd b/python/docs/guide/quickstart.qmd new file mode 100644 index 000000000..6e19ac96d --- /dev/null +++ b/python/docs/guide/quickstart.qmd @@ -0,0 +1,40 @@ +--- +title: Quick Start +--- + +This shows the bare minimum needed to get started with Kaskada. + +## Install + +Install the latest version. +This uses `kaskada>=0.6.0-a.3` to ensure the pre-release version is installed. + +``` +pip install kaskada>=0.6.0-a.3 +``` + +See the section on [installation](./installation.qmd) to learn more about installing Kaskada. + +## Write a query + +The following Python code imports the Kaskada library, creates a session, and loads some CSV data. +It then runs a query to produce a Pandas DataFrame. + +```{python} +import asyncio +import kaskada as kd +kd.init_session() +content = "\n".join( + [ + "time,key,m,n", + "1996-12-19T16:39:57,A,5,10", + "1996-12-19T16:39:58,B,24,3", + "1996-12-19T16:39:59,A,17,6", + "1996-12-19T16:40:00,A,,9", + "1996-12-19T16:40:01,A,12,", + "1996-12-19T16:40:02,A,,", + ] +) +source = await kd.sources.CsvString.create(content, time_column="time", key_column="key") +source.select("m", "n").extend({"sum_m": source.col("m").sum()}).to_pandas() +``` diff --git a/python/docs/guide/sources.qmd b/python/docs/guide/sources.qmd new file mode 100644 index 000000000..e19b39e8d --- /dev/null +++ b/python/docs/guide/sources.qmd @@ -0,0 +1,13 @@ +--- +title: Sources +--- + +Sources describe how events enter a Timestream. +Every source is a Timestream containing the events that have been read. +Most often, these events are [records](data_types.qmd#record-types). + +Each event from a source is associated with a specific time and entity key. +These define how the resulting Timestream is ordered and grouped. +Generally, the time and entity key are associated with a specific column from the source, using the `time_column` and `key_column` arguments. + +The [Sources Reference](../reference/Sources/index.qmd) has more details on the supported sources. \ No newline at end of file diff --git a/python/docs/guide/timestreams.qmd b/python/docs/guide/timestreams.qmd new file mode 100644 index 000000000..e34a1ed00 --- /dev/null +++ b/python/docs/guide/timestreams.qmd @@ -0,0 +1,54 @@ +--- +title: Timestreams +--- + +Kaskada is built on the concept of a _Timestream_. +Each Timestream is ordered by _time_ and partitioned by _entity_. +This makes it easy to focus on events happening over time and how aggregations change. + + + +```{python} +# | code-fold: true +# | warning: false +import asyncio +import kaskada as kd +kd.init_session() +data = "\n".join( + [ + "time,key,m", + "1996-12-19T16:39:57,A,5", + "1996-12-19T17:42:57,B,8", + "1996-12-20T16:39:59,A,17", + "1996-12-23T12:18:57,B,6", + "1996-12-23T16:40:01,A,12", + ] +) +multi_entity = await kd.sources.CsvString.create(data, time_column="time", key_column="key") + +kd.plot.render( + kd.plot.Plot(multi_entity.col("m"), name="m") +) +``` + +## Continuity + +It is useful to consider two kinds of timestreams -- _discrete_ and _continuous_. +Like the example we already saw, a discrete timestream consists of values at specific points in time. +On the other hand, a continuous timestream represents a value that continues until it changes. +While a discrete timestream contains values at specific points in time, a continuous timestream changes at specific points in time. + +For example, the result of aggregating a timestream produces a continuous stream that changes on each non-`null` input. + +```{python} +# | echo: false +# | warning: false +kd.plot.render( + kd.plot.Plot(multi_entity.col("m").sum(), name="sum(m)") +) +``` diff --git a/python/docs/guide/tour.qmd b/python/docs/guide/tour.qmd new file mode 100644 index 000000000..824d40309 --- /dev/null +++ b/python/docs/guide/tour.qmd @@ -0,0 +1,116 @@ +--- +title: Tour of Kaskada +--- + + +This provides an overview of the key features in Kaskada that enable feature engineering on event-based data. +The [Quick Start](./quickstart.qmd) has details on how you can quickly get started running Kaskada queries. +For a more complete explanation, see the User Guide. + +This tour uses Kaskada and Plotly to render the illustrations. +The initial setup / data is below. + +```{python} +# | code-fold: true +import asyncio +import kaskada as kd +kd.init_session() +single_entity = "\n".join( + [ + "time,key,m,n", + "1996-12-19T16:39:57,A,5,10", + "1996-12-20T16:39:59,A,17,6", + "1996-12-22T16:40:00,A,,9", + "1996-12-23T16:40:01,A,12,", + "1996-12-24T16:40:02,A,,", + ] +) +single_entity = await kd.sources.CsvString.create(single_entity, time_column="time", key_column="key") +``` + +## Events and Aggregations + +Every Kaskada query operates on one or more _sources_ containing events. +Every event in a source happens at a specific point in time and relates to a specific entity. +A source contains events with the same schema. +Often, each source represents a specific kind of event, such as a login event or purchase. + +It is often convenient to picture temporal data as a sequence of timestamped events. +A natural question to ask about the purchases is the total--or `sum`--of all purchases made. +This is accomplished by _aggregating_ the events. +The results of an aggregation change over time as additional events occur. + +```{python} +# | echo: false +# | warning: false + +kd.plot.render( + kd.plot.Plot(single_entity.col("m"), name="m"), + kd.plot.Plot(single_entity.col("m").sum(), name="sum of m") +) +``` + +The User Guide has [more details on aggregation](./aggregation.qmd), including how to use windows to control which events are aggregated. + +## Discrete and Continuous +We say that events (and values derived from them) are _discrete_ because they occur at specific in time. +and the results of the aggregation are [_continuous_](./timestreams.qmd#continuity). +In the example, after the purchase with amount 13 the sum was 20. +And it _continued_ to be 20 at every point in time until the next purchase was made, with amount 4. +A continuous value is inclusive of the event that causes the value to change and exclusive of the next change. + +Thus, an aggregation at a given point in time reflects all events that have happened up to (and including) that point in time. +The concept of continuity applies to many other operations in Kaskada, not just aggregations. +This is part of what we mean when we say that Kaskada is a temporal query language. + +## Grouping +Another property of Kaskada is that events are implicitly grouped by _entity_. +In the previous example, we assumed that all purchases were made by the same user. +When the purchases are made by multiple users, there is a natural grouping for the aggregation. +When computing a machine learning feature such as "total purchases", we usually wish to aggregate the events related to a specific user or entity. + +One way to understand this grouping is as a separate stream associated with each entity. +The stream of purchases for each user may be shown separately, as we do here, or it may be pictured flattened into a single stream keyed by user. +The idea of grouped streams as separate, per-entity streams is often useful for understanding the behavior of Kaskada Timestreams. + +::: {.callout-note title=Todo} +Add example of multiple entity aggregation. +::: + +The User Guide has [more details on grouping](./entities.qmd), including how to change the grouping of a Timestream. + +## History and Snapshots + +Since the Timestream describes how values are computed at every point in time, there are several useful ways they may be output. + +For training a model, it is often useful to output historic values matching some `filter`. +These historic points can then be used as training examples, allowing the model to be trained on past points. +This historic output is also useful for visualizing a Timestream at multiple points. + +For serving a model, it is often useful to output the value of a Timestream for every entity at a specific point in time. +This is most often used to output a snapshot at the current time. + +For both kinds of output, it is also useful to be able to select only the points after a specific time. +This would filter out points from the history, or limit the snapshot to only those entities which have changed. + +## Windowed Aggregation + +::: {.callout-note title=Todo} +Update to reflect actual syntax. Include example. +::: + +In addition to the default behavior of aggregating over all events up to a given time, aggregations may be performed over specific windows. +For example, `hourly()` describes periodic windows of an hour. +The aggregation, `sum(Purchases, window=hourly())` would produce the cumulative sum of purchases made since the beginning of the hour. +For example, if there were purchases at 8:45 AM, 9:15 AM and 9:25 AM and 10:02 AM, then the result at 9:25 AM is the sum from 9:00 AM to 9:25 AM, which would include only the events at 9:15 AM and 9:25 AM. + +A non-cumulative windowed aggregation produces values only at the end of a window. +For instance, `sum(Purchases, window=hourly(), cumulative=false)` will produce the sum for the past hour. +With the purchases in the previous example, this would mean that at 9:00 AM an event is produced containing the amount of the purchase at 8:45 AM, and at 10:00 AM an event is produced containing the sum of the purchases at 9:15 AM and 9:25 AM. +A window must be specified when using a non-cumulative aggregation. + +The section on [Aggregation](./aggregation.qmd#windowing) has more information on windowing. diff --git a/python/docs/guide/why.qmd b/python/docs/guide/why.qmd new file mode 100644 index 000000000..3fb342c55 --- /dev/null +++ b/python/docs/guide/why.qmd @@ -0,0 +1,17 @@ +--- +title: Why Kaskada? +--- + +Kaskada is a library for executing temporal queries over event-based data. +An "event" can be any fact about the world associated with a time. +For example, a user signing up for a service, or a customer purchasing a product. +As additional events occur the computed values may change as well. + +Traditional data processing systems are designed to answer questions about the current state of a dataset. +For instance, "how many purchases has a given user made?" +Over time, the user makes additional purchases and the answer *should* change. +With these traditional data processing systems, the answer changes based on when it is asked. + +With Kaskada, the query "how many purchases has a given user made?" is expressed as a _Timestream_. +This represents how the result of that query changes over time for each user. +Kaskada makes it easy to combine Timestreams to produce a new Timestream -- joining points from each input as needed. diff --git a/python/docs/index.qmd b/python/docs/index.qmd new file mode 100644 index 000000000..6beed582c --- /dev/null +++ b/python/docs/index.qmd @@ -0,0 +1,117 @@ +--- +format: + html: + css: + - _static/css/design-style.css + - _static/css/root.css + link-external-icon: true + link-external-newwindow: true + toc: false + +listing: + - id: cards + template: _templates/card.ejs + contents: + - name: "Real-time Aggregation" + icon: timeline + content: Precompute model inputs from streaming data with robust data connectors, transformations & aggregations. + - name: Event Detection + icon: binoculars + content: Trigger pro-active AI behaviors by identifying important activities, as they happen. + - name: History Replay + icon: backward + content: Backtest and fine-tune from historical data using per-example time travel and point-in-time joins. +--- + +::::: {.px-4 .py-5 .my-5 .text-center} + + +

Real-Time AI without the fuss.

+::: {.col-lg-7 .mx-auto} +[Kaskada is a next-generation streaming engine that connects AI models to real-time & historical data.]{.lead .mb-4} +::: +::::: + +## Kaskada completes the Real-Time AI stack, providing... + +::: {#cards .column-page} +::: + + +## Real-time AI in minutes + +Connect and compute over databases, streaming data, _and_ data loaded dynamically using Python.. +Kaskada is seamlessly integrated with Python's ecosystem of AI/ML tooling so you can load data, process it, train and serve models all in the same place. + +There's no infrastructure to provision (and no JVM hiding under the covers), so you can jump right in - check out the [Quick Start](./guide/quickstart.qmd). + + +## Built for scale and reliability + +Implemented in [Rust](https://www.rust-lang.org/) using [Apache Arrow](https://arrow.apache.org/), Kaskada's compute engine uses columnar data to efficiently execute large historic and high-throughput streaming queries. +Every operation in Kaskada is implemented incrementally, allowing automatic recovery if the process is terminated or killed. + +With Kaskada, most jobs are fast enough to run locally, so it's easy to build and test your real-time queries. +As your needs grow, Kaskada's cloud-native design and support for partitioned execution gives you the volume and throughput you need to scale. +Kaskada was built by core contributors to [Apache Beam](https://beam.apache.org/), [Google Cloud Dataflow](https://cloud.google.com/dataflow), and [Apache Cassandra](https://cassandra.apache.org/), and is under active development + +* * * + +## Example Real-Time App: BeepGPT + +[BeepGPT](https://github.com/kaskada-ai/beep-gpt/tree/main) keeps you in the loop without disturbing your focus. Its personalized, intelligent AI continuously monitors your Slack workspace, alerting you to important conversations and freeing you to concentrate on what’s most important. + +The core of BeepGPT's real-time processing requires only a few lines of code using Kaskada: + +```python +import asyncio +import kaskada as kd +kd.init_session() + +# Bootstrap from historical data +messages = await kd.sources.PyDict.create( + rows = pyarrow.parquet.read_table("./messages.parquet") + .to_pylist(), + time_column = "ts", + key_column = "channel", +) + +# Send each Slack message to Kaskada +def handle_message(client, req): + messages.add_rows(req.payload["event"]) +slack.socket_mode_request_listeners.append(handle_message) +slack.connect() + +# Aggregate multiple messages into a "conversation" +conversations = ( messages + .select("user", "text") + .collect(max=20) +) + +# Handle each conversation as it occurs +async for row in conversations.run_iter(mode='live'): + + # Use a pre-trained model to identify interested users + prompt = "\n\n".join([f'{msg["user"]} --> {msg["text"]}' for msg in row["result"]]) + res = openai.Completion.create( + model="davinci:ft-personal:coversation-users-full-kaskada-2023-08-05-14-25-30", + prompt=prompt + "\n\n###\n\n", + logprobs=5, + max_tokens=1, + stop=" end", + temperature=0.25, + ) + + # Notify interested users using the Slack API + for user_id in interested_users(res): + notify_user(row, user_id) +``` + +For more details, check out the [BeepGPT Github project](https://github.com/kaskada-ai/beep-gpt). + +* * * + +## Get Started + +Getting started with Kaskda is a `pip install kaskada` away. +Check out the [Quick Start](./guide/quickstart.qmd) now! From 35f200c6e7b9be6d18f43a7e7629d88db9f9cc82 Mon Sep 17 00:00:00 2001 From: Eric Pinzur Date: Sun, 8 Oct 2023 08:49:43 -0500 Subject: [PATCH 03/14] setup docs env and ci --- .github/workflows/ci_python.yml | 25 ++++++---------- python/.vscode/settings.json | 6 +++- python/README.md | 39 +++++++++++++++++++++++++ python/noxfile.py | 51 +++++++++++++++++++-------------- 4 files changed, 82 insertions(+), 39 deletions(-) diff --git a/.github/workflows/ci_python.yml b/.github/workflows/ci_python.yml index 3c8a89803..2e726cdee 100644 --- a/.github/workflows/ci_python.yml +++ b/.github/workflows/ci_python.yml @@ -69,13 +69,13 @@ jobs: poetry install --only=main --only=lint - name: black run: | - poetry run black --diff pysrc pytests docs/source + poetry run black --diff pysrc pytests docs - name: flake8 run: | - poetry run flake8 pysrc pytests docs/source + poetry run flake8 pysrc pytests docs - name: isort run: | - poetry run isort --filter-files --diff pysrc pytests docs/source + poetry run isort --filter-files --diff pysrc pytests docs - name: pydocstyle run: | poetry run pydocstyle pysrc @@ -227,28 +227,19 @@ jobs: echo "::endgroup::" deactivate done - - name: Setup QT - # Needed by sphinx-social-cards. - # https://github.com/2bndy5/sphinx-social-cards/blob/main/.github/workflows/build.yml#L54 - run: | - sudo apt-get install -y libgl1-mesa-dev libxkbcommon-x11-0 - echo "QT_QPA_PLATFORM=offscreen" >> "$GITHUB_ENV" + - name: Set up Quarto + uses: quarto-dev/quarto-actions/setup@v2 - name: Build docs - # ablog doesn't currently indicate whether it supports parallel reads, - # leading to a warning. - # when possible, add `"-j", "auto",` to do parallel builds (and in nox). run: | poetry env use 3.11 - source $(poetry env info --path)/bin/activate - poetry install --with=docs - pip install ${WHEEL} --force-reinstall - sphinx-build docs/source docs/_build -W # -j auto + nox -s docs-gen + nox -s docs-build deactivate - name: Upload docs uses: actions/upload-pages-artifact@v2 with: # Automatically uploads an artifact from the './_site' directory by default - path: ${{ github.workspace }}/python/docs/_build + path: ${{ github.workspace }}/python/docs/_site rust-format: runs-on: ubuntu-20.04 diff --git a/python/.vscode/settings.json b/python/.vscode/settings.json index 23fd35f0e..ee32511e8 100644 --- a/python/.vscode/settings.json +++ b/python/.vscode/settings.json @@ -1,3 +1,7 @@ { - "editor.formatOnSave": true + "editor.formatOnSave": true, + "[python]": { + "editor.defaultFormatter": "ms-python.autopep8" + }, + "python.formatting.provider": "none" } \ No newline at end of file diff --git a/python/README.md b/python/README.md index 2ea1da6cb..3b7fa10c1 100644 --- a/python/README.md +++ b/python/README.md @@ -33,3 +33,42 @@ Alternatively, install nox and run the tests inside an isolated environment: ```shell nox ``` + + +## Previewing Docs + +* Install `quarto-cli` on your machine. Also consider installing an IDE extension. + + See: https://quarto.org/docs/get-started/ + +* Generate reference docs + + ```shell + nox -s gen-docs + ``` + + You should re-run this after making any updates to the `pysrc` docstrings. + If _Preview Docs_ is running in another shell, the system should auto-refresh with your changes. + +* Preview docs (with auto-refresh on edit) + + ```shell + nox -s docs + ``` + +* Cleanup generated and cached docs + + ```shell + nox -s docs-clean + ``` + + Try this if you see something unexpected (especially after deleting or renaming). + +* Builds docs to `docs/_site` + + ```shell + nox -s docs-build + ``` + + This is primarily used in CI. + \ No newline at end of file diff --git a/python/noxfile.py b/python/noxfile.py index 5648b05eb..82fb8b191 100644 --- a/python/noxfile.py +++ b/python/noxfile.py @@ -50,7 +50,7 @@ def fix_lint(session: nox.Session) -> None: @nox.session(python=python_versions[0]) def safety(session: nox.Session) -> None: """Scan dependencies for insecure packages.""" - # NOTE: Pass `extras` to `export_requirements` if the project supports any. + # NOTE: Pass `extras` to `export_requirements` if the project supports any. requirements = export_requirements(session) install(session, groups=["safety"], root=False) session.run("safety", "check", "--full-report", f"--file={requirements}") @@ -114,36 +114,45 @@ def xdoctest(session: nox.Session) -> None: install(session, groups=["test"]) session.run("python", "-m", "xdoctest", *args) -@nox.session(name="docs-build", python=python_versions[0]) -def docs_build(session: nox.Session) -> None: - """Build the documentation.""" - # ablog doesn't currently indicate whether it supports parallel reads, - # leading to a warning. - # when possible, add `"-j", "auto",` to do parallel builds (and in CI). - args = session.posargs or ["docs/source", "docs/_build", "-W"] - if not session.posargs and "FORCE_COLOR" in os.environ: - args.insert(0, "--color") - install(session, groups=["typecheck", "docs"]) +@nox.session(name="docs-clean", python=python_versions[0]) +def docs_clean(session: nox.Session) -> None: + """Clean up generated and cached docs""" + + for item in ["_inv", "_site", ".quarto", "objects.json", "reference"]: + p = Path("docs", item) + if p.exists() and p.is_dir(): + shutil.rmtree(p) + elif p.exists() and p.is_file(): + p.unlink() + - build_dir = Path("docs", "_build") - if build_dir.exists(): - shutil.rmtree(build_dir) +@nox.session(name="docs-gen", python=python_versions[0]) +def docs_gen(session: nox.Session) -> None: + """Generate API reference docs""" + install(session, groups=["docs"]) - session.run("sphinx-build", *args) + with session.chdir("docs"): + session.run("python", "_scripts/gen_reference.py") + session.run("python", "-m", "quartodoc", "interlinks") @nox.session(python=python_versions[0]) def docs(session: nox.Session) -> None: """Build and serve the documentation with live reloading on file changes.""" - args = ["--open-browser", "docs/source", "docs/_build", "-j", "auto", "--ignore", "*/apidocs/*", "--watch", "pysrc/kaskada"] - install(session, groups=["typecheck", "docs"]) + install(session, groups=["docs"]) - build_dir = Path("docs", "_build") - if build_dir.exists(): - shutil.rmtree(build_dir) + with session.chdir("docs"): + session.run("quarto", "preview", external=True) + + +@nox.session(name="docs-build", python=python_versions[0]) +def docs_build(session: nox.Session) -> None: + """Build the docs.""" + install(session, groups=["docs"]) - session.run("sphinx-autobuild", *args) + with session.chdir("docs"): + session.run("quarto", "render", "--output-dir", "_site", external=True) def install(session: nox.Session, *, groups: Iterable[str], root: bool = True) -> None: From 9e9c66b3278c21acf0b333a977b6357172220178 Mon Sep 17 00:00:00 2001 From: Eric Pinzur Date: Sun, 8 Oct 2023 08:54:22 -0500 Subject: [PATCH 04/14] edited docstrings --- python/.vscode/settings.json | 6 +- python/pysrc/kaskada/_execution.py | 10 +- python/pysrc/kaskada/_timestream.py | 168 +++++++++++++------------- python/pysrc/kaskada/results.py | 44 ++++--- python/pysrc/kaskada/sources/arrow.py | 100 +++++++-------- python/pysrc/kaskada/windows.py | 88 ++++++++++---- 6 files changed, 234 insertions(+), 182 deletions(-) diff --git a/python/.vscode/settings.json b/python/.vscode/settings.json index ee32511e8..23fd35f0e 100644 --- a/python/.vscode/settings.json +++ b/python/.vscode/settings.json @@ -1,7 +1,3 @@ { - "editor.formatOnSave": true, - "[python]": { - "editor.defaultFormatter": "ms-python.autopep8" - }, - "python.formatting.provider": "none" + "editor.formatOnSave": true } \ No newline at end of file diff --git a/python/pysrc/kaskada/_execution.py b/python/pysrc/kaskada/_execution.py index ca9ea7742..e9bb9f70e 100644 --- a/python/pysrc/kaskada/_execution.py +++ b/python/pysrc/kaskada/_execution.py @@ -3,7 +3,7 @@ from dataclasses import dataclass from typing import AsyncIterator, Callable, Iterator, Literal, Optional, TypeVar, Union -import kaskada as kd +import kaskada import pyarrow as pa from . import _ffi @@ -43,7 +43,7 @@ class _ExecutionOptions: @staticmethod def create( - results: Optional[Union[kd.results.History, kd.results.Snapshot]], + results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]], row_limit: Optional[int], max_batch_size: Optional[int], mode: Literal["once", "live"] = "once", @@ -56,15 +56,15 @@ def create( ) if results is None: - results = kd.results.History() + results = kaskada.results.History() - if isinstance(results, kd.results.History): + if isinstance(results, kaskada.results.History): options.results = "history" if results.since is not None: options.changed_since = int(results.since.timestamp()) if results.until is not None: options.final_at = int(results.until.timestamp()) - elif isinstance(results, kd.results.Snapshot): + elif isinstance(results, kaskada.results.Snapshot): options.results = "snapshot" if results.changed_since is not None: options.changed_since = int(results.changed_since.timestamp()) diff --git a/python/pysrc/kaskada/_timestream.py b/python/pysrc/kaskada/_timestream.py index 197689223..9ef805648 100644 --- a/python/pysrc/kaskada/_timestream.py +++ b/python/pysrc/kaskada/_timestream.py @@ -19,7 +19,7 @@ overload, ) -import kaskada as kd +import kaskada import kaskada._ffi as _ffi import pandas as pd import pyarrow as pa @@ -31,14 +31,18 @@ if TYPE_CHECKING: import graphviz -#: A literal value that can be used as an argument to a Timestream operation. +# docstring must be under the definition :( LiteralValue: TypeAlias = Optional[Union[int, str, float, bool, timedelta, datetime]] -#: A Timestream or literal which can be used as an argument to a Timestream operation. +"""A literal value that can be used as an argument to a Timestream operation.""" + +# docstring must be under the definition :( Arg: TypeAlias = Union[ "Timestream", Callable[["Timestream"], "Timestream"], LiteralValue ] +"""A Timestream or literal which can be used as an argument to a Timestream operation.""" + def _augment_error(args: Sequence[Arg], e: Exception) -> Exception: """Augment an error with information about the arguments.""" @@ -111,12 +115,12 @@ def _call( Args: func: Name of the function to apply. input: The input to use for any "deferred" arguments. - If `None`, then any arguments that require a `Timestream` argument - will produce an error. + If `None`, then any arguments that require a `Timestream` argument + will produce an error. *args: List of arguments to the expression. session: FFI Session to create the expression in. - If unspecified, will infer from the arguments. - Will fail if all arguments are literals and the session is not provided. + If unspecified, will infer from the arguments. + Will fail if all arguments are literals and the session is not provided. Returns: Timestream representing the result of the function applied to the arguments. @@ -191,8 +195,8 @@ def pipe( Args: func: Function to apply to this Timestream. - Alternatively a `(func, keyword)` tuple where `keyword` is a string - indicating the keyword of `func` that expects the Timestream. + Alternatively a `(func, keyword)` tuple where `keyword` is a string + indicating the keyword of `func` that expects the Timestream. *args: Positional arguments passed into ``func``. **kwargs: A dictionary of keyword arguments passed into ``func``. @@ -201,7 +205,7 @@ def pipe( Raises: ValueError: When using `self` with a specific `keyword` if the `keyword` also - appears on in the `kwargs`. + appears on in the `kwargs`. Notes: Use ``.pipe`` when chaining together functions that expect Timestreams. @@ -646,7 +650,7 @@ def collect( *, max: Optional[int], min: Optional[int] = 0, - window: Optional[kd.windows.Window] = None, + window: Optional[kaskada.windows.Window] = None, ) -> Timestream: """Return a Timestream collecting up to the last `max` values in the `window`. @@ -654,11 +658,11 @@ def collect( Args: max: The maximum number of values to collect. - If `None` all values are collected. + If `None` all values are collected. min: The minimum number of values to collect before producing a value. - Defaults to 0. + Defaults to 0. window: The window to use for the aggregation. If not specified, - the entire Timestream is used. + the entire Timestream is used. Returns: A Timestream containing the list of collected elements at each point. @@ -720,7 +724,7 @@ def with_key(self, key: Arg, grouping: Optional[str] = None) -> Timestream: Args: key: The new key to use for the grouping. grouping: A string literal naming the new grouping. If no `grouping` is specified, - one will be computed from the type of the `key`. + one will be computed from the type of the `key`. """ return Timestream._call("with_key", key, self, grouping, input=self) @@ -746,7 +750,7 @@ def coalesce(self, arg: Arg, *args: Arg) -> Timestream: Returns: Timestream containing the first non-null value from each point. - If all values are null, then returns null. + If all values are null, then returns null. """ return Timestream._call("coalesce", self, arg, *args, input=self) @@ -804,7 +808,7 @@ def shift_until(self, predicate: Arg) -> Timestream: """ return Timestream._call("shift_until", predicate, self, input=self) - def sum(self, *, window: Optional[kd.windows.Window] = None) -> Timestream: + def sum(self, *, window: Optional[kaskada.windows.Window] = None) -> Timestream: """Return a Timestream summing the values in the `window`. Computes the sum for each key separately. @@ -814,7 +818,7 @@ def sum(self, *, window: Optional[kd.windows.Window] = None) -> Timestream: """ return _aggregation("sum", self, window) - def first(self, *, window: Optional[kd.windows.Window] = None) -> Timestream: + def first(self, *, window: Optional[kaskada.windows.Window] = None) -> Timestream: """Return a Timestream containing the first value in the `window`. Computed for each key separately. @@ -824,7 +828,7 @@ def first(self, *, window: Optional[kd.windows.Window] = None) -> Timestream: """ return _aggregation("first", self, window) - def last(self, window: Optional[kd.windows.Window] = None) -> Timestream: + def last(self, window: Optional[kaskada.windows.Window] = None) -> Timestream: """Return a Timestream containing the last value in the `window`. Computed for each key separately. @@ -834,7 +838,7 @@ def last(self, window: Optional[kd.windows.Window] = None) -> Timestream: """ return _aggregation("last", self, window) - def count(self, window: Optional[kd.windows.Window] = None) -> Timestream: + def count(self, window: Optional[kaskada.windows.Window] = None) -> Timestream: """Return a Timestream containing the count value in the `window`. Computed for each key separately. @@ -844,7 +848,7 @@ def count(self, window: Optional[kd.windows.Window] = None) -> Timestream: """ return _aggregation("count", self, window) - def count_if(self, window: Optional[kd.windows.Window] = None) -> Timestream: + def count_if(self, window: Optional[kaskada.windows.Window] = None) -> Timestream: """Return a Timestream containing the count of `true` values in `window`. Computed for each key separately. @@ -854,7 +858,7 @@ def count_if(self, window: Optional[kd.windows.Window] = None) -> Timestream: """ return _aggregation("count_if", self, window) - def max(self, window: Optional[kd.windows.Window] = None) -> Timestream: + def max(self, window: Optional[kaskada.windows.Window] = None) -> Timestream: """Return a Timestream containing the max value in the `window`. Computed for each key separately. @@ -864,12 +868,12 @@ def max(self, window: Optional[kd.windows.Window] = None) -> Timestream: See Also: This returns the maximum of values in a column. See - :func:`greatest` to get the maximum value + [](`~kaskada.Timestream.greatest`) to get the maximum value between Timestreams at each point. """ return _aggregation("max", self, window) - def min(self, window: Optional[kd.windows.Window] = None) -> Timestream: + def min(self, window: Optional[kaskada.windows.Window] = None) -> Timestream: """Return a Timestream containing the min value in the `window`. Computed for each key separately. @@ -879,12 +883,12 @@ def min(self, window: Optional[kd.windows.Window] = None) -> Timestream: See Also: This returns the minimum of values in a column. See - :func:`least` to get the minimum value + [](`~kaskada.Timestream.least`) to get the minimum value between Timestreams at each point. """ return _aggregation("min", self, window) - def mean(self, window: Optional[kd.windows.Window] = None) -> Timestream: + def mean(self, window: Optional[kaskada.windows.Window] = None) -> Timestream: """Return a Timestream containing the mean value in the `window`. Computed for each key separately. @@ -894,7 +898,7 @@ def mean(self, window: Optional[kd.windows.Window] = None) -> Timestream: """ return _aggregation("mean", self, window) - def stddev(self, window: Optional[kd.windows.Window] = None) -> Timestream: + def stddev(self, window: Optional[kaskada.windows.Window] = None) -> Timestream: """Return a Timestream containing the standard deviation in the `window`. Computed for each key separately. @@ -904,7 +908,7 @@ def stddev(self, window: Optional[kd.windows.Window] = None) -> Timestream: """ return _aggregation("stddev", self, window) - def variance(self, window: Optional[kd.windows.Window] = None) -> Timestream: + def variance(self, window: Optional[kaskada.windows.Window] = None) -> Timestream: """Return a Timestream containing the variance in the `window`. Computed for each key separately. @@ -955,9 +959,9 @@ def seconds_since_previous(self, n: int = 1) -> Timestream: Args: n: The number of points to look back. For example, `n=1` refers to - the previous point. + the previous point. - Defaults to 1 (the previous point). + Defaults to 1 (the previous point). """ time_of_current = Timestream._call("time_of", self).cast(pa.int64()) time_of_previous = Timestream._call("time_of", self).lag(n).cast(pa.int64()) @@ -987,7 +991,7 @@ def record(self, fields: Callable[[Timestream], Mapping[str, Arg]]) -> Timestrea See Also: kaskada.record: Function for creating a record from one or more - timestreams. + timestreams. """ return record(fields(self)) @@ -996,8 +1000,8 @@ def round(self) -> Timestream: Returns: A Timestream of the same type as `self`. The result contains `null` - if the value was `null` at that point. Otherwise, it contains - the result of rounding the value to the nearest integer. + if the value was `null` at that point. Otherwise, it contains + the result of rounding the value to the nearest integer. Notes: This method may be applied to any numeric type. For anything other @@ -1005,8 +1009,8 @@ def round(self) -> Timestream: are already integers. See Also: - - :func:`ceil` - - :func:`floor` + - [](`~kaskada.Timestream.ceil`) + - [](`~kaskada.Timestream.floor`) """ return Timestream._call("round", self) @@ -1026,13 +1030,13 @@ def greatest(self, rhs: Arg) -> Timestream: Returns: Each point contains the value from `self` if `self` - is greater than `rhs`, otherwise it contains `rhs`. - If any input is `null` or `NaN`, then that will be - the result. + is greater than `rhs`, otherwise it contains `rhs`. + If any input is `null` or `NaN`, then that will be + the result. See Also: This returns the greatest of two values. See - :func:`max` for the maximum of values in + [](`~kaskada.Timestream.max`) for the maximum of values in a column. """ return Timestream._call("zip_max", self, rhs) @@ -1045,13 +1049,13 @@ def least(self, rhs: Arg) -> Timestream: Returns: Each point contains the value from `self` if `self` - is less than `rhs`, otherwise it contains `rhs`. - If any input is `null` or `NaN`, then that will be - the result. + is less than `rhs`, otherwise it contains `rhs`. + If any input is `null` or `NaN`, then that will be + the result. See Also: This returns the least of two values. See - :func:`min` for the minimum of values in + [](`~kaskada.Timestream.min`) for the minimum of values in a column. """ return Timestream._call("zip_min", self, rhs) @@ -1059,7 +1063,7 @@ def least(self, rhs: Arg) -> Timestream: def preview( self, limit: int = 10, - results: Optional[Union[kd.results.History, kd.results.Snapshot]] = None, + results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]] = None, ) -> pd.DataFrame: """Preview the points in this TimeStream as a DataFrame. @@ -1071,7 +1075,7 @@ def preview( def to_pandas( self, - results: Optional[Union[kd.results.History, kd.results.Snapshot]] = None, + results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]] = None, *, row_limit: Optional[int] = None, ) -> pd.DataFrame: @@ -1080,14 +1084,12 @@ def to_pandas( Args: results: The results to produce in the DataFrame. Defaults to `History()` producing all points. row_limit: The maximum number of rows to return. Defaults to `None` for no limit. - max_batch_size: The maximum number of rows to return in each batch. - Defaults to `None` for no limit. See Also: - - :func:`preview`: For quick peeks at the contents of a TimeStream during development. - - :func:`write`: For writing results to supported destinations without passing through - Pandas. - - :func:`run_iter`: For non-blocking (iterator or async iterator) execution. + - [](`~kaskada.Timestream.preview`): For quick peeks at the contents of a TimeStream during development. + - [](`~kaskada.Timestream.write`): For writing results to supported destinations without passing through + Pandas. + - [](`~kaskada.Timestream.run_iter`): For non-blocking (iterator or async iterator) execution. """ execution = self._execute(results, row_limit=row_limit) batches = execution.collect_pyarrow() @@ -1097,23 +1099,23 @@ def to_pandas( def write( self, - destination: kd.destinations.Destination, + destination: kaskada.destinations.Destination, mode: Literal["once", "live"] = "once", - results: Optional[Union[kd.results.History, kd.results.Snapshot]] = None, + results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]] = None, ) -> Execution: """Execute the TimeStream writing to the given destination. Args: destination: The destination to write to. mode: The execution mode to use. Defaults to `'once'` to produce the results - from the currently available data. Use `'live'` to start a standing query - that continues to process new data until stopped. - results: The results to produce. Defaults to `History()` producing all points. + from the currently available data. Use `'live'` to start a standing query + that continues to process new data until stopped. + results: The results to produce. Defaults to `Histroy()` producing all points. Returns: An `ExecutionProgress` which allows iterating (synchronously or asynchronously) - over the progress information, as well as cancelling the query if it is no longer - needed. + over the progress information, as well as cancelling the query if it is no longer + needed. """ raise NotImplementedError @@ -1123,7 +1125,7 @@ def run_iter( kind: Literal["pandas"] = "pandas", *, mode: Literal["once", "live"] = "once", - results: Optional[Union[kd.results.History, kd.results.Snapshot]] = None, + results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]] = None, row_limit: Optional[int] = None, max_batch_size: Optional[int] = None, ) -> ResultIterator[pd.DataFrame]: @@ -1135,7 +1137,7 @@ def run_iter( kind: Literal["pyarrow"], *, mode: Literal["once", "live"] = "once", - results: Optional[Union[kd.results.History, kd.results.Snapshot]] = None, + results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]] = None, row_limit: Optional[int] = None, max_batch_size: Optional[int] = None, ) -> ResultIterator[pa.RecordBatch]: @@ -1147,7 +1149,7 @@ def run_iter( kind: Literal["row"], *, mode: Literal["once", "live"] = "once", - results: Optional[Union[kd.results.History, kd.results.Snapshot]] = None, + results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]] = None, row_limit: Optional[int] = None, max_batch_size: Optional[int] = None, ) -> ResultIterator[dict]: @@ -1158,7 +1160,7 @@ def run_iter( kind: Literal["pandas", "pyarrow", "row"] = "pandas", *, mode: Literal["once", "live"] = "once", - results: Optional[Union[kd.results.History, kd.results.Snapshot]] = None, + results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]] = None, row_limit: Optional[int] = None, max_batch_size: Optional[int] = None, ) -> Union[ @@ -1171,19 +1173,19 @@ def run_iter( Args: kind: The kind of iterator to produce. Defaults to `pandas`. mode: The execution mode to use. Defaults to `'once'` to produce the results - from the currently available data. Use `'live'` to start a standing query - that continues to process new data until stopped. + from the currently available data. Use `'live'` to start a standing query + that continues to process new data until stopped. results: The results to produce. Defaults to `History()` producing all points. row_limit: The maximum number of rows to return. Defaults to `None` for no limit. max_batch_size: The maximum number of rows to return in each batch. - Defaults to `None` for no limit. + Defaults to `None` for no limit. Returns: Iterator over data of the corresponding kind. The `QueryIterator` allows - cancelling the query or materialization as well as iterating. + cancelling the query or materialization as well as iterating. See Also: - - :func:`write`: To write the results directly to a + - [](`~kaskada.Timestream.write`): To write the results directly to a :class:`Destination`. """ execution = self._execute( @@ -1201,7 +1203,7 @@ def run_iter( def explain( self, kind: Literal["initial_dfg", "final_dfg", "final_plan"] = "final_plan", - results: Optional[Union[kd.results.History, kd.results.Snapshot]] = None, + results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]] = None, mode: Literal["once", "live"] = "once", ) -> "graphviz.Source": """Return an explanation of this Timestream will be executed. @@ -1214,15 +1216,15 @@ def explain( results: The results to produce. Defaults to `History()` producing all points. kind: The kind of plan to produce. mode: The execution mode to use. Defaults to `'once'` to produce the results - from the currently available data. Use `'live'` to start a standing query - that continues to process new data until stopped. + from the currently available data. Use `'live'` to start a standing query + that continues to process new data until stopped. Returns: A GraphViz representation of the execution plan as a string, SVG string, or SVG. - Specific representation depends on the `format` argument. + Specific representation depends on the `format` argument. Raises: - ValueError if the `kind` is not recognized or the `format` is not supported. + ValueError: if the `kind` is not recognized or the `format` is not supported. Caution: This method is intended for debugging and development purposes only. @@ -1245,7 +1247,7 @@ def explain( def _execute( self, - results: Optional[Union[kd.results.History, kd.results.Snapshot]], + results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]], *, row_limit: Optional[int] = None, max_batch_size: Optional[int] = None, @@ -1264,28 +1266,28 @@ def _execute( def _aggregation( op: str, input: Timestream, - window: Optional[kd.windows.Window], + window: Optional[kaskada.windows.Window], *args: Union[Timestream, LiteralValue], ) -> Timestream: """Return the aggregation `op` with the given `input`, `window` and `args`. Args: - op: The operation to create. - input: The input to the aggregation. - window: The window to use for the aggregation. - *args: Additional arguments to provide after `input` and before the flattened window. + op: The operation to create. + input: The input to the aggregation. + window: The window to use for the aggregation. + *args: Additional arguments to provide after `input` and before the flattened window. Raises: NotImplementedError: If the window is not a known type. """ if window is None: return Timestream._call(op, input, *args, None, None) - elif isinstance(window, kd.windows.Since): + elif isinstance(window, kaskada.windows.Since): predicate = window.predicate if callable(predicate): predicate = predicate(input) return Timestream._call(op, input, *args, predicate, None) - elif isinstance(window, kd.windows.Sliding): + elif isinstance(window, kaskada.windows.Sliding): predicate = window.predicate if callable(predicate): predicate = predicate(input) @@ -1293,7 +1295,7 @@ def _aggregation( return Timestream._call(op, input, *args, predicate, window.duration).filter( predicate ) - elif isinstance(window, kd.windows.Trailing): + elif isinstance(window, kaskada.windows.Trailing): if op != "collect": raise NotImplementedError( f"Aggregation '{op} does not support trailing windows" @@ -1315,7 +1317,7 @@ def _aggregation( # `duration` has passed with no "real" inputs. merged_input = record({"input": input, "shift": input_shift}).col("input") return Timestream._call("collect", merged_input, *args, None, trailing_ns) - elif isinstance(window, kd.windows.Tumbling): + elif isinstance(window, kaskada.windows.Tumbling): # Tumbling windows are analogous to Since windows, aside from output behavior. # Tumbling windows only emit once per window. However, this behavior is not implemented # in Sparrow yet, so we hack this by using a Since window with a filter applied afterwards @@ -1338,7 +1340,7 @@ def record(fields: Mapping[str, Arg]) -> Timestream: See Also: Timestream.record: Method for creating a record from fields computed from - a timestream. + a timestream. """ import itertools diff --git a/python/pysrc/kaskada/results.py b/python/pysrc/kaskada/results.py index a661ad744..4d6286965 100644 --- a/python/pysrc/kaskada/results.py +++ b/python/pysrc/kaskada/results.py @@ -7,32 +7,40 @@ @dataclass class History: - """Execution options for queries producing all historic points.""" + """Execution options for queries producing all historic points. + + Args: + since: If set, only returns points after this time. + + Setting this allows incremental execution to use a checkpoint + from a time before the `since` time. + + until: Only return points less than or equal to this time. + If not set, the current time will be used. + """ - #: If set, only returns points after this time. - #: - #: Setting this allows incremental execution to use a checkpoint - #: from a time before the `since` time. since: Optional[datetime] = None - #: Only return points less than or equal to this time. - #: If not set, the current time will be used. until: Optional[datetime] = None @dataclass class Snapshot: - """Execution options for queries producing snapshots at a specific time.""" - - #: If set, only includes entities that changed after this time. - #: - #: Snapshot queries support incremental execution even when this isn't set. - #: However, every snapshot will include every entity unless this is set. - #: When writing results to an external store that already has values - #: from an earlier snapshot, this can be used to reduce the amount of - #: data to be written. + """Execution options for queries producing snapshots at a specific time. + + Args: + changed_since: If set, only includes entities that changed after this time. + + Snapshot queries support incremental execution even when this isn't set. + However, every snapshot will include every entity unless this is set. + When writing results to an external store that already has values + from an earlier snapshot, this can be used to reduce the amount of + data to be written. + + at: If set, produces the snapshot at the given time. + If not set, the current time will be used. + """ + changed_since: Optional[datetime] = None - #: If set, produces the snapshot at the given time. - #: If not set, the current time will be used. at: Optional[datetime] = None diff --git a/python/pysrc/kaskada/sources/arrow.py b/python/pysrc/kaskada/sources/arrow.py index 4684a7124..53fe90e75 100644 --- a/python/pysrc/kaskada/sources/arrow.py +++ b/python/pysrc/kaskada/sources/arrow.py @@ -35,12 +35,12 @@ def __init__( key_column: The name of the column containing the key. schema: The schema to use. subsort_column: The name of the column containing the subsort. - If not provided, the subsort will be assigned by the system. + If not provided, the subsort will be assigned by the system. grouping_name: The name of the group associated with each key. - This is used to ensure implicit joins are only performed between data grouped - by the same entity. + This is used to ensure implicit joins are only performed between data grouped + by the same entity. time_unit: The unit of the time column. One of `ns`, `us`, `ms`, or `s`. - If not specified (and not specified in the data), nanosecond will be assumed. + If not specified (and not specified in the data), nanosecond will be assumed. """ super().__init__( schema=schema, @@ -69,13 +69,13 @@ async def create( time_column: The name of the column containing the time. key_column: The name of the column containing the key. subsort_column: The name of the column containing the subsort. - If not provided, the subsort will be assigned by the system. + If not provided, the subsort will be assigned by the system. schema: The schema to use. If not provided, it will be inferred from the input. grouping_name: The name of the group associated with each key. - This is used to ensure implicit joins are only performed between data grouped - by the same entity. + This is used to ensure implicit joins are only performed between data grouped + by the same entity. time_unit: The unit of the time column. One of `ns`, `us`, `ms`, or `s`. - If not specified (and not specified in the data), nanosecond will be assumed. + If not specified (and not specified in the data), nanosecond will be assumed. """ if schema is None: if dataframe is None: @@ -123,17 +123,17 @@ def __init__( key_column: The name of the column containing the key. schema: The schema to use. queryable: Whether added rows will be available for running queries. - If True, rows (both provided to the constructor and added later) will be available - for interactive queries. If False, rows will be discarded after being sent to any - running materializations. Consider setting this to False when the source will only - be used for materialization to avoid unnecessary memory usage. + If True, rows (both provided to the constructor and added later) will be available + for interactive queries. If False, rows will be discarded after being sent to any + running materializations. Consider setting this to False when the source will only + be used for materialization to avoid unnecessary memory usage. subsort_column: The name of the column containing the subsort. - If not provided, the subsort will be assigned by the system. + If not provided, the subsort will be assigned by the system. grouping_name: The name of the group associated with each key. - This is used to ensure implicit joins are only performed between data grouped - by the same entity. + This is used to ensure implicit joins are only performed between data grouped + by the same entity. time_unit: The unit of the time column. One of `ns`, `us`, `ms`, or `s`. - If not specified (and not specified in the data), nanosecond will be assumed. + If not specified (and not specified in the data), nanosecond will be assumed. """ super().__init__( queryable=queryable, @@ -166,18 +166,18 @@ async def create( time_column: The name of the column containing the time. key_column: The name of the column containing the key. queryable: Whether added rows will be available for running queries. - If True, rows (both provided to the constructor and added later) will be available - for interactive queries. If False, rows will be discarded after being sent to any - running materializations. Consider setting this to False when the source will only - be used for materialization to avoid unnecessary memory usage. + If True, rows (both provided to the constructor and added later) will be available + for interactive queries. If False, rows will be discarded after being sent to any + running materializations. Consider setting this to False when the source will only + be used for materialization to avoid unnecessary memory usage. subsort_column: The name of the column containing the subsort. - If not provided, the subsort will be assigned by the system. + If not provided, the subsort will be assigned by the system. schema: The schema to use. If not provided, it will be inferred from the input. grouping_name: The name of the group associated with each key. - This is used to ensure implicit joins are only performed between data grouped - by the same entity. + This is used to ensure implicit joins are only performed between data grouped + by the same entity. time_unit: The unit of the time column. One of `ns`, `us`, `ms`, or `s`. - If not specified (and not specified in the data), nanosecond will be assumed. + If not specified (and not specified in the data), nanosecond will be assumed. """ if schema is None: if rows is None: @@ -227,12 +227,12 @@ def __init__( key_column: The name of the column containing the key. schema: The schema to use. subsort_column: The name of the column containing the subsort. - If not provided, the subsort will be assigned by the system. + If not provided, the subsort will be assigned by the system. grouping_name: The name of the group associated with each key. - This is used to ensure implicit joins are only performed between data grouped - by the same entity. + This is used to ensure implicit joins are only performed between data grouped + by the same entity. time_unit: The unit of the time column. One of `ns`, `us`, `ms`, or `s`. - If not specified (and not specified in the data), nanosecond will be assumed. + If not specified (and not specified in the data), nanosecond will be assumed. """ super().__init__( schema=schema, @@ -270,13 +270,13 @@ async def create( time_column: The name of the column containing the time. key_column: The name of the column containing the key. subsort_column: The name of the column containing the subsort. - If not provided, the subsort will be assigned by the system. + If not provided, the subsort will be assigned by the system. schema: The schema to use. If not provided, it will be inferred from the input. grouping_name: The name of the group associated with each key. - This is used to ensure implicit joins are only performed between data grouped - by the same entity. + This is used to ensure implicit joins are only performed between data grouped + by the same entity. time_unit: The unit of the time column. One of `ns`, `us`, `ms`, or `s`. - If not specified (and not specified in the data), nanosecond will be assumed. + If not specified (and not specified in the data), nanosecond will be assumed. """ if isinstance(csv_string, str): csv_string = BytesIO(csv_string.encode("utf-8")) @@ -427,12 +427,12 @@ def __init__( key_column: The name of the column containing the key. schema: The schema to use. subsort_column: The name of the column containing the subsort. - If not provided, the subsort will be assigned by the system. + If not provided, the subsort will be assigned by the system. grouping_name: The name of the group associated with each key. - This is used to ensure implicit joins are only performed between data grouped - by the same entity. + This is used to ensure implicit joins are only performed between data grouped + by the same entity. time_unit: The unit of the time column. One of `ns`, `us`, `ms`, or `s`. - If not specified (and not specified in the data), nanosecond will be assumed. + If not specified (and not specified in the data), nanosecond will be assumed. """ super().__init__( schema=schema, @@ -462,13 +462,13 @@ async def create( time_column: The name of the column containing the time. key_column: The name of the column containing the key. subsort_column: The name of the column containing the subsort. - If not provided, the subsort will be assigned by the system. + If not provided, the subsort will be assigned by the system. schema: The schema to use. If not provided, it will be inferred from the input. grouping_name: The name of the group associated with each key. - This is used to ensure implicit joins are only performed between data grouped - by the same entity. + This is used to ensure implicit joins are only performed between data grouped + by the same entity. time_unit: The unit of the time column. One of `ns`, `us`, `ms`, or `s`. - If not specified (and not specified in the data), nanosecond will be assumed. + If not specified (and not specified in the data), nanosecond will be assumed. """ if isinstance(json_string, str): json_string = BytesIO(json_string.encode("utf-8")) @@ -520,12 +520,12 @@ def __init__( key_column: The name of the column containing the key. schema: The schema to use. subsort_column: The name of the column containing the subsort. - If not provided, the subsort will be assigned by the system. + If not provided, the subsort will be assigned by the system. grouping_name: The name of the group associated with each key. - This is used to ensure implicit joins are only performed between data grouped - by the same entity. + This is used to ensure implicit joins are only performed between data grouped + by the same entity. time_unit: The unit of the time column. One of `ns`, `us`, `ms`, or `s`. - If not specified (and not specified in the data), nanosecond will be assumed. + If not specified (and not specified in the data), nanosecond will be assumed. """ super().__init__( schema=schema, @@ -552,18 +552,18 @@ async def create( Args: file: The url or path of the Parquet file to add. Paths should be relative to the - current working directory or absolute. URLs may describe local file paths or - object-store locations. + current working directory or absolute. URLs may describe local file paths or + object-store locations. time_column: The name of the column containing the time. key_column: The name of the column containing the key. schema: The schema to use. If not provided, it will be inferred from the input. subsort_column: The name of the column containing the subsort. - If not provided, the subsort will be assigned by the system. + If not provided, the subsort will be assigned by the system. grouping_name: The name of the group associated with each key. - This is used to ensure implicit joins are only performed between data grouped - by the same entity. + This is used to ensure implicit joins are only performed between data grouped + by the same entity. time_unit: The unit of the time column. One of `ns`, `us`, `ms`, or `s`. - If not specified (and not specified in the data), nanosecond will be assumed. + If not specified (and not specified in the data), nanosecond will be assumed. """ if schema is None: if file is None: diff --git a/python/pysrc/kaskada/windows.py b/python/pysrc/kaskada/windows.py index f878e7c54..018ec595e 100644 --- a/python/pysrc/kaskada/windows.py +++ b/python/pysrc/kaskada/windows.py @@ -24,9 +24,6 @@ class Since(Window): Args: predicate: the condition used to determine when the window resets. - - Returns: - Window for aggregating cumulative values since the predicate. """ #: The boolean Timestream to use as predicate for the window. @@ -38,27 +35,47 @@ class Since(Window): @staticmethod def minutely() -> Since: - """Return a window since the start of each calendar minute.""" + """Return a window since the start of each calendar minute. + + Returns: + Window for aggregating cumulative values since the predicate. + """ return Since(predicate=lambda domain: Timestream._call("minutely", domain)) @staticmethod def hourly() -> Since: - """Return a window since the start of each calendar hour.""" + """Return a window since the start of each calendar hour. + + Returns: + Window for aggregating cumulative values since the predicate. + """ return Since(predicate=lambda domain: Timestream._call("hourly", domain)) @staticmethod def daily() -> Since: - """Return a window since the start of each calendar day.""" + """Return a window since the start of each calendar day. + + Returns: + Window for aggregating cumulative values since the predicate. + """ return Since(predicate=lambda domain: Timestream._call("daily", domain)) @staticmethod def monthly() -> Since: - """Return a window since the start of each calendar month.""" + """Return a window since the start of each calendar month. + + Returns: + Window for aggregating cumulative values since the predicate. + """ return Since(predicate=lambda domain: Timestream._call("monthly", domain)) @staticmethod def yearly() -> Since: - """Return a window since the start of each calendar year.""" + """Return a window since the start of each calendar year. + + Returns: + Window for aggregating cumulative values since the predicate. + """ return Since(predicate=lambda domain: Timestream._call("yearly", domain)) @@ -73,10 +90,7 @@ class Tumbling(Window): Args: predicate: the condition used to determine when the window resets. - Returns: - Window for aggregating values since the predicate. - - Note: + Notes: Like other systems, Kaskada treats tumbling windows as non-overlapping. When one window ends the next starts. @@ -94,27 +108,47 @@ class Tumbling(Window): @staticmethod def minutely() -> Tumbling: - """Return a tumbling window that resets at the start of each calendar minute.""" + """Return a tumbling window that resets at the start of each calendar minute. + + Returns: + Window for aggregating values since the predicate. + """ return Tumbling(predicate=lambda domain: Timestream._call("minutely", domain)) @staticmethod def hourly() -> Tumbling: - """Return a tumbling window that resets at the start of each calendar hour.""" + """Return a tumbling window that resets at the start of each calendar hour. + + Returns: + Window for aggregating values since the predicate. + """ return Tumbling(predicate=lambda domain: Timestream._call("hourly", domain)) @staticmethod def daily() -> Tumbling: - """Return a tumbling window that resets at the start of each calendar day.""" + """Return a tumbling window that resets at the start of each calendar day. + + Returns: + Window for aggregating values since the predicate. + """ return Tumbling(predicate=lambda domain: Timestream._call("daily", domain)) @staticmethod def monthly() -> Tumbling: - """Return a tumbling window that resets at the start of each calendar month.""" + """Return a tumbling window that resets at the start of each calendar month. + + Returns: + Window for aggregating values since the predicate. + """ return Tumbling(predicate=lambda domain: Timestream._call("monthly", domain)) @staticmethod def yearly() -> Tumbling: - """Return a tumbling window that resets at the start of each calendar year.""" + """Return a tumbling window that resets at the start of each calendar year. + + Returns: + Window for aggregating values since the predicate. + """ return Tumbling(predicate=lambda domain: Timestream._call("yearly", domain)) @@ -129,10 +163,7 @@ class Sliding(Window): Args: duration: the number of active windows at any given time. predicate: the condition used to determine when the oldest window ends and a new - window starts. - - Returns: - Overlapping windows for aggregating values. + window starts. """ #: The number of sliding intervals to use in the window. @@ -155,6 +186,9 @@ def minutely(duration: int) -> Sliding: Args: duration: The number of minutes to use in the window. + + Returns: + Overlapping windows for aggregating values. """ return Sliding( duration=duration, @@ -167,6 +201,9 @@ def hourly(duration: int) -> Sliding: Args: duration: The number of hours to use in the window. + + Returns: + Overlapping windows for aggregating values. """ return Sliding( duration=duration, @@ -179,6 +216,9 @@ def daily(duration: int) -> Sliding: Args: duration: The number of days to use in the window. + + Returns: + Overlapping windows for aggregating values. """ return Sliding( duration=duration, @@ -191,6 +231,9 @@ def monthly(duration: int) -> Sliding: Args: duration: The number of months to use in the window. + + Returns: + Overlapping windows for aggregating values. """ return Sliding( duration=duration, @@ -203,6 +246,9 @@ def yearly(duration: int) -> Sliding: Args: duration: The number of years to use in the window. + + Returns: + Overlapping windows for aggregating values. """ return Sliding( duration=duration, From 08f64ebe9aa2fd6a34550aafd4686709a41b47e0 Mon Sep 17 00:00:00 2001 From: Eric Pinzur Date: Sun, 8 Oct 2023 22:46:09 -0500 Subject: [PATCH 05/14] fix build --- .github/workflows/ci_python.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci_python.yml b/.github/workflows/ci_python.yml index 2e726cdee..6302b0ff1 100644 --- a/.github/workflows/ci_python.yml +++ b/.github/workflows/ci_python.yml @@ -232,6 +232,7 @@ jobs: - name: Build docs run: | poetry env use 3.11 + poetry install --only=dev nox -s docs-gen nox -s docs-build deactivate From d06c07f5f7313811b43ef8c8d6af2cb4d8f4a40e Mon Sep 17 00:00:00 2001 From: Eric Pinzur Date: Mon, 9 Oct 2023 05:46:06 -0500 Subject: [PATCH 06/14] fix lint --- .github/workflows/ci_python.yml | 3 +- python/docs/_scripts/builder.py | 46 ++++++++++++-------- python/docs/_scripts/renderer.py | 67 ++++++++++++++++------------- python/docs/_scripts/summarizer.py | 7 +-- python/docs/examples/bluesky.py | 16 ++++--- python/pysrc/kaskada/_timestream.py | 39 ++++++++++++----- 6 files changed, 109 insertions(+), 69 deletions(-) diff --git a/.github/workflows/ci_python.yml b/.github/workflows/ci_python.yml index 6302b0ff1..9df01b2f5 100644 --- a/.github/workflows/ci_python.yml +++ b/.github/workflows/ci_python.yml @@ -72,7 +72,7 @@ jobs: poetry run black --diff pysrc pytests docs - name: flake8 run: | - poetry run flake8 pysrc pytests docs + poetry run flake8 pysrc pytests - name: isort run: | poetry run isort --filter-files --diff pysrc pytests docs @@ -232,6 +232,7 @@ jobs: - name: Build docs run: | poetry env use 3.11 + source $(poetry env info --path)/bin/activate poetry install --only=dev nox -s docs-gen nox -s docs-build diff --git a/python/docs/_scripts/builder.py b/python/docs/_scripts/builder.py index f2e4055b5..e7c199457 100644 --- a/python/docs/_scripts/builder.py +++ b/python/docs/_scripts/builder.py @@ -2,16 +2,13 @@ import logging import sys - from pathlib import Path -from pydantic import ValidationError - -from quartodoc.inventory import create_inventory, convert_inventory -from quartodoc import layout, preview, blueprint, collect -from quartodoc.validation import fmt - from typing import Any, Union +from pydantic import ValidationError +from quartodoc import blueprint, collect, layout, preview +from quartodoc.inventory import convert_inventory, create_inventory +from quartodoc.validation import fmt from renderer import Renderer from summarizer import Summarizer @@ -136,7 +133,7 @@ def build(self): convert_inventory(inv, self.out_inventory) def get_package(self, item: Union[layout.Section, layout.Page]) -> str: - if item.package and f'{item.package}' != "": + if item.package and f"{item.package}" != "": return item.package else: return self.package @@ -167,7 +164,10 @@ def write_pages(self): section_path = location / self.out_index self.write_page_if_not_exists(section_path, section_text) - is_flat = section.options and section.options.children == layout.ChoicesChildren.flat + is_flat = ( + section.options + and section.options.children == layout.ChoicesChildren.flat + ) for page in section.contents: if isinstance(page, layout.Page): @@ -186,24 +186,32 @@ def write_pages(self): raise NotImplementedError(f"Unsupported section item: {type(page)}") if len(self.page_map.keys()) > 0: - _log.warning(f'Extra pages: {self.page_map.keys()}') - _log.error(f'Linking between pages may not work properly. Fix the issue and try again') + _log.warning(f"Extra pages: {self.page_map.keys()}") + _log.error( + f"Linking between pages may not work properly. Fix the issue and try again" + ) if len(self.item_map.keys()) > 0: - _log.warning(f'Extra items: {self.item_map.keys()}') - _log.error(f'Linking between pages may not work properly. Fix the issue and try again') + _log.warning(f"Extra items: {self.item_map.keys()}") + _log.error( + f"Linking between pages may not work properly. Fix the issue and try again" + ) def update_page_items(self, page: layout.Page, location: Path, is_flat: bool): for doc in page.contents: if isinstance(doc, layout.Doc): - page_path = f'{location}/index.html' if is_flat else f'{location}/{page.path}.html' + page_path = ( + f"{location}/index.html" + if is_flat + else f"{location}/{page.path}.html" + ) self.update_items(doc, page_path) else: raise NotImplementedError(f"Unsupported page item: {type(doc)}") def update_items(self, doc: layout.Doc, page_path: str): name = doc.obj.path - uri = f'{page_path}#{doc.anchor}' + uri = f"{page_path}#{doc.anchor}" # item corresponding to the specified path ---- # e.g. this might be a top-level import @@ -213,7 +221,7 @@ def update_items(self, doc: layout.Doc, page_path: str): del self.item_map[name] else: item = layout.Item(uri=uri, name=name, obj=doc.obj, dispname=None) - _log.warning(f'Missing item, adding it: {item}') + _log.warning(f"Missing item, adding it: {item}") self.items.append(item) canonical_path = doc.obj.canonical_path @@ -225,8 +233,10 @@ def update_items(self, doc: layout.Doc, page_path: str): item.uri = uri del self.item_map[canonical_path] else: - item = layout.Item(uri=uri, name=canonical_path, obj=doc.obj, dispname=name) - _log.warning(f'Missing item, adding it: {item}') + item = layout.Item( + uri=uri, name=canonical_path, obj=doc.obj, dispname=name + ) + _log.warning(f"Missing item, adding it: {item}") self.items.append(item) # recurse in 😊 diff --git a/python/docs/_scripts/renderer.py b/python/docs/_scripts/renderer.py index 2298ece9a..5d4be75af 100644 --- a/python/docs/_scripts/renderer.py +++ b/python/docs/_scripts/renderer.py @@ -1,15 +1,15 @@ from __future__ import annotations -import quartodoc.ast as qast +from typing import Optional, Union -from griffe.docstrings import dataclasses as ds +import quartodoc.ast as qast from griffe import dataclasses as dc -from tabulate import tabulate +from griffe.docstrings import dataclasses as ds from plum import dispatch -from typing import Union, Optional from quartodoc import layout - from summarizer import Summarizer +from tabulate import tabulate + try: # Name and Expression were moved to expressions in v0.28 @@ -49,7 +49,7 @@ def sanitize(val: str, allow_markdown=False): return res -class Renderer(): +class Renderer: """Render docstrings to markdown.""" summarizer = Summarizer() @@ -61,7 +61,7 @@ def _get_display_name(self, el: "dc.Alias | dc.Object"): display_name = f"**{prefix}.**[**{name}**]{{.red}}" if isinstance(el, dc.Object): - if 'staticmethod' in el.labels: + if "staticmethod" in el.labels: display_name = "***static*** " + display_name text = [display_name] @@ -78,23 +78,25 @@ def _fetch_method_parameters(self, el: dc.Function): return el.parameters - def _render_definition_list(self, title: str, items: [str], title_class: Optional[str] = None) -> str: + def _render_definition_list( + self, title: str, items: [str], title_class: Optional[str] = None + ) -> str: rows = [title] for item in items: if len(rows) == 1: - rows.append(f'~ {item}') + rows.append(f"~ {item}") else: - rows.append(f' {item}') + rows.append(f" {item}") if title_class: - rows.insert(0, f':::{{.{title_class}}}') - rows.append(':::') + rows.insert(0, f":::{{.{title_class}}}") + rows.append(":::") return "\n" + "\n".join(rows) def _render_header(self, title: str, order: Optional[int] = None) -> str: text = ["---"] - text.append(f'title: {title}') + text.append(f"title: {title}") if order: - text.append(f'order: {order}') + text.append(f"order: {order}") text.append("---") return "\n".join(text) @@ -190,7 +192,7 @@ def render(self, el: layout.Page, is_flat: bool = False): if el.summary: if el.summary.name: if is_flat: - rows.append(f'## {el.summary.name}') + rows.append(f"## {el.summary.name}") else: rows.append(self._render_header(el.summary.name)) if el.summary.desc: @@ -206,7 +208,9 @@ def render(self, el: layout.Doc): raise NotImplementedError(f"Unsupported Doc type: {type(el)}") @dispatch - def render(self, el: Union[layout.DocClass, layout.DocModule], is_flat: bool = False) -> str: + def render( + self, el: Union[layout.DocClass, layout.DocModule], is_flat: bool = False + ) -> str: title = "" if is_flat else self._render_header(el.name) sig = self.signature(el) @@ -219,7 +223,8 @@ def render(self, el: Union[layout.DocClass, layout.DocModule], is_flat: bool = F if raw_attrs and not _has_attr_section(el.obj.docstring): attr_rows = map(self.render, raw_attrs) attr_text = self._render_definition_list( - "Attributes:", attr_rows, title_class="highlight") + "Attributes:", attr_rows, title_class="highlight" + ) body_rows.extend(attr_text.split("\n")) # add classes @@ -358,15 +363,17 @@ def render(self, el: ds.DocstringSectionParameters): for param in el.value: name = sanitize(param.name) anno = self.render_annotation(param.annotation) - default = f', default: {escape(param.default)}' if param.default else "" + default = f", default: {escape(param.default)}" if param.default else "" - rows.append(f'{prefix}**{name}** ({anno}{default})') + rows.append(f"{prefix}**{name}** ({anno}{default})") rows.append("") for row in param.description.split("\n"): - rows.append(f'{follow}{row}') + rows.append(f"{follow}{row}") rows.append("") - return self._render_definition_list("Parameters:", rows, title_class="highlight") + return self._render_definition_list( + "Parameters:", rows, title_class="highlight" + ) # attributes ---- @@ -380,13 +387,15 @@ def render(self, el: ds.DocstringSectionAttributes): for attr in el.value: name = sanitize(attr.name) anno = self.render_annotation(attr.annotation) - rows.append(f'{prefix}**{name}** ({anno})') + rows.append(f"{prefix}**{name}** ({anno})") rows.append("") for row in attr.description.split("\n"): - rows.append(f'{follow}{row}') + rows.append(f"{follow}{row}") rows.append("") - return self._render_definition_list("Attributes:", rows, title_class="highlight") + return self._render_definition_list( + "Attributes:", rows, title_class="highlight" + ) # examples ---- @@ -419,7 +428,7 @@ def render(self, el: ds.DocstringSectionReturns): title = prefix name = sanitize(item.name) if name: - title += f'**{name}**' + title += f"**{name}**" return_type = self.render_annotation(item.annotation) if return_type: @@ -431,7 +440,7 @@ def render(self, el: ds.DocstringSectionReturns): if item.description: rows.append("") for row in item.description.split("\n"): - rows.append(f'{follow}{row}') + rows.append(f"{follow}{row}") rows.append("") return self._render_definition_list("Returns:", rows, title_class="highlight") @@ -446,10 +455,10 @@ def render(self, el: ds.DocstringSectionRaises): for item in el.value: # name = sanitize(item.name) anno = self.render_annotation(item.annotation) - rows.append(f'{prefix}{anno}') + rows.append(f"{prefix}{anno}") rows.append("") for row in item.description.split("\n"): - rows.append(f'{follow}{row}') + rows.append(f"{follow}{row}") rows.append("") return self._render_definition_list("Raises:", rows, title_class="highlight") @@ -465,7 +474,7 @@ def render(self, el: ds.DocstringSectionAdmonition) -> str: rows.append(f'::: {{.callout-tip title="{el.title}"}}') rows.append(el.value.description) - rows.append(':::') + rows.append(":::") return "\n".join(rows) diff --git a/python/docs/_scripts/summarizer.py b/python/docs/_scripts/summarizer.py index cf643dbd4..e1c44b179 100644 --- a/python/docs/_scripts/summarizer.py +++ b/python/docs/_scripts/summarizer.py @@ -1,13 +1,14 @@ from __future__ import annotations -from griffe.docstrings import dataclasses as ds +from typing import Optional, Union + from griffe import dataclasses as dc +from griffe.docstrings import dataclasses as ds from plum import dispatch -from typing import Union, Optional from quartodoc import layout -class Summarizer(): +class Summarizer: """Summarize docstrings to markdown.""" @staticmethod diff --git a/python/docs/examples/bluesky.py b/python/docs/examples/bluesky.py index 447b2dd8a..906a1c0aa 100644 --- a/python/docs/examples/bluesky.py +++ b/python/docs/examples/bluesky.py @@ -79,13 +79,15 @@ async def receive_at(message) -> None: # The parsing produces a hot mess of incompatible types, so we build # a dict from scratch to simplify. - posts.add_rows({ - "record": dict(new_post["record"]), - "uri": new_post["uri"], - "cid": new_post["cid"], - "author": new_post["author"], - "ts": time.time(), - }) + posts.add_rows( + { + "record": dict(new_post["record"]), + "uri": new_post["uri"], + "cid": new_post["cid"], + "author": new_post["author"], + "ts": time.time(), + } + ) # Handler for values emitted by Kaskada. async def receive_outputs(): diff --git a/python/pysrc/kaskada/_timestream.py b/python/pysrc/kaskada/_timestream.py index 9ef805648..3fed6947e 100644 --- a/python/pysrc/kaskada/_timestream.py +++ b/python/pysrc/kaskada/_timestream.py @@ -1063,7 +1063,9 @@ def least(self, rhs: Arg) -> Timestream: def preview( self, limit: int = 10, - results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]] = None, + results: Optional[ + Union[kaskada.results.History, kaskada.results.Snapshot] + ] = None, ) -> pd.DataFrame: """Preview the points in this TimeStream as a DataFrame. @@ -1075,7 +1077,9 @@ def preview( def to_pandas( self, - results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]] = None, + results: Optional[ + Union[kaskada.results.History, kaskada.results.Snapshot] + ] = None, *, row_limit: Optional[int] = None, ) -> pd.DataFrame: @@ -1086,9 +1090,10 @@ def to_pandas( row_limit: The maximum number of rows to return. Defaults to `None` for no limit. See Also: - - [](`~kaskada.Timestream.preview`): For quick peeks at the contents of a TimeStream during development. - - [](`~kaskada.Timestream.write`): For writing results to supported destinations without passing through - Pandas. + - [](`~kaskada.Timestream.preview`): For quick peeks at the contents of a TimeStream during + development. + - [](`~kaskada.Timestream.write`): For writing results to supported destinations without + passing through Pandas. - [](`~kaskada.Timestream.run_iter`): For non-blocking (iterator or async iterator) execution. """ execution = self._execute(results, row_limit=row_limit) @@ -1101,7 +1106,9 @@ def write( self, destination: kaskada.destinations.Destination, mode: Literal["once", "live"] = "once", - results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]] = None, + results: Optional[ + Union[kaskada.results.History, kaskada.results.Snapshot] + ] = None, ) -> Execution: """Execute the TimeStream writing to the given destination. @@ -1125,7 +1132,9 @@ def run_iter( kind: Literal["pandas"] = "pandas", *, mode: Literal["once", "live"] = "once", - results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]] = None, + results: Optional[ + Union[kaskada.results.History, kaskada.results.Snapshot] + ] = None, row_limit: Optional[int] = None, max_batch_size: Optional[int] = None, ) -> ResultIterator[pd.DataFrame]: @@ -1137,7 +1146,9 @@ def run_iter( kind: Literal["pyarrow"], *, mode: Literal["once", "live"] = "once", - results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]] = None, + results: Optional[ + Union[kaskada.results.History, kaskada.results.Snapshot] + ] = None, row_limit: Optional[int] = None, max_batch_size: Optional[int] = None, ) -> ResultIterator[pa.RecordBatch]: @@ -1149,7 +1160,9 @@ def run_iter( kind: Literal["row"], *, mode: Literal["once", "live"] = "once", - results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]] = None, + results: Optional[ + Union[kaskada.results.History, kaskada.results.Snapshot] + ] = None, row_limit: Optional[int] = None, max_batch_size: Optional[int] = None, ) -> ResultIterator[dict]: @@ -1160,7 +1173,9 @@ def run_iter( kind: Literal["pandas", "pyarrow", "row"] = "pandas", *, mode: Literal["once", "live"] = "once", - results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]] = None, + results: Optional[ + Union[kaskada.results.History, kaskada.results.Snapshot] + ] = None, row_limit: Optional[int] = None, max_batch_size: Optional[int] = None, ) -> Union[ @@ -1203,7 +1218,9 @@ def run_iter( def explain( self, kind: Literal["initial_dfg", "final_dfg", "final_plan"] = "final_plan", - results: Optional[Union[kaskada.results.History, kaskada.results.Snapshot]] = None, + results: Optional[ + Union[kaskada.results.History, kaskada.results.Snapshot] + ] = None, mode: Literal["once", "live"] = "once", ) -> "graphviz.Source": """Return an explanation of this Timestream will be executed. From 43773545d86c81b564c173d95896692dad5d49de Mon Sep 17 00:00:00 2001 From: Eric Pinzur Date: Mon, 9 Oct 2023 10:19:53 -0500 Subject: [PATCH 07/14] try building without nox --- .github/workflows/ci_python.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci_python.yml b/.github/workflows/ci_python.yml index 9df01b2f5..e5d83c9d6 100644 --- a/.github/workflows/ci_python.yml +++ b/.github/workflows/ci_python.yml @@ -233,9 +233,12 @@ jobs: run: | poetry env use 3.11 source $(poetry env info --path)/bin/activate - poetry install --only=dev - nox -s docs-gen - nox -s docs-build + poetry install --with=docs + pip install ${WHEEL} --force-reinstall + cd docs + python _scripts/gen_reference.py + python -m quartodoc interlinks + quarto render --output-dir _site deactivate - name: Upload docs uses: actions/upload-pages-artifact@v2 From fbcd74714be1eab372bc624bfdbcd67386074e28 Mon Sep 17 00:00:00 2001 From: Eric Pinzur Date: Mon, 9 Oct 2023 10:51:26 -0500 Subject: [PATCH 08/14] added missing template --- python/docs/.gitignore | 5 ++++- python/docs/_templates/announcement.html | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 python/docs/_templates/announcement.html diff --git a/python/docs/.gitignore b/python/docs/.gitignore index 907d4ff4d..489c9246a 100644 --- a/python/docs/.gitignore +++ b/python/docs/.gitignore @@ -9,7 +9,10 @@ /reference/ # files that might remain if a quarto build is interrupted -*.html +index.html +/blog/*.html +/examples/*.html +/guide/*.html index-listing.json data_types-listing.json /site_libs/ diff --git a/python/docs/_templates/announcement.html b/python/docs/_templates/announcement.html new file mode 100644 index 000000000..c022c76ba --- /dev/null +++ b/python/docs/_templates/announcement.html @@ -0,0 +1,3 @@ +
+
This describes the next version of Kaskada. It is currently available as an alpha release.
+
\ No newline at end of file From 257473efb09c9ff69d5fa7f3ef665735cc2d5d21 Mon Sep 17 00:00:00 2001 From: Ben Chambers <35960+bjchambers@users.noreply.github.com> Date: Mon, 9 Oct 2023 11:21:57 -0700 Subject: [PATCH 09/14] minor tweaks from getting started --- python/README.md | 3 +-- python/noxfile.py | 8 ++++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/python/README.md b/python/README.md index 3b7fa10c1..bb2b2b59f 100644 --- a/python/README.md +++ b/python/README.md @@ -44,7 +44,7 @@ nox * Generate reference docs ```shell - nox -s gen-docs + nox -s docs-gen ``` You should re-run this after making any updates to the `pysrc` docstrings. @@ -71,4 +71,3 @@ nox ``` This is primarily used in CI. - \ No newline at end of file diff --git a/python/noxfile.py b/python/noxfile.py index 82fb8b191..50e8c8577 100644 --- a/python/noxfile.py +++ b/python/noxfile.py @@ -140,6 +140,10 @@ def docs_gen(session: nox.Session) -> None: @nox.session(python=python_versions[0]) def docs(session: nox.Session) -> None: """Build and serve the documentation with live reloading on file changes.""" + if not shutil.which("quarto"): + session.error("Unable to execute `quarto`. Is it installed and in your path?\n" + "See https://quarto.org/docs/get-started/") + install(session, groups=["docs"]) with session.chdir("docs"): @@ -149,6 +153,10 @@ def docs(session: nox.Session) -> None: @nox.session(name="docs-build", python=python_versions[0]) def docs_build(session: nox.Session) -> None: """Build the docs.""" + if not shutil.which("quarto"): + session.error("Unable to execute `quarto`. Is it installed and in your path?\n" + "See https://quarto.org/docs/get-started/") + install(session, groups=["docs"]) with session.chdir("docs"): From f57e1eaf3953d9f095b4bd8c3592d26bb39a9274 Mon Sep 17 00:00:00 2001 From: Ben Chambers <35960+bjchambers@users.noreply.github.com> Date: Mon, 9 Oct 2023 12:12:11 -0700 Subject: [PATCH 10/14] docs: Add community page Also: - switch to using bootstrap icons over font awesome icons - update card.ejs to allow for links --- python/docs/_quarto.yml | 5 ++ python/docs/_static/css/root.css | 38 ------------- .../fonts/FontAwesome6Free-Solid-900.ttf | Bin 384736 -> 0 bytes .../fonts/FontAwesome6Free-Solid-900.woff2 | Bin 133940 -> 0 bytes python/docs/_templates/card.ejs | 9 +++- python/docs/community/index.qmd | 51 ++++++++++++++++++ python/docs/index.qmd | 7 ++- 7 files changed, 67 insertions(+), 43 deletions(-) delete mode 100644 python/docs/_static/css/root.css delete mode 100644 python/docs/_static/fonts/FontAwesome6Free-Solid-900.ttf delete mode 100644 python/docs/_static/fonts/FontAwesome6Free-Solid-900.woff2 create mode 100644 python/docs/community/index.qmd diff --git a/python/docs/_quarto.yml b/python/docs/_quarto.yml index aa93147b1..a08ed7093 100644 --- a/python/docs/_quarto.yml +++ b/python/docs/_quarto.yml @@ -21,6 +21,8 @@ website: text: User Guide - href: examples/index.qmd text: Examples + - href: community/index.qmd + text: Community - href: reference/index.qmd text: API - href: blog/index.qmd @@ -48,6 +50,9 @@ website: - guide/execution.qmd - title: Examples contents: examples + - title: Community + contents: + - community/index.qmd - title: API style: docked contents: reference diff --git a/python/docs/_static/css/root.css b/python/docs/_static/css/root.css deleted file mode 100644 index 388f018c3..000000000 --- a/python/docs/_static/css/root.css +++ /dev/null @@ -1,38 +0,0 @@ -/*! - * Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com - * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) - * Copyright 2023 Fonticons, Inc. - */ - -.fas { - -moz-osx-font-smoothing: grayscale; - -webkit-font-smoothing: antialiased; - display: var(--fa-display, inline-block); - font-family: 'Font Awesome 6 Free'; - font-style: normal; - font-weight: 900; - font-variant: normal; - line-height: 1; - text-rendering: auto; -} - -@font-face { - font-family: 'Font Awesome 6 Free'; - font-display: block; - font-weight: 900; - src: - url("../fonts/FontAwesome6Free-Solid-900.woff2") format("woff2"), - url("../fonts/FontAwesome6Free-Solid-900.ttf") format("truetype"); -} - -.fa-binoculars::before { - content: "\f1e5"; -} - -.fa-timeline::before { - content: "\e29c"; -} - -.fa-backward::before { - content: "\f04a"; -} \ No newline at end of file diff --git a/python/docs/_static/fonts/FontAwesome6Free-Solid-900.ttf b/python/docs/_static/fonts/FontAwesome6Free-Solid-900.ttf deleted file mode 100644 index deab676ff9d908d8023782116fc4affa93ecede4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 384736 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
5;698S6E-l(mmqlLoMcx4N0vEeP1@ySA;7KK|c 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

BmFx3;X;of;ZS^E^Ji-ilCCh#LMnCj%N76v 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 e3MgMs@_yoF!zFs%u$A7?TFfDWy{

-

+

<%= item.name %>

@@ -15,6 +15,13 @@ <%= item.content %>

+ <% if (item.link) { %> +
+ <% } %> <% } %> diff --git a/python/docs/community/index.qmd b/python/docs/community/index.qmd new file mode 100644 index 000000000..2e992a267 --- /dev/null +++ b/python/docs/community/index.qmd @@ -0,0 +1,51 @@ +--- +title: Community +format: + html: + css: + - /_static/css/design-style.css + link-external-icon: true + link-external-newwindow: true + +listing: + - id: cards + template: ../_templates/card.ejs + contents: + - name: GitHub Discussions + icon: bi bi-github + content: Ask questions and discuss Kaskada on GitHub. + link: https://github.com/kaskada-ai/kaskada/discussions + link_label: See GitHub Discussions + - name: Slack + icon: bi bi-slack + content: Join us on Slack to chat about Proactive AI! + link: https://join.slack.com/t/kaskada-hq/shared_invite/zt-1t1lms085-bqs2jtGO2TYr9kuuam~c9w + link_label: Join Slack + - name: Office Hours + icon: bi bi-camera-video-fill + content: Discuss your real-time Gen AI needs and ideas with us! + link: https://calendly.com/kaskada-io/office-hours + link_label: Schedule a video call +--- + +::: {#cards } +::: + +Welcome to the Kaskada community! + +The Kaskada project was open-sourced in 2023. As a growing community, we're here to explore new ways to interact with event-based data at scale and have some fun along the way. We build in the open and use the channels below for communication. + +## Contributing + +Nothing makes us happier than community contributions. See the README in the main Kaskada repository to get a grasp of the project layout and reference the [`CONTRIBUTING.md`](https://github.com/kaskada-ai/kaskada/blob/main/CONTRIBUTING.md){target="_blank" rel="noopener noreferrer"} file for detailed steps. + +Use the [GitHub issue tracker](https://github.com/kaskada-ai/kaskada/issues) to file bugs and feature requests. + +Acceptance of the DataStax [contributor license agreement (CLA)](https://cla.datastax.com/) is required in order for us to be able to accept your code contribution. You will see this on the standard pull request checklist for the Kaskada repositories. + +If you're interested in contributing but don't know where to start, we also recommend looking for a good first issue in the main repository. + +## Code of Conduct + +To make Kaskada a welcoming and harassment-free experience for everyone, we adopt and follow the [Contributor Covenant](https://www.contributor-covenant.org/). +Please read our [Code of Conduct](https://github.com/kaskada-ai/kaskada/blob/main/CODE_OF_CONDUCT.md) before engaging with the community. diff --git a/python/docs/index.qmd b/python/docs/index.qmd index 6beed582c..070dd5d74 100644 --- a/python/docs/index.qmd +++ b/python/docs/index.qmd @@ -3,7 +3,6 @@ format: html: css: - _static/css/design-style.css - - _static/css/root.css link-external-icon: true link-external-newwindow: true toc: false @@ -13,13 +12,13 @@ listing: template: _templates/card.ejs contents: - name: "Real-time Aggregation" - icon: timeline + icon: bi bi-clock-history content: Precompute model inputs from streaming data with robust data connectors, transformations & aggregations. - name: Event Detection - icon: binoculars + icon: bi bi-binoculars-fill content: Trigger pro-active AI behaviors by identifying important activities, as they happen. - name: History Replay - icon: backward + icon: bi bi-skip-backward-fill content: Backtest and fine-tune from historical data using per-example time travel and point-in-time joins. --- From 9ee8273a81cdc02c7f3b3e97ce70230993a1048b Mon Sep 17 00:00:00 2001 From: Eric Pinzur <2641606+epinzur@users.noreply.github.com> Date: Tue, 10 Oct 2023 17:39:11 +0200 Subject: [PATCH 11/14] made some quarto tweaks (#801) * removed 1-element sidebar from Community page * re-added `docs` to linting * Setup overrides for error F811 for reference generation scripts. https://www.flake8rules.com/rules/F811.html * Fixed other linting issues for reference generation scripts --- .github/workflows/ci_python.yml | 2 +- python/docs/_quarto.yml | 3 -- python/docs/_scripts/builder.py | 23 +++++--- python/docs/_scripts/renderer.py | 84 +++++++++++++++++------------- python/docs/_scripts/summarizer.py | 20 +++---- 5 files changed, 74 insertions(+), 58 deletions(-) diff --git a/.github/workflows/ci_python.yml b/.github/workflows/ci_python.yml index e5d83c9d6..d99fb7e4c 100644 --- a/.github/workflows/ci_python.yml +++ b/.github/workflows/ci_python.yml @@ -72,7 +72,7 @@ jobs: poetry run black --diff pysrc pytests docs - name: flake8 run: | - poetry run flake8 pysrc pytests + poetry run flake8 pysrc pytests docs - name: isort run: | poetry run isort --filter-files --diff pysrc pytests docs diff --git a/python/docs/_quarto.yml b/python/docs/_quarto.yml index a08ed7093..0530bde15 100644 --- a/python/docs/_quarto.yml +++ b/python/docs/_quarto.yml @@ -50,9 +50,6 @@ website: - guide/execution.qmd - title: Examples contents: examples - - title: Community - contents: - - community/index.qmd - title: API style: docked contents: reference diff --git a/python/docs/_scripts/builder.py b/python/docs/_scripts/builder.py index e7c199457..57e03b08b 100644 --- a/python/docs/_scripts/builder.py +++ b/python/docs/_scripts/builder.py @@ -6,12 +6,17 @@ from typing import Any, Union from pydantic import ValidationError -from quartodoc import blueprint, collect, layout, preview +from quartodoc import blueprint, collect, layout from quartodoc.inventory import convert_inventory, create_inventory from quartodoc.validation import fmt from renderer import Renderer from summarizer import Summarizer +# `preview()` can be used to help debug doc generation. +# use it on a `section` or `page` element to see a visual +# representation of the element contents. Use the `max_depth` +# named param to limit how much is returned to stdout. +# from quartodoc import preview _log = logging.getLogger("quartodoc") @@ -176,25 +181,27 @@ def write_pages(self): _log.info(f"Rendering {page.path}") # preview(page, max_depth=4) page_text = self.renderer.render(page) - page_path = location / (page.path + self.out_page_suffix) + page_path = location / \ + (page.path + self.out_page_suffix) self.write_page_if_not_exists(page_path, page_text) if page.path in self.page_map: del self.page_map[page.path] self.update_page_items(page, location, is_flat) else: - raise NotImplementedError(f"Unsupported section item: {type(page)}") + raise NotImplementedError( + f"Unsupported section item: {type(page)}") if len(self.page_map.keys()) > 0: _log.warning(f"Extra pages: {self.page_map.keys()}") _log.error( - f"Linking between pages may not work properly. Fix the issue and try again" + "Linking between pages may not work properly. Fix the issue and try again" ) if len(self.item_map.keys()) > 0: _log.warning(f"Extra items: {self.item_map.keys()}") _log.error( - f"Linking between pages may not work properly. Fix the issue and try again" + "Linking between pages may not work properly. Fix the issue and try again" ) def update_page_items(self, page: layout.Page, location: Path, is_flat: bool): @@ -207,7 +214,8 @@ def update_page_items(self, page: layout.Page, location: Path, is_flat: bool): ) self.update_items(doc, page_path) else: - raise NotImplementedError(f"Unsupported page item: {type(doc)}") + raise NotImplementedError( + f"Unsupported page item: {type(doc)}") def update_items(self, doc: layout.Doc, page_path: str): name = doc.obj.path @@ -285,7 +293,8 @@ def from_quarto_config(cls, quarto_cfg: "str | dict"): cfg = quarto_cfg.get("quartodoc") if cfg is None: - raise KeyError("No `quartodoc:` section found in your _quarto.yml.") + raise KeyError( + "No `quartodoc:` section found in your _quarto.yml.") return Builder( **{k: v for k, v in cfg.items()}, diff --git a/python/docs/_scripts/renderer.py b/python/docs/_scripts/renderer.py index 5d4be75af..704e5cc37 100644 --- a/python/docs/_scripts/renderer.py +++ b/python/docs/_scripts/renderer.py @@ -108,48 +108,52 @@ def _render_table(self, rows, headers): # render_annotation method -------------------------------------------------------- @dispatch - def render_annotation(self, el: str) -> str: + def render_annotation(self, el: str) -> str: # noqa: F811 return sanitize(el) @dispatch - def render_annotation(self, el: None) -> str: + def render_annotation(self, el: None) -> str: # noqa: F811 return "" @dispatch - def render_annotation(self, el: expr.Name) -> str: + def render_annotation(self, el: expr.Name) -> str: # noqa: F811 if el.full not in skip_annotation_types: return f"[{sanitize(el.source)}](`{el.full}`)" return "" @dispatch - def render_annotation(self, el: expr.Expression) -> str: + def render_annotation(self, el: expr.Expression) -> str: # noqa: F811 text = "".join(map(self.render_annotation, el)) return text.lstrip(".") # signature method -------------------------------------------------------- @dispatch - def signature(self, el: layout.Doc): + def signature(self, el: layout.Doc): # noqa: F811 return self.signature(el.obj) @dispatch - def signature(self, el: dc.Alias, source: Optional[dc.Alias] = None): + def signature(self, el: dc.Alias, source: Optional[dc.Alias] = None): # noqa: F811 """Return a string representation of an object's signature.""" return self.signature(el.target, el) @dispatch - def signature(self, el: dc.Function, source: Optional[dc.Alias] = None) -> str: + def signature( # noqa: F811 + self, el: dc.Function, source: Optional[dc.Alias] = None + ) -> str: name = self._get_display_name(source or el) pars = self.render(self._fetch_method_parameters(el)) return f"{name}([{pars}]{{.bold-italic}})" @dispatch - def signature(self, el: dc.Class, source: Optional[dc.Alias] = None) -> str: + def signature( # noqa: F811 + self, el: dc.Class, source: Optional[dc.Alias] = None + ) -> str: name = self._get_display_name(source or el) return f"***class*** {name}" @dispatch - def signature( + def signature( # noqa: F811 self, el: Union[dc.Module, dc.Attribute], source: Optional[dc.Alias] = None ): name = self._get_display_name(source or el) @@ -158,19 +162,21 @@ def signature( # render method ----------------------------------------------------------- @dispatch - def render(self, el): + def render(self, el): # noqa: F811 """Return a string representation of an object, or layout element.""" raise NotImplementedError(f"Unsupported type: {type(el)}") @dispatch - def render(self, el: str): + def render(self, el: str): # noqa: F811 return el # render layouts ========================================================== @dispatch - def render(self, el: layout.Section, order: Optional[int] = None) -> str: + def render( # noqa: F811 + self, el: layout.Section, order: Optional[int] = None + ) -> str: rows = [self._render_header(el.title or el.subtitle, order=order)] if el.desc: @@ -187,7 +193,7 @@ def render(self, el: layout.Section, order: Optional[int] = None) -> str: return text @dispatch - def render(self, el: layout.Page, is_flat: bool = False): + def render(self, el: layout.Page, is_flat: bool = False): # noqa: F811 rows = [] if el.summary: if el.summary.name: @@ -204,11 +210,11 @@ def render(self, el: layout.Page, is_flat: bool = False): return "\n\n".join(rows) @dispatch - def render(self, el: layout.Doc): + def render(self, el: layout.Doc): # noqa: F811 raise NotImplementedError(f"Unsupported Doc type: {type(el)}") @dispatch - def render( + def render( # noqa: F811 self, el: Union[layout.DocClass, layout.DocModule], is_flat: bool = False ) -> str: title = "" if is_flat else self._render_header(el.name) @@ -230,19 +236,21 @@ def render( # add classes for raw_class in el.members: if raw_class.obj.is_class and isinstance(raw_class, layout.Doc): - body_rows.extend(self.render(raw_class, is_flat=True).split("\n")) + body_rows.extend(self.render( + raw_class, is_flat=True).split("\n")) # add methods for raw_method in el.members: if raw_method.obj.is_function and isinstance(raw_method, layout.Doc): - body_rows.extend(self.render(raw_method, is_flat=True).split("\n")) + body_rows.extend(self.render( + raw_method, is_flat=True).split("\n")) text = self._render_definition_list(sig, body_rows) return "\n\n".join([title, text]) @dispatch - def render(self, el: layout.DocFunction, is_flat: bool = False): + def render(self, el: layout.DocFunction, is_flat: bool = False): # noqa: F811 title = "" if is_flat else self._render_header(el.name) sig = self.signature(el) @@ -252,7 +260,7 @@ def render(self, el: layout.DocFunction, is_flat: bool = False): return "\n\n".join([title, text]) @dispatch - def render(self, el: layout.DocAttribute, is_flat: bool = False): + def render(self, el: layout.DocAttribute, is_flat: bool = False): # noqa: F811 link = f"[{el.name}](#{el.anchor})" description = self.summarizer.summarize(el.obj) @@ -261,7 +269,7 @@ def render(self, el: layout.DocAttribute, is_flat: bool = False): # render griffe objects =================================================== @dispatch - def render(self, el: Union[dc.Object, dc.Alias]): + def render(self, el: Union[dc.Object, dc.Alias]): # noqa: F811 """Render high level objects representing functions, classes, etc..""" str_body = [] @@ -279,10 +287,11 @@ def render(self, el: Union[dc.Object, dc.Alias]): # signature parts ------------------------------------------------------------- @dispatch - def render(self, el: dc.Parameters): + def render(self, el: dc.Parameters): # noqa: F811 # index for switch from positional to kw args (via an unnamed *) try: - kw_only = [par.kind for par in el].index(dc.ParameterKind.keyword_only) + kw_only = [par.kind for par in el].index( + dc.ParameterKind.keyword_only) except ValueError: kw_only = None @@ -318,8 +327,9 @@ def render(self, el: dc.Parameters): return ", ".join(pars) @dispatch - def render(self, el: dc.Parameter): - splats = {dc.ParameterKind.var_keyword, dc.ParameterKind.var_positional} + def render(self, el: dc.Parameter): # noqa: F811 + splats = {dc.ParameterKind.var_keyword, + dc.ParameterKind.var_positional} has_default = el.default and el.kind not in splats if el.kind == dc.ParameterKind.var_keyword: @@ -343,7 +353,7 @@ def render(self, el: dc.Parameter): # note this can be a number of things. for example, opening docstring text, # or a section with a header not included in the numpydoc standard @dispatch - def render(self, el: ds.DocstringSectionText): + def render(self, el: ds.DocstringSectionText): # noqa: F811 new_el = qast.transform(el) if isinstance(new_el, ds.DocstringSectionText): # ensures we don't recurse forever @@ -354,7 +364,7 @@ def render(self, el: ds.DocstringSectionText): # parameters ---- @dispatch - def render(self, el: ds.DocstringSectionParameters): + def render(self, el: ds.DocstringSectionParameters): # noqa: F811 # if more than one param, render as un-ordered list prefix = "* " if len(el.value) > 1 else "" follow = " " if len(el.value) > 1 else "" @@ -378,7 +388,7 @@ def render(self, el: ds.DocstringSectionParameters): # attributes ---- @dispatch - def render(self, el: ds.DocstringSectionAttributes): + def render(self, el: ds.DocstringSectionAttributes): # noqa: F811 # if more than one param, render as un-ordered list prefix = "* " if len(el.value) > 1 else "" follow = " " if len(el.value) > 1 else "" @@ -400,25 +410,25 @@ def render(self, el: ds.DocstringSectionAttributes): # examples ---- @dispatch - def render(self, el: ds.DocstringSectionExamples): + def render(self, el: ds.DocstringSectionExamples): # noqa: F811 # its value is a tuple: DocstringSectionKind["text" | "examples"], str data = map(qast.transform, el.value) return "\n\n".join(list(map(self.render, data))) @dispatch - def render(self, el: qast.ExampleCode): + def render(self, el: qast.ExampleCode): # noqa: F811 return f"""```python {el.value} ```""" @dispatch - def render(self, el: qast.ExampleText): + def render(self, el: qast.ExampleText): # noqa: F811 return el.value # returns ---- @dispatch - def render(self, el: ds.DocstringSectionReturns): + def render(self, el: ds.DocstringSectionReturns): # noqa: F811 # if more than one param, render as un-ordered list prefix = "* " if len(el.value) > 1 else "" follow = " " if len(el.value) > 1 else "" @@ -446,7 +456,7 @@ def render(self, el: ds.DocstringSectionReturns): return self._render_definition_list("Returns:", rows, title_class="highlight") @dispatch - def render(self, el: ds.DocstringSectionRaises): + def render(self, el: ds.DocstringSectionRaises): # noqa: F811 # if more than one param, render as un-ordered list prefix = "* " if len(el.value) > 1 else "" follow = " " if len(el.value) > 1 else "" @@ -464,14 +474,14 @@ def render(self, el: ds.DocstringSectionRaises): return self._render_definition_list("Raises:", rows, title_class="highlight") @dispatch - def render(self, el: ds.DocstringSectionAdmonition) -> str: + def render(self, el: ds.DocstringSectionAdmonition) -> str: # noqa: F811 rows = [] if el.title.lower().startswith("note"): - rows.append(f'::: {{.callout-note title="{el.title}"}}') + rows.append(f"::: {{.callout-note title={el.title!r}}}") elif el.title.lower().startswith("warn"): - rows.append(f'::: {{.callout-warning title="{el.title}"}}') + rows.append(f"::: {{.callout-warning title={el.title!r}}}") else: - rows.append(f'::: {{.callout-tip title="{el.title}"}}') + rows.append(f"::: {{.callout-tip title={el.title!r}}}") rows.append(el.value.description) rows.append(":::") @@ -488,5 +498,5 @@ def render(self, el: ds.DocstringSectionAdmonition) -> str: (ds.DocstringReceive,), (ds.DocstringAttribute,), ) - def render(self, el): + def render(self, el): # noqa: F811 raise NotImplementedError(f"{type(el)}") diff --git a/python/docs/_scripts/summarizer.py b/python/docs/_scripts/summarizer.py index e1c44b179..015f81fb9 100644 --- a/python/docs/_scripts/summarizer.py +++ b/python/docs/_scripts/summarizer.py @@ -16,16 +16,16 @@ def _summary_row(link, description): return f"| {link} | {description} |" @dispatch - def summarize(self, el): + def summarize(self, el): # noqa: F811 raise NotImplementedError(f"Unsupported type: {type(el)}") @dispatch - def summarize(self, el: layout.Layout): + def summarize(self, el: layout.Layout): # noqa: F811 rendered_sections = list(map(self.summarize, el.sections)) return "\n\n".join(rendered_sections) @dispatch - def summarize(self, el: layout.Section): + def summarize(self, el: layout.Section): # noqa: F811 desc = f"\n\n{el.desc}" if el.desc is not None else "" if el.title is not None: header = f"## {el.title}{desc}" @@ -40,7 +40,7 @@ def summarize(self, el: layout.Section): return header @dispatch - def summarize(self, contents: layout.ContentList): + def summarize(self, contents: layout.ContentList): # noqa: F811 thead = "| | |\n| --- | --- |" rendered = [] @@ -50,7 +50,7 @@ def summarize(self, contents: layout.ContentList): return "\n".join([thead, *rendered]) @dispatch - def summarize(self, el: layout.Page): + def summarize(self, el: layout.Page): # noqa: F811 if el.summary is not None: # TODO: assumes that files end with .qmd return self._summary_row( @@ -68,18 +68,18 @@ def summarize(self, el: layout.Page): return "\n".join(rows) @dispatch - def summarize(self, el: layout.MemberPage): + def summarize(self, el: layout.MemberPage): # noqa: F811 # TODO: model should validate these only have a single entry return self.summarize(el.contents[0], el.path, shorten=True) @dispatch - def summarize(self, el: layout.Interlaced, *args, **kwargs): + def summarize(self, el: layout.Interlaced, *args, **kwargs): # noqa: F811 rows = [self.summarize(doc, *args, **kwargs) for doc in el.contents] return "\n".join(rows) @dispatch - def summarize( + def summarize( # noqa: F811 self, el: layout.Doc, path: Optional[str] = None, shorten: bool = False ): # this is where summary page method links are created @@ -93,12 +93,12 @@ def summarize( return self._summary_row(link, description) @dispatch - def summarize(self, el: layout.Link): + def summarize(self, el: layout.Link): # noqa: F811 description = self.summarize(el.obj) return self._summary_row(f"[](`{el.name}`)", description) @dispatch - def summarize(self, obj: Union[dc.Object, dc.Alias]) -> str: + def summarize(self, obj: Union[dc.Object, dc.Alias]) -> str: # noqa: F811 """Test""" # get high-level description doc = obj.docstring From 016e717aab14ff9e03a7ff05a62ea7c7b4aaeba0 Mon Sep 17 00:00:00 2001 From: Eric Pinzur Date: Tue, 10 Oct 2023 11:21:30 -0500 Subject: [PATCH 12/14] update dependencies after rebase --- python/poetry.lock | 1935 ++++++++++++++++++++--------------------- python/pyproject.toml | 44 +- 2 files changed, 973 insertions(+), 1006 deletions(-) diff --git a/python/poetry.lock b/python/poetry.lock index 9c93fe4a0..cdc36eca9 100644 --- a/python/poetry.lock +++ b/python/poetry.lock @@ -1,93 +1,126 @@ # This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] -name = "ablog" -version = "0.11.5" -description = "A Sphinx extension that converts any documentation or personal website project into a full-fledged blog." +name = "anyio" +version = "4.0.0" +description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false -python-versions = ">=3.9" +python-versions = ">=3.8" files = [ - {file = "ablog-0.11.5-py3-none-any.whl", hash = "sha256:158a9638244c3e9183d5b0f8368857ec125d3a2087d0e943363a915df0afc3ce"}, - {file = "ablog-0.11.5.tar.gz", hash = "sha256:b9d2d3d14c9f164278822cd17b6deb36d88356282a309a0aa8ca9e7f166d6889"}, + {file = "anyio-4.0.0-py3-none-any.whl", hash = "sha256:cfdb2b588b9fc25ede96d8db56ed50848b0b649dca3dd1df0b11f683bb9e0b5f"}, + {file = "anyio-4.0.0.tar.gz", hash = "sha256:f7ed51751b2c2add651e5747c891b47e26d2a21be5d32d9311dfe9692f3e5d7a"}, ] [package.dependencies] -docutils = ">=0.18" -feedgen = ">=0.9.0" -invoke = ">=1.6.0" -packaging = ">=19.0" -python-dateutil = ">=2.8.2" -sphinx = ">=5.0.0" -watchdog = ">=2.1.0" +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} +idna = ">=2.8" +sniffio = ">=1.1" [package.extras] -all = ["ipython (>=7.30.0)", "myst-parser (>=0.17.0)", "nbsphinx (>=0.8.0)"] -dev = ["alabaster", "ipython (>=7.30.0)", "myst-parser (>=0.17.0)", "nbsphinx (>=0.8.0)", "pytest", "sphinx-automodapi"] -docs = ["alabaster", "sphinx-automodapi"] -markdown = ["myst-parser (>=0.17.0)"] -notebook = ["ipython (>=7.30.0)", "nbsphinx (>=0.8.0)"] -tests = ["pytest"] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.22)"] [[package]] -name = "accessible-pygments" -version = "0.0.4" -description = "A collection of accessible pygments styles" +name = "appnope" +version = "0.1.3" +description = "Disable App Nap on macOS >= 10.9" optional = false python-versions = "*" files = [ - {file = "accessible-pygments-0.0.4.tar.gz", hash = "sha256:e7b57a9b15958e9601c7e9eb07a440c813283545a20973f2574a5f453d0e953e"}, - {file = "accessible_pygments-0.0.4-py2.py3-none-any.whl", hash = "sha256:416c6d8c1ea1c5ad8701903a20fcedf953c6e720d64f33dc47bfb2d3f2fa4e8d"}, + {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"}, + {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"}, ] -[package.dependencies] -pygments = ">=1.5" - [[package]] -name = "alabaster" -version = "0.7.13" -description = "A configurable sidebar-enabled Sphinx theme" +name = "argcomplete" +version = "3.1.2" +description = "Bash tab completion for argparse" optional = false python-versions = ">=3.6" files = [ - {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"}, - {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"}, + {file = "argcomplete-3.1.2-py3-none-any.whl", hash = "sha256:d97c036d12a752d1079f190bc1521c545b941fda89ad85d15afa909b4d1b9a99"}, + {file = "argcomplete-3.1.2.tar.gz", hash = "sha256:d5d1e5efd41435260b8f85673b74ea2e883affcbec9f4230c582689e8e78251b"}, ] +[package.extras] +test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] + [[package]] -name = "annotated-types" -version = "0.5.0" -description = "Reusable constraint types to use with typing.Annotated" +name = "argon2-cffi" +version = "23.1.0" +description = "Argon2 for Python" optional = false python-versions = ">=3.7" files = [ - {file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"}, - {file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"}, + {file = "argon2_cffi-23.1.0-py3-none-any.whl", hash = "sha256:c670642b78ba29641818ab2e68bd4e6a78ba53b7eff7b4c3815ae16abf91c7ea"}, + {file = "argon2_cffi-23.1.0.tar.gz", hash = "sha256:879c3e79a2729ce768ebb7d36d4609e3a78a4ca2ec3a9f12286ca057e3d0db08"}, ] +[package.dependencies] +argon2-cffi-bindings = "*" + +[package.extras] +dev = ["argon2-cffi[tests,typing]", "tox (>4)"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-copybutton", "sphinx-notfound-page"] +tests = ["hypothesis", "pytest"] +typing = ["mypy"] + [[package]] -name = "appnope" -version = "0.1.3" -description = "Disable App Nap on macOS >= 10.9" +name = "argon2-cffi-bindings" +version = "21.2.0" +description = "Low-level CFFI bindings for Argon2" optional = false -python-versions = "*" +python-versions = ">=3.6" files = [ - {file = "appnope-0.1.3-py2.py3-none-any.whl", hash = "sha256:265a455292d0bd8a72453494fa24df5a11eb18373a60c7c0430889f22548605e"}, - {file = "appnope-0.1.3.tar.gz", hash = "sha256:02bd91c4de869fbb1e1c50aafc4098827a7a54ab2f39d9dcba6c9547ed920e24"}, -] + {file = "argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_i686.whl", hash = "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win32.whl", hash = "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f"}, + {file = "argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3e385d1c39c520c08b53d63300c3ecc28622f076f4c2b0e6d7e796e9f6502194"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c3e3cc67fdb7d82c4718f19b4e7a87123caf8a93fde7e23cf66ac0337d3cb3f"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a22ad9800121b71099d0fb0a65323810a15f2e292f2ba450810a7316e128ee5"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9f8b450ed0547e3d473fdc8612083fd08dd2120d6ac8f73828df9b7d45bb351"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:93f9bf70084f97245ba10ee36575f0c3f1e7d7724d67d8e5b08e61787c320ed7"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3b9ef65804859d335dc6b31582cad2c5166f0c3e7975f324d9ffaa34ee7e6583"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4966ef5848d820776f5f562a7d45fdd70c2f330c961d0d745b784034bd9f48d"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ef543a89dee4db46a1a6e206cd015360e5a75822f76df533845c3cbaf72670"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2937d286e2ad0cc79a7087d3c272832865f779430e0cc2b4f3718d3159b0cb"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5e00316dabdaea0b2dd82d141cc66889ced0cdcbfa599e8b471cf22c620c329a"}, +] + +[package.dependencies] +cffi = ">=1.0.1" + +[package.extras] +dev = ["cogapp", "pre-commit", "pytest", "wheel"] +tests = ["pytest"] [[package]] -name = "argcomplete" -version = "3.1.2" -description = "Bash tab completion for argparse" +name = "arrow" +version = "1.3.0" +description = "Better dates & times for Python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "argcomplete-3.1.2-py3-none-any.whl", hash = "sha256:d97c036d12a752d1079f190bc1521c545b941fda89ad85d15afa909b4d1b9a99"}, - {file = "argcomplete-3.1.2.tar.gz", hash = "sha256:d5d1e5efd41435260b8f85673b74ea2e883affcbec9f4230c582689e8e78251b"}, + {file = "arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80"}, + {file = "arrow-1.3.0.tar.gz", hash = "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85"}, ] +[package.dependencies] +python-dateutil = ">=2.7.0" +types-python-dateutil = ">=2.8.10" + [package.extras] -test = ["coverage", "mypy", "pexpect", "ruff", "wheel"] +doc = ["doc8", "sphinx (>=7.0.0)", "sphinx-autobuild", "sphinx-autodoc-typehints", "sphinx_rtd_theme (>=1.3.0)"] +test = ["dateparser (==1.*)", "pre-commit", "pytest", "pytest-cov", "pytest-mock", "pytz (==2021.1)", "simplejson (==3.*)"] [[package]] name = "asttokens" @@ -106,6 +139,20 @@ six = ">=1.12.0" [package.extras] test = ["astroid", "pytest"] +[[package]] +name = "async-lru" +version = "2.0.4" +description = "Simple LRU cache for asyncio" +optional = false +python-versions = ">=3.8" +files = [ + {file = "async-lru-2.0.4.tar.gz", hash = "sha256:b8a59a5df60805ff63220b2a0c5b5393da5521b113cd5465a44eb037d81a5627"}, + {file = "async_lru-2.0.4-py3-none-any.whl", hash = "sha256:ff02944ce3c288c5be660c42dbcca0742b32c3b279d6dceda655190240b99224"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} + [[package]] name = "attrs" version = "23.1.0" @@ -164,6 +211,24 @@ files = [ {file = "backcall-0.2.0.tar.gz", hash = "sha256:5cbdbf27be5e7cfadb448baf0aa95508f91f2bbc6c6437cd9cd06e2a4c215e1e"}, ] +[[package]] +name = "beartype" +version = "0.16.2" +description = "Unbearably fast runtime type checking in pure Python." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "beartype-0.16.2-py3-none-any.whl", hash = "sha256:72d133615fe674affc8c49365dd24dfe2260552b9a8a2b7193cdd48021527782"}, + {file = "beartype-0.16.2.tar.gz", hash = "sha256:47ec1c8c3be3f999f4f9f829e8913f65926aa7e85b180d9ffd305dc78d3e7d7b"}, +] + +[package.extras] +all = ["typing-extensions (>=3.10.0.0)"] +dev = ["autoapi (>=0.9.0)", "coverage (>=5.5)", "mypy (>=0.800)", "numpy", "pandera", "pydata-sphinx-theme (<=0.7.2)", "pytest (>=4.0.0)", "sphinx", "sphinx (>=4.2.0,<6.0.0)", "sphinxext-opengraph (>=0.7.5)", "tox (>=3.20.1)", "typing-extensions (>=3.10.0.0)"] +doc-rtd = ["autoapi (>=0.9.0)", "pydata-sphinx-theme (<=0.7.2)", "sphinx (>=4.2.0,<6.0.0)", "sphinxext-opengraph (>=0.7.5)"] +test-tox = ["mypy (>=0.800)", "numpy", "pandera", "pytest (>=4.0.0)", "sphinx", "typing-extensions (>=3.10.0.0)"] +test-tox-coverage = ["coverage (>=5.5)"] + [[package]] name = "beautifulsoup4" version = "4.12.2" @@ -230,19 +295,37 @@ d = ["aiohttp (>=3.7.4)"] jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] uvloop = ["uvloop (>=0.15.2)"] +[[package]] +name = "bleach" +version = "6.1.0" +description = "An easy safelist-based HTML-sanitizing tool." +optional = false +python-versions = ">=3.8" +files = [ + {file = "bleach-6.1.0-py3-none-any.whl", hash = "sha256:3225f354cfc436b9789c66c4ee030194bee0568fbf9cbdad3bc8b5c26c5f12b6"}, + {file = "bleach-6.1.0.tar.gz", hash = "sha256:0a31f1837963c41d46bbf1331b8778e1308ea0791db03cc4e7357b97cf42a8fe"}, +] + +[package.dependencies] +six = ">=1.9.0" +webencodings = "*" + +[package.extras] +css = ["tinycss2 (>=1.1.0,<1.3)"] + [[package]] name = "boto3" -version = "1.28.61" +version = "1.28.62" description = "The AWS SDK for Python" optional = false python-versions = ">= 3.7" files = [ - {file = "boto3-1.28.61-py3-none-any.whl", hash = "sha256:ec49986e6c9549177e351494de64886c3f9daffd1a7af9e40302208aa1ffff1c"}, - {file = "boto3-1.28.61.tar.gz", hash = "sha256:7a539aaf00eb45aea1ae857ef5d05e67def24fc07af4cb36c202fa45f8f30590"}, + {file = "boto3-1.28.62-py3-none-any.whl", hash = "sha256:0dfa2fc96ccafce4feb23044d6cba8b25075ad428a0c450d369d099c6a1059d2"}, + {file = "boto3-1.28.62.tar.gz", hash = "sha256:148eeba0f1867b3db5b3e5ae2997d75a94d03fad46171374a0819168c36f7ed0"}, ] [package.dependencies] -botocore = ">=1.31.61,<1.32.0" +botocore = ">=1.31.62,<1.32.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.7.0,<0.8.0" @@ -631,19 +714,22 @@ xray = ["mypy-boto3-xray (>=1.28.0,<1.29.0)"] [[package]] name = "botocore" -version = "1.31.61" +version = "1.31.62" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">= 3.7" files = [ - {file = "botocore-1.31.61-py3-none-any.whl", hash = "sha256:433bf93af09ad205d6db4c2ffc1f0e3193ddad4e0aced0a68ad8b0fa9de903e2"}, - {file = "botocore-1.31.61.tar.gz", hash = "sha256:39b059603f0e92a26599eecc7fe9b141f13eb412c964786ca3a7df5375928c87"}, + {file = "botocore-1.31.62-py3-none-any.whl", hash = "sha256:be792d806afc064694a2d0b9b25779f3ca0c1584b29a35ac32e67f0064ddb8b7"}, + {file = "botocore-1.31.62.tar.gz", hash = "sha256:272b78ac65256b6294cb9cdb0ac484d447ad3a85642e33cb6a3b1b8afee15a4c"}, ] [package.dependencies] jmespath = ">=0.7.1,<2.0.0" python-dateutil = ">=2.1,<3.0.0" -urllib3 = ">=1.25.4,<1.27" +urllib3 = [ + {version = ">=1.25.4,<1.27", markers = "python_version < \"3.10\""}, + {version = ">=1.25.4,<2.1", markers = "python_version >= \"3.10\""}, +] [package.extras] crt = ["awscrt (==0.16.26)"] @@ -1002,6 +1088,17 @@ files = [ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, ] +[[package]] +name = "defusedxml" +version = "0.7.1" +description = "XML bomb protection for Python stdlib modules" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] + [[package]] name = "distlib" version = "0.3.7" @@ -1106,20 +1203,6 @@ files = [ [package.extras] devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] -[[package]] -name = "feedgen" -version = "0.9.0" -description = "Feed Generator (ATOM, RSS, Podcasts)" -optional = false -python-versions = "*" -files = [ - {file = "feedgen-0.9.0.tar.gz", hash = "sha256:8e811bdbbed6570034950db23a4388453628a70e689a6e8303ccec430f5a804a"}, -] - -[package.dependencies] -lxml = "*" -python-dateutil = "*" - [[package]] name = "filelock" version = "3.12.4" @@ -1189,6 +1272,17 @@ restructuredtext-lint = "*" [package.extras] develop = ["build", "twine"] +[[package]] +name = "fqdn" +version = "1.5.1" +description = "Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers" +optional = false +python-versions = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4, <4" +files = [ + {file = "fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014"}, + {file = "fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f"}, +] + [[package]] name = "graphviz" version = "0.20.1" @@ -1206,79 +1300,18 @@ docs = ["sphinx (>=5)", "sphinx-autodoc-typehints", "sphinx-rtd-theme"] test = ["coverage", "mock (>=4)", "pytest (>=7)", "pytest-cov", "pytest-mock (>=3)"] [[package]] -name = "greenlet" -version = "3.0.0" -description = "Lightweight in-process concurrent programming" +name = "griffe" +version = "0.32.3" +description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "greenlet-3.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e09dea87cc91aea5500262993cbd484b41edf8af74f976719dd83fe724644cd6"}, - {file = "greenlet-3.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f47932c434a3c8d3c86d865443fadc1fbf574e9b11d6650b656e602b1797908a"}, - {file = "greenlet-3.0.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bdfaeecf8cc705d35d8e6de324bf58427d7eafb55f67050d8f28053a3d57118c"}, - {file = "greenlet-3.0.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a68d670c8f89ff65c82b936275369e532772eebc027c3be68c6b87ad05ca695"}, - {file = "greenlet-3.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ad562a104cd41e9d4644f46ea37167b93190c6d5e4048fcc4b80d34ecb278f"}, - {file = "greenlet-3.0.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:02a807b2a58d5cdebb07050efe3d7deaf915468d112dfcf5e426d0564aa3aa4a"}, - {file = "greenlet-3.0.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b1660a15a446206c8545edc292ab5c48b91ff732f91b3d3b30d9a915d5ec4779"}, - {file = "greenlet-3.0.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:813720bd57e193391dfe26f4871186cf460848b83df7e23e6bef698a7624b4c9"}, - {file = "greenlet-3.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:aa15a2ec737cb609ed48902b45c5e4ff6044feb5dcdfcf6fa8482379190330d7"}, - {file = "greenlet-3.0.0-cp310-universal2-macosx_11_0_x86_64.whl", hash = "sha256:7709fd7bb02b31908dc8fd35bfd0a29fc24681d5cc9ac1d64ad07f8d2b7db62f"}, - {file = "greenlet-3.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:211ef8d174601b80e01436f4e6905aca341b15a566f35a10dd8d1e93f5dbb3b7"}, - {file = "greenlet-3.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6512592cc49b2c6d9b19fbaa0312124cd4c4c8a90d28473f86f92685cc5fef8e"}, - {file = "greenlet-3.0.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:871b0a8835f9e9d461b7fdaa1b57e3492dd45398e87324c047469ce2fc9f516c"}, - {file = "greenlet-3.0.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b505fcfc26f4148551826a96f7317e02c400665fa0883fe505d4fcaab1dabfdd"}, - {file = "greenlet-3.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:123910c58234a8d40eaab595bc56a5ae49bdd90122dde5bdc012c20595a94c14"}, - {file = "greenlet-3.0.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:96d9ea57292f636ec851a9bb961a5cc0f9976900e16e5d5647f19aa36ba6366b"}, - {file = "greenlet-3.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0b72b802496cccbd9b31acea72b6f87e7771ccfd7f7927437d592e5c92ed703c"}, - {file = "greenlet-3.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:527cd90ba3d8d7ae7dceb06fda619895768a46a1b4e423bdb24c1969823b8362"}, - {file = "greenlet-3.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:37f60b3a42d8b5499be910d1267b24355c495064f271cfe74bf28b17b099133c"}, - {file = "greenlet-3.0.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1482fba7fbed96ea7842b5a7fc11d61727e8be75a077e603e8ab49d24e234383"}, - {file = "greenlet-3.0.0-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:be557119bf467d37a8099d91fbf11b2de5eb1fd5fc5b91598407574848dc910f"}, - {file = "greenlet-3.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:73b2f1922a39d5d59cc0e597987300df3396b148a9bd10b76a058a2f2772fc04"}, - {file = "greenlet-3.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1e22c22f7826096ad503e9bb681b05b8c1f5a8138469b255eb91f26a76634f2"}, - {file = "greenlet-3.0.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1d363666acc21d2c204dd8705c0e0457d7b2ee7a76cb16ffc099d6799744ac99"}, - {file = "greenlet-3.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:334ef6ed8337bd0b58bb0ae4f7f2dcc84c9f116e474bb4ec250a8bb9bd797a66"}, - {file = "greenlet-3.0.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6672fdde0fd1a60b44fb1751a7779c6db487e42b0cc65e7caa6aa686874e79fb"}, - {file = "greenlet-3.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:952256c2bc5b4ee8df8dfc54fc4de330970bf5d79253c863fb5e6761f00dda35"}, - {file = "greenlet-3.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:269d06fa0f9624455ce08ae0179430eea61085e3cf6457f05982b37fd2cefe17"}, - {file = "greenlet-3.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:9adbd8ecf097e34ada8efde9b6fec4dd2a903b1e98037adf72d12993a1c80b51"}, - {file = "greenlet-3.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6b5ce7f40f0e2f8b88c28e6691ca6806814157ff05e794cdd161be928550f4c"}, - {file = "greenlet-3.0.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ecf94aa539e97a8411b5ea52fc6ccd8371be9550c4041011a091eb8b3ca1d810"}, - {file = "greenlet-3.0.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80dcd3c938cbcac986c5c92779db8e8ce51a89a849c135172c88ecbdc8c056b7"}, - {file = "greenlet-3.0.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e52a712c38e5fb4fd68e00dc3caf00b60cb65634d50e32281a9d6431b33b4af1"}, - {file = "greenlet-3.0.0-cp37-cp37m-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d5539f6da3418c3dc002739cb2bb8d169056aa66e0c83f6bacae0cd3ac26b423"}, - {file = "greenlet-3.0.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:343675e0da2f3c69d3fb1e894ba0a1acf58f481f3b9372ce1eb465ef93cf6fed"}, - {file = "greenlet-3.0.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:abe1ef3d780de56defd0c77c5ba95e152f4e4c4e12d7e11dd8447d338b85a625"}, - {file = "greenlet-3.0.0-cp37-cp37m-win32.whl", hash = "sha256:e693e759e172fa1c2c90d35dea4acbdd1d609b6936115d3739148d5e4cd11947"}, - {file = "greenlet-3.0.0-cp37-cp37m-win_amd64.whl", hash = "sha256:bdd696947cd695924aecb3870660b7545a19851f93b9d327ef8236bfc49be705"}, - {file = "greenlet-3.0.0-cp37-universal2-macosx_11_0_x86_64.whl", hash = "sha256:cc3e2679ea13b4de79bdc44b25a0c4fcd5e94e21b8f290791744ac42d34a0353"}, - {file = "greenlet-3.0.0-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:63acdc34c9cde42a6534518e32ce55c30f932b473c62c235a466469a710bfbf9"}, - {file = "greenlet-3.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a1a6244ff96343e9994e37e5b4839f09a0207d35ef6134dce5c20d260d0302c"}, - {file = "greenlet-3.0.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b822fab253ac0f330ee807e7485769e3ac85d5eef827ca224feaaefa462dc0d0"}, - {file = "greenlet-3.0.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8060b32d8586e912a7b7dac2d15b28dbbd63a174ab32f5bc6d107a1c4143f40b"}, - {file = "greenlet-3.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:621fcb346141ae08cb95424ebfc5b014361621b8132c48e538e34c3c93ac7365"}, - {file = "greenlet-3.0.0-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6bb36985f606a7c49916eff74ab99399cdfd09241c375d5a820bb855dfb4af9f"}, - {file = "greenlet-3.0.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:10b5582744abd9858947d163843d323d0b67be9432db50f8bf83031032bc218d"}, - {file = "greenlet-3.0.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f351479a6914fd81a55c8e68963609f792d9b067fb8a60a042c585a621e0de4f"}, - {file = "greenlet-3.0.0-cp38-cp38-win32.whl", hash = "sha256:9de687479faec7db5b198cc365bc34addd256b0028956501f4d4d5e9ca2e240a"}, - {file = "greenlet-3.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:3fd2b18432e7298fcbec3d39e1a0aa91ae9ea1c93356ec089421fabc3651572b"}, - {file = "greenlet-3.0.0-cp38-universal2-macosx_11_0_x86_64.whl", hash = "sha256:3c0d36f5adc6e6100aedbc976d7428a9f7194ea79911aa4bf471f44ee13a9464"}, - {file = "greenlet-3.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:4cd83fb8d8e17633ad534d9ac93719ef8937568d730ef07ac3a98cb520fd93e4"}, - {file = "greenlet-3.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a5b2d4cdaf1c71057ff823a19d850ed5c6c2d3686cb71f73ae4d6382aaa7a06"}, - {file = "greenlet-3.0.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2e7dcdfad252f2ca83c685b0fa9fba00e4d8f243b73839229d56ee3d9d219314"}, - {file = "greenlet-3.0.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c94e4e924d09b5a3e37b853fe5924a95eac058cb6f6fb437ebb588b7eda79870"}, - {file = "greenlet-3.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad6fb737e46b8bd63156b8f59ba6cdef46fe2b7db0c5804388a2d0519b8ddb99"}, - {file = "greenlet-3.0.0-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d55db1db455c59b46f794346efce896e754b8942817f46a1bada2d29446e305a"}, - {file = "greenlet-3.0.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:56867a3b3cf26dc8a0beecdb4459c59f4c47cdd5424618c08515f682e1d46692"}, - {file = "greenlet-3.0.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9a812224a5fb17a538207e8cf8e86f517df2080c8ee0f8c1ed2bdaccd18f38f4"}, - {file = "greenlet-3.0.0-cp39-cp39-win32.whl", hash = "sha256:0d3f83ffb18dc57243e0151331e3c383b05e5b6c5029ac29f754745c800f8ed9"}, - {file = "greenlet-3.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:831d6f35037cf18ca5e80a737a27d822d87cd922521d18ed3dbc8a6967be50ce"}, - {file = "greenlet-3.0.0-cp39-universal2-macosx_11_0_x86_64.whl", hash = "sha256:a048293392d4e058298710a54dfaefcefdf49d287cd33fb1f7d63d55426e4355"}, - {file = "greenlet-3.0.0.tar.gz", hash = "sha256:19834e3f91f485442adc1ee440171ec5d9a4840a1f7bd5ed97833544719ce10b"}, -] - -[package.extras] -docs = ["Sphinx"] -test = ["objgraph", "psutil"] + {file = "griffe-0.32.3-py3-none-any.whl", hash = "sha256:d9471934225818bf8f309822f70451cc6abb4b24e59e0bb27402a45f9412510f"}, + {file = "griffe-0.32.3.tar.gz", hash = "sha256:14983896ad581f59d5ad7b6c9261ff12bdaa905acccc1129341d13e545da8521"}, +] + +[package.dependencies] +colorama = ">=0.4" [[package]] name = "idna" @@ -1291,17 +1324,6 @@ files = [ {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, ] -[[package]] -name = "imagesize" -version = "1.4.1" -description = "Getting image size from png/jpeg/jpeg2000/gif file" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, - {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, -] - [[package]] name = "importlib-metadata" version = "6.8.0" @@ -1321,6 +1343,24 @@ docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker perf = ["ipython"] testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] +[[package]] +name = "importlib-resources" +version = "6.1.0" +description = "Read resources from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_resources-6.1.0-py3-none-any.whl", hash = "sha256:aa50258bbfa56d4e33fbd8aa3ef48ded10d1735f11532b8df95388cc6bdb7e83"}, + {file = "importlib_resources-6.1.0.tar.gz", hash = "sha256:9d48dcccc213325e810fd723e7fbb45ccb39f6cf5c31f00cf2b965f5f10f3cb9"}, +] + +[package.dependencies] +zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff", "zipp (>=3.17)"] + [[package]] name = "iniconfig" version = "2.0.0" @@ -1332,17 +1372,6 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] -[[package]] -name = "invoke" -version = "2.2.0" -description = "Pythonic task execution" -optional = false -python-versions = ">=3.6" -files = [ - {file = "invoke-2.2.0-py3-none-any.whl", hash = "sha256:6ea924cc53d4f78e3d98bc436b08069a03077e6f85ad1ddaa8a116d7dad15820"}, - {file = "invoke-2.2.0.tar.gz", hash = "sha256:ee6cbb101af1a859c7fe84f2a264c059020b0cb7fe3535f9424300ab568f6bd5"}, -] - [[package]] name = "ipykernel" version = "6.25.2" @@ -1416,6 +1445,52 @@ qtconsole = ["qtconsole"] test = ["pytest (<7.1)", "pytest-asyncio", "testpath"] test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.21)", "pandas", "pytest (<7.1)", "pytest-asyncio", "testpath", "trio"] +[[package]] +name = "ipython-genutils" +version = "0.2.0" +description = "Vestigial utilities from IPython" +optional = false +python-versions = "*" +files = [ + {file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"}, + {file = "ipython_genutils-0.2.0.tar.gz", hash = "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"}, +] + +[[package]] +name = "ipywidgets" +version = "8.1.1" +description = "Jupyter interactive widgets" +optional = false +python-versions = ">=3.7" +files = [ + {file = "ipywidgets-8.1.1-py3-none-any.whl", hash = "sha256:2b88d728656aea3bbfd05d32c747cfd0078f9d7e159cf982433b58ad717eed7f"}, + {file = "ipywidgets-8.1.1.tar.gz", hash = "sha256:40211efb556adec6fa450ccc2a77d59ca44a060f4f9f136833df59c9f538e6e8"}, +] + +[package.dependencies] +comm = ">=0.1.3" +ipython = ">=6.1.0" +jupyterlab-widgets = ">=3.0.9,<3.1.0" +traitlets = ">=4.3.1" +widgetsnbextension = ">=4.0.9,<4.1.0" + +[package.extras] +test = ["ipykernel", "jsonschema", "pytest (>=3.6.0)", "pytest-cov", "pytz"] + +[[package]] +name = "isoduration" +version = "20.11.0" +description = "Operations with ISO 8601 durations" +optional = false +python-versions = ">=3.7" +files = [ + {file = "isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042"}, + {file = "isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9"}, +] + +[package.dependencies] +arrow = ">=0.15.0" + [[package]] name = "isort" version = "5.12.0" @@ -1480,6 +1555,31 @@ files = [ {file = "jmespath-1.0.1.tar.gz", hash = "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe"}, ] +[[package]] +name = "json5" +version = "0.9.14" +description = "A Python implementation of the JSON5 data format." +optional = false +python-versions = "*" +files = [ + {file = "json5-0.9.14-py2.py3-none-any.whl", hash = "sha256:740c7f1b9e584a468dbb2939d8d458db3427f2c93ae2139d05f47e453eae964f"}, + {file = "json5-0.9.14.tar.gz", hash = "sha256:9ed66c3a6ca3510a976a9ef9b8c0787de24802724ab1860bc0153c7fdd589b02"}, +] + +[package.extras] +dev = ["hypothesis"] + +[[package]] +name = "jsonpointer" +version = "2.4" +description = "Identify specific nodes in a JSON document (RFC 6901)" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +files = [ + {file = "jsonpointer-2.4-py2.py3-none-any.whl", hash = "sha256:15d51bba20eea3165644553647711d150376234112651b4f1811022aecad7d7a"}, + {file = "jsonpointer-2.4.tar.gz", hash = "sha256:585cee82b70211fa9e6043b7bb89db6e1aa49524340dde8ad6b63206ea689d88"}, +] + [[package]] name = "jsonschema" version = "4.19.1" @@ -1493,9 +1593,17 @@ files = [ [package.dependencies] attrs = ">=22.2.0" +fqdn = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +idna = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +isoduration = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +jsonpointer = {version = ">1.13", optional = true, markers = "extra == \"format-nongpl\""} jsonschema-specifications = ">=2023.03.6" referencing = ">=0.28.4" +rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} rpds-py = ">=0.7.1" +uri-template = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +webcolors = {version = ">=1.11", optional = true, markers = "extra == \"format-nongpl\""} [package.extras] format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] @@ -1516,31 +1624,24 @@ files = [ referencing = ">=0.28.0" [[package]] -name = "jupyter-cache" -version = "0.6.1" -description = "A defined interface for working with a cache of jupyter notebooks." +name = "jupyter" +version = "1.0.0" +description = "Jupyter metapackage. Install all the Jupyter components in one go." optional = false -python-versions = "~=3.8" +python-versions = "*" files = [ - {file = "jupyter-cache-0.6.1.tar.gz", hash = "sha256:26f83901143edf4af2f3ff5a91e2d2ad298e46e2cee03c8071d37a23a63ccbfc"}, - {file = "jupyter_cache-0.6.1-py3-none-any.whl", hash = "sha256:2fce7d4975805c77f75bdfc1bc2e82bc538b8e5b1af27f2f5e06d55b9f996a82"}, + {file = "jupyter-1.0.0-py2.py3-none-any.whl", hash = "sha256:5b290f93b98ffbc21c0c7e749f054b3267782166d72fa5e3ed1ed4eaf34a2b78"}, + {file = "jupyter-1.0.0.tar.gz", hash = "sha256:d9dc4b3318f310e34c82951ea5d6683f67bed7def4b259fafbfe4f1beb1d8e5f"}, + {file = "jupyter-1.0.0.zip", hash = "sha256:3e1f86076bbb7c8c207829390305a2b1fe836d471ed54be66a3b8c41e7f46cc7"}, ] [package.dependencies] -attrs = "*" -click = "*" -importlib-metadata = "*" -nbclient = ">=0.2,<0.8" -nbformat = "*" -pyyaml = "*" -sqlalchemy = ">=1.3.12,<3" -tabulate = "*" - -[package.extras] -cli = ["click-log"] -code-style = ["pre-commit (>=2.12,<4.0)"] -rtd = ["ipykernel", "jupytext", "myst-nb", "nbdime", "sphinx-book-theme", "sphinx-copybutton"] -testing = ["coverage", "ipykernel", "jupytext", "matplotlib", "nbdime", "nbformat (>=5.1)", "numpy", "pandas", "pytest (>=6,<8)", "pytest-cov", "pytest-regressions", "sympy"] +ipykernel = "*" +ipywidgets = "*" +jupyter-console = "*" +nbconvert = "*" +notebook = "*" +qtconsole = "*" [[package]] name = "jupyter-client" @@ -1565,15 +1666,39 @@ traitlets = ">=5.3" docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko", "pre-commit", "pytest", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] +[[package]] +name = "jupyter-console" +version = "6.6.3" +description = "Jupyter terminal console" +optional = false +python-versions = ">=3.7" +files = [ + {file = "jupyter_console-6.6.3-py3-none-any.whl", hash = "sha256:309d33409fcc92ffdad25f0bcdf9a4a9daa61b6f341177570fdac03de5352485"}, + {file = "jupyter_console-6.6.3.tar.gz", hash = "sha256:566a4bf31c87adbfadf22cdf846e3069b59a71ed5da71d6ba4d8aaad14a53539"}, +] + +[package.dependencies] +ipykernel = ">=6.14" +ipython = "*" +jupyter-client = ">=7.0.0" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +prompt-toolkit = ">=3.0.30" +pygments = "*" +pyzmq = ">=17" +traitlets = ">=5.4" + +[package.extras] +test = ["flaky", "pexpect", "pytest"] + [[package]] name = "jupyter-core" -version = "5.3.2" +version = "5.4.0" description = "Jupyter core package. A base package on which Jupyter projects rely." optional = false python-versions = ">=3.8" files = [ - {file = "jupyter_core-5.3.2-py3-none-any.whl", hash = "sha256:a4af53c3fa3f6330cebb0d9f658e148725d15652811d1c32dc0f63bb96f2e6d6"}, - {file = "jupyter_core-5.3.2.tar.gz", hash = "sha256:0c28db6cbe2c37b5b398e1a1a5b22f84fd64cd10afc1f6c05b02fb09481ba45f"}, + {file = "jupyter_core-5.4.0-py3-none-any.whl", hash = "sha256:66e252f675ac04dcf2feb6ed4afb3cd7f68cf92f483607522dc251f32d471571"}, + {file = "jupyter_core-5.4.0.tar.gz", hash = "sha256:e4b98344bb94ee2e3e6c4519a97d001656009f9cb2b7f2baf15b3c205770011d"}, ] [package.dependencies] @@ -1586,170 +1711,179 @@ docs = ["myst-parser", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", " test = ["ipykernel", "pre-commit", "pytest", "pytest-cov", "pytest-timeout"] [[package]] -name = "linkify-it-py" -version = "2.0.2" -description = "Links recognition library with FULL unicode support." +name = "jupyter-events" +version = "0.7.0" +description = "Jupyter Event System library" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "linkify-it-py-2.0.2.tar.gz", hash = "sha256:19f3060727842c254c808e99d465c80c49d2c7306788140987a1a7a29b0d6ad2"}, - {file = "linkify_it_py-2.0.2-py3-none-any.whl", hash = "sha256:a3a24428f6c96f27370d7fe61d2ac0be09017be5190d68d8658233171f1b6541"}, + {file = "jupyter_events-0.7.0-py3-none-any.whl", hash = "sha256:4753da434c13a37c3f3c89b500afa0c0a6241633441421f6adafe2fb2e2b924e"}, + {file = "jupyter_events-0.7.0.tar.gz", hash = "sha256:7be27f54b8388c03eefea123a4f79247c5b9381c49fb1cd48615ee191eb12615"}, ] [package.dependencies] -uc-micro-py = "*" +jsonschema = {version = ">=4.18.0", extras = ["format-nongpl"]} +python-json-logger = ">=2.0.4" +pyyaml = ">=5.3" +referencing = "*" +rfc3339-validator = "*" +rfc3986-validator = ">=0.1.1" +traitlets = ">=5.3" [package.extras] -benchmark = ["pytest", "pytest-benchmark"] -dev = ["black", "flake8", "isort", "pre-commit", "pyproject-flake8"] -doc = ["myst-parser", "sphinx", "sphinx-book-theme"] -test = ["coverage", "pytest", "pytest-cov"] +cli = ["click", "rich"] +docs = ["jupyterlite-sphinx", "myst-parser", "pydata-sphinx-theme", "sphinxcontrib-spelling"] +test = ["click", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.19.0)", "pytest-console-scripts", "rich"] [[package]] -name = "livereload" -version = "2.6.3" -description = "Python LiveReload is an awesome tool for web developers" +name = "jupyter-lsp" +version = "2.2.0" +description = "Multi-Language Server WebSocket proxy for Jupyter Notebook/Lab server" optional = false -python-versions = "*" +python-versions = ">=3.8" files = [ - {file = "livereload-2.6.3-py2.py3-none-any.whl", hash = "sha256:ad4ac6f53b2d62bb6ce1a5e6e96f1f00976a32348afedcb4b6d68df2a1d346e4"}, - {file = "livereload-2.6.3.tar.gz", hash = "sha256:776f2f865e59fde56490a56bcc6773b6917366bce0c267c60ee8aaf1a0959869"}, + {file = "jupyter-lsp-2.2.0.tar.gz", hash = "sha256:8ebbcb533adb41e5d635eb8fe82956b0aafbf0fd443b6c4bfa906edeeb8635a1"}, + {file = "jupyter_lsp-2.2.0-py3-none-any.whl", hash = "sha256:9e06b8b4f7dd50300b70dd1a78c0c3b0c3d8fa68e0f2d8a5d1fbab62072aca3f"}, ] [package.dependencies] -six = "*" -tornado = {version = "*", markers = "python_version > \"2.7\""} - -[[package]] -name = "lxml" -version = "4.9.3" -description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, != 3.4.*" -files = [ - {file = "lxml-4.9.3-cp27-cp27m-macosx_11_0_x86_64.whl", hash = "sha256:b0a545b46b526d418eb91754565ba5b63b1c0b12f9bd2f808c852d9b4b2f9b5c"}, - {file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:075b731ddd9e7f68ad24c635374211376aa05a281673ede86cbe1d1b3455279d"}, - {file = "lxml-4.9.3-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1e224d5755dba2f4a9498e150c43792392ac9b5380aa1b845f98a1618c94eeef"}, - {file = "lxml-4.9.3-cp27-cp27m-win32.whl", hash = "sha256:2c74524e179f2ad6d2a4f7caf70e2d96639c0954c943ad601a9e146c76408ed7"}, - {file = "lxml-4.9.3-cp27-cp27m-win_amd64.whl", hash = "sha256:4f1026bc732b6a7f96369f7bfe1a4f2290fb34dce00d8644bc3036fb351a4ca1"}, - {file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c0781a98ff5e6586926293e59480b64ddd46282953203c76ae15dbbbf302e8bb"}, - {file = "lxml-4.9.3-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:cef2502e7e8a96fe5ad686d60b49e1ab03e438bd9123987994528febd569868e"}, - {file = "lxml-4.9.3-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:b86164d2cff4d3aaa1f04a14685cbc072efd0b4f99ca5708b2ad1b9b5988a991"}, - {file = "lxml-4.9.3-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:42871176e7896d5d45138f6d28751053c711ed4d48d8e30b498da155af39aebd"}, - {file = "lxml-4.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:ae8b9c6deb1e634ba4f1930eb67ef6e6bf6a44b6eb5ad605642b2d6d5ed9ce3c"}, - {file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:411007c0d88188d9f621b11d252cce90c4a2d1a49db6c068e3c16422f306eab8"}, - {file = "lxml-4.9.3-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:cd47b4a0d41d2afa3e58e5bf1f62069255aa2fd6ff5ee41604418ca925911d76"}, - {file = "lxml-4.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0e2cb47860da1f7e9a5256254b74ae331687b9672dfa780eed355c4c9c3dbd23"}, - {file = "lxml-4.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1247694b26342a7bf47c02e513d32225ededd18045264d40758abeb3c838a51f"}, - {file = "lxml-4.9.3-cp310-cp310-win32.whl", hash = "sha256:cdb650fc86227eba20de1a29d4b2c1bfe139dc75a0669270033cb2ea3d391b85"}, - {file = "lxml-4.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:97047f0d25cd4bcae81f9ec9dc290ca3e15927c192df17331b53bebe0e3ff96d"}, - {file = "lxml-4.9.3-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:1f447ea5429b54f9582d4b955f5f1985f278ce5cf169f72eea8afd9502973dd5"}, - {file = "lxml-4.9.3-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:57d6ba0ca2b0c462f339640d22882acc711de224d769edf29962b09f77129cbf"}, - {file = "lxml-4.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:9767e79108424fb6c3edf8f81e6730666a50feb01a328f4a016464a5893f835a"}, - {file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:71c52db65e4b56b8ddc5bb89fb2e66c558ed9d1a74a45ceb7dcb20c191c3df2f"}, - {file = "lxml-4.9.3-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:d73d8ecf8ecf10a3bd007f2192725a34bd62898e8da27eb9d32a58084f93962b"}, - {file = "lxml-4.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0a3d3487f07c1d7f150894c238299934a2a074ef590b583103a45002035be120"}, - {file = "lxml-4.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e28c51fa0ce5674be9f560c6761c1b441631901993f76700b1b30ca6c8378d6"}, - {file = "lxml-4.9.3-cp311-cp311-win32.whl", hash = "sha256:0bfd0767c5c1de2551a120673b72e5d4b628737cb05414f03c3277bf9bed3305"}, - {file = "lxml-4.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:25f32acefac14ef7bd53e4218fe93b804ef6f6b92ffdb4322bb6d49d94cad2bc"}, - {file = "lxml-4.9.3-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:d3ff32724f98fbbbfa9f49d82852b159e9784d6094983d9a8b7f2ddaebb063d4"}, - {file = "lxml-4.9.3-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:48d6ed886b343d11493129e019da91d4039826794a3e3027321c56d9e71505be"}, - {file = "lxml-4.9.3-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9a92d3faef50658dd2c5470af249985782bf754c4e18e15afb67d3ab06233f13"}, - {file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b4e4bc18382088514ebde9328da057775055940a1f2e18f6ad2d78aa0f3ec5b9"}, - {file = "lxml-4.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fc9b106a1bf918db68619fdcd6d5ad4f972fdd19c01d19bdb6bf63f3589a9ec5"}, - {file = "lxml-4.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:d37017287a7adb6ab77e1c5bee9bcf9660f90ff445042b790402a654d2ad81d8"}, - {file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:56dc1f1ebccc656d1b3ed288f11e27172a01503fc016bcabdcbc0978b19352b7"}, - {file = "lxml-4.9.3-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:578695735c5a3f51569810dfebd05dd6f888147a34f0f98d4bb27e92b76e05c2"}, - {file = "lxml-4.9.3-cp35-cp35m-win32.whl", hash = "sha256:704f61ba8c1283c71b16135caf697557f5ecf3e74d9e453233e4771d68a1f42d"}, - {file = "lxml-4.9.3-cp35-cp35m-win_amd64.whl", hash = "sha256:c41bfca0bd3532d53d16fd34d20806d5c2b1ace22a2f2e4c0008570bf2c58833"}, - {file = "lxml-4.9.3-cp36-cp36m-macosx_11_0_x86_64.whl", hash = "sha256:64f479d719dc9f4c813ad9bb6b28f8390360660b73b2e4beb4cb0ae7104f1c12"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:dd708cf4ee4408cf46a48b108fb9427bfa00b9b85812a9262b5c668af2533ea5"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c31c7462abdf8f2ac0577d9f05279727e698f97ecbb02f17939ea99ae8daa98"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e3cd95e10c2610c360154afdc2f1480aea394f4a4f1ea0a5eacce49640c9b190"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:4930be26af26ac545c3dffb662521d4e6268352866956672231887d18f0eaab2"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4aec80cde9197340bc353d2768e2a75f5f60bacda2bab72ab1dc499589b3878c"}, - {file = "lxml-4.9.3-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:14e019fd83b831b2e61baed40cab76222139926b1fb5ed0e79225bc0cae14584"}, - {file = "lxml-4.9.3-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0c0850c8b02c298d3c7006b23e98249515ac57430e16a166873fc47a5d549287"}, - {file = "lxml-4.9.3-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:aca086dc5f9ef98c512bac8efea4483eb84abbf926eaeedf7b91479feb092458"}, - {file = "lxml-4.9.3-cp36-cp36m-win32.whl", hash = "sha256:50baa9c1c47efcaef189f31e3d00d697c6d4afda5c3cde0302d063492ff9b477"}, - {file = "lxml-4.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:bef4e656f7d98aaa3486d2627e7d2df1157d7e88e7efd43a65aa5dd4714916cf"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:46f409a2d60f634fe550f7133ed30ad5321ae2e6630f13657fb9479506b00601"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:4c28a9144688aef80d6ea666c809b4b0e50010a2aca784c97f5e6bf143d9f129"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:141f1d1a9b663c679dc524af3ea1773e618907e96075262726c7612c02b149a4"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:53ace1c1fd5a74ef662f844a0413446c0629d151055340e9893da958a374f70d"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:17a753023436a18e27dd7769e798ce302963c236bc4114ceee5b25c18c52c693"}, - {file = "lxml-4.9.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7d298a1bd60c067ea75d9f684f5f3992c9d6766fadbc0bcedd39750bf344c2f4"}, - {file = "lxml-4.9.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:081d32421db5df44c41b7f08a334a090a545c54ba977e47fd7cc2deece78809a"}, - {file = "lxml-4.9.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:23eed6d7b1a3336ad92d8e39d4bfe09073c31bfe502f20ca5116b2a334f8ec02"}, - {file = "lxml-4.9.3-cp37-cp37m-win32.whl", hash = "sha256:1509dd12b773c02acd154582088820893109f6ca27ef7291b003d0e81666109f"}, - {file = "lxml-4.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:120fa9349a24c7043854c53cae8cec227e1f79195a7493e09e0c12e29f918e52"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4d2d1edbca80b510443f51afd8496be95529db04a509bc8faee49c7b0fb6d2cc"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:8d7e43bd40f65f7d97ad8ef5c9b1778943d02f04febef12def25f7583d19baac"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:71d66ee82e7417828af6ecd7db817913cb0cf9d4e61aa0ac1fde0583d84358db"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:6fc3c450eaa0b56f815c7b62f2b7fba7266c4779adcf1cece9e6deb1de7305ce"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:65299ea57d82fb91c7f019300d24050c4ddeb7c5a190e076b5f48a2b43d19c42"}, - {file = "lxml-4.9.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:eadfbbbfb41b44034a4c757fd5d70baccd43296fb894dba0295606a7cf3124aa"}, - {file = "lxml-4.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3e9bdd30efde2b9ccfa9cb5768ba04fe71b018a25ea093379c857c9dad262c40"}, - {file = "lxml-4.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:fcdd00edfd0a3001e0181eab3e63bd5c74ad3e67152c84f93f13769a40e073a7"}, - {file = "lxml-4.9.3-cp38-cp38-win32.whl", hash = "sha256:57aba1bbdf450b726d58b2aea5fe47c7875f5afb2c4a23784ed78f19a0462574"}, - {file = "lxml-4.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:92af161ecbdb2883c4593d5ed4815ea71b31fafd7fd05789b23100d081ecac96"}, - {file = "lxml-4.9.3-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:9bb6ad405121241e99a86efff22d3ef469024ce22875a7ae045896ad23ba2340"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8ed74706b26ad100433da4b9d807eae371efaa266ffc3e9191ea436087a9d6a7"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fbf521479bcac1e25a663df882c46a641a9bff6b56dc8b0fafaebd2f66fb231b"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:303bf1edce6ced16bf67a18a1cf8339d0db79577eec5d9a6d4a80f0fb10aa2da"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:5515edd2a6d1a5a70bfcdee23b42ec33425e405c5b351478ab7dc9347228f96e"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:690dafd0b187ed38583a648076865d8c229661ed20e48f2335d68e2cf7dc829d"}, - {file = "lxml-4.9.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b6420a005548ad52154c8ceab4a1290ff78d757f9e5cbc68f8c77089acd3c432"}, - {file = "lxml-4.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bb3bb49c7a6ad9d981d734ef7c7193bc349ac338776a0360cc671eaee89bcf69"}, - {file = "lxml-4.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d27be7405547d1f958b60837dc4c1007da90b8b23f54ba1f8b728c78fdb19d50"}, - {file = "lxml-4.9.3-cp39-cp39-win32.whl", hash = "sha256:8df133a2ea5e74eef5e8fc6f19b9e085f758768a16e9877a60aec455ed2609b2"}, - {file = "lxml-4.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:4dd9a263e845a72eacb60d12401e37c616438ea2e5442885f65082c276dfb2b2"}, - {file = "lxml-4.9.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6689a3d7fd13dc687e9102a27e98ef33730ac4fe37795d5036d18b4d527abd35"}, - {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:f6bdac493b949141b733c5345b6ba8f87a226029cbabc7e9e121a413e49441e0"}, - {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:05186a0f1346ae12553d66df1cfce6f251589fea3ad3da4f3ef4e34b2d58c6a3"}, - {file = "lxml-4.9.3-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c2006f5c8d28dee289f7020f721354362fa304acbaaf9745751ac4006650254b"}, - {file = "lxml-4.9.3-pp38-pypy38_pp73-macosx_11_0_x86_64.whl", hash = "sha256:5c245b783db29c4e4fbbbfc9c5a78be496c9fea25517f90606aa1f6b2b3d5f7b"}, - {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:4fb960a632a49f2f089d522f70496640fdf1218f1243889da3822e0a9f5f3ba7"}, - {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:50670615eaf97227d5dc60de2dc99fb134a7130d310d783314e7724bf163f75d"}, - {file = "lxml-4.9.3-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9719fe17307a9e814580af1f5c6e05ca593b12fb7e44fe62450a5384dbf61b4b"}, - {file = "lxml-4.9.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:3331bece23c9ee066e0fb3f96c61322b9e0f54d775fccefff4c38ca488de283a"}, - {file = "lxml-4.9.3-pp39-pypy39_pp73-macosx_11_0_x86_64.whl", hash = "sha256:ed667f49b11360951e201453fc3967344d0d0263aa415e1619e85ae7fd17b4e0"}, - {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_24_i686.whl", hash = "sha256:8b77946fd508cbf0fccd8e400a7f71d4ac0e1595812e66025bac475a8e811694"}, - {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:e4da8ca0c0c0aea88fd46be8e44bd49716772358d648cce45fe387f7b92374a7"}, - {file = "lxml-4.9.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:fe4bda6bd4340caa6e5cf95e73f8fea5c4bfc55763dd42f1b50a94c1b4a2fbd4"}, - {file = "lxml-4.9.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:f3df3db1d336b9356dd3112eae5f5c2b8b377f3bc826848567f10bfddfee77e9"}, - {file = "lxml-4.9.3.tar.gz", hash = "sha256:48628bd53a426c9eb9bc066a923acaa0878d1e86129fd5359aee99285f4eed9c"}, -] - -[package.extras] -cssselect = ["cssselect (>=0.7)"] -html5 = ["html5lib"] -htmlsoup = ["BeautifulSoup4"] -source = ["Cython (>=0.29.35)"] - -[[package]] -name = "markdown-it-py" -version = "3.0.0" -description = "Python port of markdown-it. Markdown parsing, done right!" +importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} +jupyter-server = ">=1.1.2" + +[[package]] +name = "jupyter-server" +version = "2.7.3" +description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_server-2.7.3-py3-none-any.whl", hash = "sha256:8e4b90380b59d7a1e31086c4692231f2a2ea4cb269f5516e60aba72ce8317fc9"}, + {file = "jupyter_server-2.7.3.tar.gz", hash = "sha256:d4916c8581c4ebbc534cebdaa8eca2478d9f3bfdd88eae29fcab0120eac57649"}, +] + +[package.dependencies] +anyio = ">=3.1.0" +argon2-cffi = "*" +jinja2 = "*" +jupyter-client = ">=7.4.4" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-events = ">=0.6.0" +jupyter-server-terminals = "*" +nbconvert = ">=6.4.4" +nbformat = ">=5.3.0" +overrides = "*" +packaging = "*" +prometheus-client = "*" +pywinpty = {version = "*", markers = "os_name == \"nt\""} +pyzmq = ">=24" +send2trash = ">=1.8.2" +terminado = ">=0.8.3" +tornado = ">=6.2.0" +traitlets = ">=5.6.0" +websocket-client = "*" + +[package.extras] +docs = ["ipykernel", "jinja2", "jupyter-client", "jupyter-server", "myst-parser", "nbformat", "prometheus-client", "pydata-sphinx-theme", "send2trash", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-openapi (>=0.8.0)", "sphinxcontrib-spelling", "sphinxemoji", "tornado", "typing-extensions"] +test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0)", "pytest-console-scripts", "pytest-jupyter[server] (>=0.4)", "pytest-timeout", "requests"] + +[[package]] +name = "jupyter-server-terminals" +version = "0.4.4" +description = "A Jupyter Server Extension Providing Terminals." +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyter_server_terminals-0.4.4-py3-none-any.whl", hash = "sha256:75779164661cec02a8758a5311e18bb8eb70c4e86c6b699403100f1585a12a36"}, + {file = "jupyter_server_terminals-0.4.4.tar.gz", hash = "sha256:57ab779797c25a7ba68e97bcfb5d7740f2b5e8a83b5e8102b10438041a7eac5d"}, +] + +[package.dependencies] +pywinpty = {version = ">=2.0.3", markers = "os_name == \"nt\""} +terminado = ">=0.8.3" + +[package.extras] +docs = ["jinja2", "jupyter-server", "mistune (<3.0)", "myst-parser", "nbformat", "packaging", "pydata-sphinx-theme", "sphinxcontrib-github-alt", "sphinxcontrib-openapi", "sphinxcontrib-spelling", "sphinxemoji", "tornado"] +test = ["coverage", "jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-cov", "pytest-jupyter[server] (>=0.5.3)", "pytest-timeout"] + +[[package]] +name = "jupyterlab" +version = "4.0.6" +description = "JupyterLab computational environment" +optional = false +python-versions = ">=3.8" +files = [ + {file = "jupyterlab-4.0.6-py3-none-any.whl", hash = "sha256:7d9dacad1e3f30fe4d6d4efc97fda25fbb5012012b8f27cc03a2283abcdee708"}, + {file = "jupyterlab-4.0.6.tar.gz", hash = "sha256:6c43ae5a6a1fd2fdfafcb3454004958bde6da76331abb44cffc6f9e436b19ba1"}, +] + +[package.dependencies] +async-lru = ">=1.0.0" +importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} +ipykernel = "*" +jinja2 = ">=3.0.3" +jupyter-core = "*" +jupyter-lsp = ">=2.0.0" +jupyter-server = ">=2.4.0,<3" +jupyterlab-server = ">=2.19.0,<3" +notebook-shim = ">=0.2" +packaging = "*" +tomli = {version = "*", markers = "python_version < \"3.11\""} +tornado = ">=6.2.0" +traitlets = "*" + +[package.extras] +dev = ["black[jupyter] (==23.7.0)", "build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.0.286)"] +docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-tornasync", "sphinx (>=1.8,<7.2.0)", "sphinx-copybutton"] +docs-screenshots = ["altair (==5.0.1)", "ipython (==8.14.0)", "ipywidgets (==8.0.6)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.0.post0)", "matplotlib (==3.7.1)", "nbconvert (>=7.0.0)", "pandas (==2.0.2)", "scipy (==1.10.1)", "vega-datasets (==0.9.0)"] +test = ["coverage", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter (>=0.5.3)", "pytest-timeout", "pytest-tornasync", "requests", "requests-cache", "virtualenv"] + +[[package]] +name = "jupyterlab-pygments" +version = "0.2.2" +description = "Pygments theme using JupyterLab CSS variables" +optional = false +python-versions = ">=3.7" +files = [ + {file = "jupyterlab_pygments-0.2.2-py2.py3-none-any.whl", hash = "sha256:2405800db07c9f770863bcf8049a529c3dd4d3e28536638bd7c1c01d2748309f"}, + {file = "jupyterlab_pygments-0.2.2.tar.gz", hash = "sha256:7405d7fde60819d905a9fa8ce89e4cd830e318cdad22a0030f7a901da705585d"}, +] + +[[package]] +name = "jupyterlab-server" +version = "2.25.0" +description = "A set of server components for JupyterLab and JupyterLab like applications." optional = false python-versions = ">=3.8" files = [ - {file = "markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb"}, - {file = "markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1"}, + {file = "jupyterlab_server-2.25.0-py3-none-any.whl", hash = "sha256:c9f67a98b295c5dee87f41551b0558374e45d449f3edca153dd722140630dcb2"}, + {file = "jupyterlab_server-2.25.0.tar.gz", hash = "sha256:77c2f1f282d610f95e496e20d5bf1d2a7706826dfb7b18f3378ae2870d272fb7"}, ] [package.dependencies] -mdurl = ">=0.1,<1.0" +babel = ">=2.10" +importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} +jinja2 = ">=3.0.3" +json5 = ">=0.9.0" +jsonschema = ">=4.18.0" +jupyter-server = ">=1.21,<3" +packaging = ">=21.3" +requests = ">=2.31" [package.extras] -benchmarking = ["psutil", "pytest", "pytest-benchmark"] -code-style = ["pre-commit (>=3.0,<4.0)"] -compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] -linkify = ["linkify-it-py (>=1,<3)"] -plugins = ["mdit-py-plugins"] -profiling = ["gprof2dot"] -rtd = ["jupyter_sphinx", "mdit-py-plugins", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] +docs = ["autodoc-traits", "jinja2 (<3.2.0)", "mistune (<4)", "myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-copybutton", "sphinxcontrib-openapi (>0.8)"] +openapi = ["openapi-core (>=0.18.0,<0.19.0)", "ruamel-yaml"] +test = ["hatch", "ipykernel", "openapi-core (>=0.18.0,<0.19.0)", "openapi-spec-validator (>=0.6.0,<0.7.0)", "pytest (>=7.0)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter[server] (>=0.6.2)", "pytest-timeout", "requests-mock", "ruamel-yaml", "sphinxcontrib-spelling", "strict-rfc3339", "werkzeug"] + +[[package]] +name = "jupyterlab-widgets" +version = "3.0.9" +description = "Jupyter interactive widgets for JupyterLab" +optional = false +python-versions = ">=3.7" +files = [ + {file = "jupyterlab_widgets-3.0.9-py3-none-any.whl", hash = "sha256:3cf5bdf5b897bf3bccf1c11873aa4afd776d7430200f765e0686bd352487b58d"}, + {file = "jupyterlab_widgets-3.0.9.tar.gz", hash = "sha256:6005a4e974c7beee84060fdfba341a3218495046de8ae3ec64888e5fe19fdb4c"}, +] [[package]] name = "markupsafe" @@ -1778,6 +1912,16 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -1865,33 +2009,14 @@ files = [ ] [[package]] -name = "mdit-py-plugins" -version = "0.4.0" -description = "Collection of plugins for markdown-it-py" +name = "mistune" +version = "3.0.2" +description = "A sane and fast Markdown parser with useful plugins and renderers" optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "mdit_py_plugins-0.4.0-py3-none-any.whl", hash = "sha256:b51b3bb70691f57f974e257e367107857a93b36f322a9e6d44ca5bf28ec2def9"}, - {file = "mdit_py_plugins-0.4.0.tar.gz", hash = "sha256:d8ab27e9aed6c38aa716819fedfde15ca275715955f8a185a8e1cf90fb1d2c1b"}, -] - -[package.dependencies] -markdown-it-py = ">=1.0.0,<4.0.0" - -[package.extras] -code-style = ["pre-commit"] -rtd = ["myst-parser", "sphinx-book-theme"] -testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] - -[[package]] -name = "mdurl" -version = "0.1.2" -description = "Markdown URL utilities" -optional = false -python-versions = ">=3.7" -files = [ - {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, - {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, + {file = "mistune-3.0.2-py3-none-any.whl", hash = "sha256:71481854c30fdbc938963d3605b72501f5c10a9320ecd412c121c163a1c7d205"}, + {file = "mistune-3.0.2.tar.gz", hash = "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8"}, ] [[package]] @@ -1966,84 +2091,64 @@ files = [ ] [[package]] -name = "myst-nb" -version = "0.18.0" -description = "A Jupyter Notebook Sphinx reader built on top of the MyST markdown parser." -optional = false -python-versions = ">=3.8" -files = [] -develop = false - -[package.dependencies] -importlib_metadata = "*" -ipykernel = "*" -ipython = "*" -jupyter-cache = ">=0.5,<0.7" -myst-parser = ">=0.18.0" -nbclient = "*" -nbformat = ">=5.0,<6.0" -pyyaml = "*" -sphinx = ">=4" -typing-extensions = "*" - -[package.extras] -code-style = ["pre-commit"] -rtd = ["alabaster", "altair", "bokeh", "coconut (>=1.4.3,<3.1.0)", "ipykernel (>=5.5,<7.0)", "ipywidgets", "jupytext (>=1.11.2,<1.16.0)", "matplotlib", "numpy", "pandas", "plotly", "sphinx-book-theme (>=0.3)", "sphinx-copybutton", "sphinx-design (>=0.4.0,<0.5.0)", "sphinxcontrib-bibtex", "sympy"] -testing = ["beautifulsoup4", "coverage (>=6.4,<8.0)", "ipykernel (>=5.5,<7.0)", "ipython (!=8.1.0,<8.16)", "ipywidgets (>=8)", "jupytext (>=1.11.2,<1.16.0)", "matplotlib (>=3.5.3,<3.6)", "nbdime", "numpy", "pandas", "pytest (>=7.1,<8.0)", "pytest-cov (>=3,<5)", "pytest-param-files (>=0.3.3,<0.4.0)", "pytest-regressions", "sympy (>=1.10.1)"] - -[package.source] -type = "git" -url = "https://github.com/executablebooks/MyST-NB.git" -reference = "59854c270deb76f297f228477be5d5088babd143" -resolved_reference = "59854c270deb76f297f228477be5d5088babd143" - -[[package]] -name = "myst-parser" -version = "2.0.0" -description = "An extended [CommonMark](https://spec.commonmark.org/) compliant parser," +name = "nbclient" +version = "0.8.0" +description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." optional = false -python-versions = ">=3.8" +python-versions = ">=3.8.0" files = [ - {file = "myst_parser-2.0.0-py3-none-any.whl", hash = "sha256:7c36344ae39c8e740dad7fdabf5aa6fc4897a813083c6cc9990044eb93656b14"}, - {file = "myst_parser-2.0.0.tar.gz", hash = "sha256:ea929a67a6a0b1683cdbe19b8d2e724cd7643f8aa3e7bb18dd65beac3483bead"}, + {file = "nbclient-0.8.0-py3-none-any.whl", hash = "sha256:25e861299e5303a0477568557c4045eccc7a34c17fc08e7959558707b9ebe548"}, + {file = "nbclient-0.8.0.tar.gz", hash = "sha256:f9b179cd4b2d7bca965f900a2ebf0db4a12ebff2f36a711cb66861e4ae158e55"}, ] [package.dependencies] -docutils = ">=0.16,<0.21" -jinja2 = "*" -markdown-it-py = ">=3.0,<4.0" -mdit-py-plugins = ">=0.4,<1.0" -pyyaml = "*" -sphinx = ">=6,<8" +jupyter-client = ">=6.1.12" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +nbformat = ">=5.1" +traitlets = ">=5.4" [package.extras] -code-style = ["pre-commit (>=3.0,<4.0)"] -linkify = ["linkify-it-py (>=2.0,<3.0)"] -rtd = ["ipython", "pydata-sphinx-theme (==v0.13.0rc4)", "sphinx-autodoc2 (>=0.4.2,<0.5.0)", "sphinx-book-theme (==1.0.0rc2)", "sphinx-copybutton", "sphinx-design2", "sphinx-pyscript", "sphinx-tippy (>=0.3.1)", "sphinx-togglebutton", "sphinxext-opengraph (>=0.8.2,<0.9.0)", "sphinxext-rediraffe (>=0.2.7,<0.3.0)"] -testing = ["beautifulsoup4", "coverage[toml]", "pytest (>=7,<8)", "pytest-cov", "pytest-param-files (>=0.3.4,<0.4.0)", "pytest-regressions", "sphinx-pytest"] -testing-docutils = ["pygments", "pytest (>=7,<8)", "pytest-param-files (>=0.3.4,<0.4.0)"] +dev = ["pre-commit"] +docs = ["autodoc-traits", "mock", "moto", "myst-parser", "nbclient[test]", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling"] +test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"] [[package]] -name = "nbclient" -version = "0.7.4" -description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." +name = "nbconvert" +version = "7.9.2" +description = "Converting Jupyter Notebooks" optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.8" files = [ - {file = "nbclient-0.7.4-py3-none-any.whl", hash = "sha256:c817c0768c5ff0d60e468e017613e6eae27b6fa31e43f905addd2d24df60c125"}, - {file = "nbclient-0.7.4.tar.gz", hash = "sha256:d447f0e5a4cfe79d462459aec1b3dc5c2e9152597262be8ee27f7d4c02566a0d"}, + {file = "nbconvert-7.9.2-py3-none-any.whl", hash = "sha256:39fe4b8bdd1b0104fdd86fc8a43a9077ba64c720bda4c6132690d917a0a154ee"}, + {file = "nbconvert-7.9.2.tar.gz", hash = "sha256:e56cc7588acc4f93e2bb5a34ec69028e4941797b2bfaf6462f18a41d1cc258c9"}, ] [package.dependencies] -jupyter-client = ">=6.1.12" -jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" -nbformat = ">=5.1" -traitlets = ">=5.3" +beautifulsoup4 = "*" +bleach = "!=5.0.0" +defusedxml = "*" +importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""} +jinja2 = ">=3.0" +jupyter-core = ">=4.7" +jupyterlab-pygments = "*" +markupsafe = ">=2.0" +mistune = ">=2.0.3,<4" +nbclient = ">=0.5.0" +nbformat = ">=5.7" +packaging = "*" +pandocfilters = ">=1.4.1" +pygments = ">=2.4.1" +tinycss2 = "*" +traitlets = ">=5.1" [package.extras] -dev = ["pre-commit"] -docs = ["autodoc-traits", "mock", "moto", "myst-parser", "nbclient[test]", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling"] -test = ["flaky", "ipykernel", "ipython", "ipywidgets", "nbconvert (>=7.0.0)", "pytest (>=7.0)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"] +all = ["nbconvert[docs,qtpdf,serve,test,webpdf]"] +docs = ["ipykernel", "ipython", "myst-parser", "nbsphinx (>=0.2.12)", "pydata-sphinx-theme", "sphinx (==5.0.2)", "sphinxcontrib-spelling"] +qtpdf = ["nbconvert[qtpng]"] +qtpng = ["pyqtwebengine (>=5.15)"] +serve = ["tornado (>=6.1)"] +test = ["flaky", "ipykernel", "ipywidgets (>=7)", "pytest", "pytest-dependency"] +webpdf = ["playwright"] [[package]] name = "nbformat" @@ -2077,6 +2182,46 @@ files = [ {file = "nest_asyncio-1.5.8.tar.gz", hash = "sha256:25aa2ca0d2a5b5531956b9e273b45cf664cae2b145101d73b86b199978d48fdb"}, ] +[[package]] +name = "notebook" +version = "7.0.4" +description = "Jupyter Notebook - A web-based notebook environment for interactive computing" +optional = false +python-versions = ">=3.8" +files = [ + {file = "notebook-7.0.4-py3-none-any.whl", hash = "sha256:ee738414ac01773c1ad6834cf76cc6f1ce140ac8197fd13b3e2d44d89e257f72"}, + {file = "notebook-7.0.4.tar.gz", hash = "sha256:0c1b458f72ce8774445c8ef9ed2492bd0b9ce9605ac996e2b066114f69795e71"}, +] + +[package.dependencies] +jupyter-server = ">=2.4.0,<3" +jupyterlab = ">=4.0.2,<5" +jupyterlab-server = ">=2.22.1,<3" +notebook-shim = ">=0.2,<0.3" +tornado = ">=6.2.0" + +[package.extras] +dev = ["hatch", "pre-commit"] +docs = ["myst-parser", "nbsphinx", "pydata-sphinx-theme", "sphinx (>=1.3.6)", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["importlib-resources (>=5.0)", "ipykernel", "jupyter-server[test] (>=2.4.0,<3)", "jupyterlab-server[test] (>=2.22.1,<3)", "nbval", "pytest (>=7.0)", "pytest-console-scripts", "pytest-timeout", "pytest-tornasync", "requests"] + +[[package]] +name = "notebook-shim" +version = "0.2.3" +description = "A shim layer for notebook traits and config" +optional = false +python-versions = ">=3.7" +files = [ + {file = "notebook_shim-0.2.3-py3-none-any.whl", hash = "sha256:a83496a43341c1674b093bfcebf0fe8e74cbe7eda5fd2bbc56f8e39e1486c0c7"}, + {file = "notebook_shim-0.2.3.tar.gz", hash = "sha256:f69388ac283ae008cd506dda10d0288b09a017d822d5e8c7129a152cbd3ce7e9"}, +] + +[package.dependencies] +jupyter-server = ">=1.8,<3" + +[package.extras] +test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync"] + [[package]] name = "nox" version = "2023.4.22" @@ -2131,6 +2276,17 @@ files = [ {file = "numpy-1.25.2.tar.gz", hash = "sha256:fd608e19c8d7c55021dffd43bfe5492fab8cc105cc8986f813f8c3c048b38760"}, ] +[[package]] +name = "overrides" +version = "7.4.0" +description = "A decorator to automatically detect mismatch when overriding a method." +optional = false +python-versions = ">=3.6" +files = [ + {file = "overrides-7.4.0-py3-none-any.whl", hash = "sha256:3ad24583f86d6d7a49049695efe9933e67ba62f0c7625d53c59fa832ce4b8b7d"}, + {file = "overrides-7.4.0.tar.gz", hash = "sha256:9502a3cca51f4fac40b5feca985b6703a5c1f6ad815588a7ca9e285b9dca6757"}, +] + [[package]] name = "packaging" version = "23.2" @@ -2282,6 +2438,17 @@ files = [ numpy = {version = ">=1.25.0", markers = "python_version >= \"3.9\""} types-pytz = ">=2022.1.1" +[[package]] +name = "pandocfilters" +version = "1.5.0" +description = "Utilities for writing pandoc filters in python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "pandocfilters-1.5.0-py2.py3-none-any.whl", hash = "sha256:33aae3f25fd1a026079f5d27bdd52496f0e0803b3469282162bafdcbdf6ef14f"}, + {file = "pandocfilters-1.5.0.tar.gz", hash = "sha256:0b679503337d233b4339a817bfc8c50064e2eff681314376a47cb582305a7a38"}, +] + [[package]] name = "parso" version = "0.8.3" @@ -2392,6 +2559,49 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "plum-dispatch" +version = "1.7.4" +description = "Multiple dispatch in Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "plum-dispatch-1.7.4.tar.gz", hash = "sha256:1c1d15b2842b5fa98405fd3dff6fad4887bdc77b60bd200e209d76ebfe9990fe"}, + {file = "plum_dispatch-1.7.4-py3-none-any.whl", hash = "sha256:c40dbeab269bbbf972ce0dbc078380da19ebaee1a370a2c564e1814a11bde216"}, +] + +[[package]] +name = "plum-dispatch" +version = "2.2.2" +description = "Multiple dispatch in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "plum_dispatch-2.2.2-py3-none-any.whl", hash = "sha256:d7ee415bd166ffa90eaa4b24d7c9dc7ca6f8875750586001e7c9baff706223bd"}, + {file = "plum_dispatch-2.2.2.tar.gz", hash = "sha256:d5d180225c9fbf0277375bb558b649d97d0b651a91037bb7155cedbe9f52764b"}, +] + +[package.dependencies] +beartype = ">=0.16.2" +typing-extensions = {version = "*", markers = "python_version <= \"3.10\""} + +[package.extras] +dev = ["black (==23.9.0)", "build", "coveralls", "ghp-import", "ipython", "jupyter-book", "mypy", "numpy", "pre-commit", "pyright", "pytest (>=6)", "pytest-cov", "tox", "wheel"] + +[[package]] +name = "prometheus-client" +version = "0.17.1" +description = "Python client for the Prometheus monitoring system." +optional = false +python-versions = ">=3.6" +files = [ + {file = "prometheus_client-0.17.1-py3-none-any.whl", hash = "sha256:e537f37160f6807b8202a6fc4764cdd19bac5480ddd3e0d463c3002b34462101"}, + {file = "prometheus_client-0.17.1.tar.gz", hash = "sha256:21e674f39831ae3f8acde238afd9a27a37d0d2fb5a28ea094f0ce25d2cbf2091"}, +] + +[package.extras] +twisted = ["twisted"] + [[package]] name = "prompt-toolkit" version = "3.0.39" @@ -2518,183 +2728,55 @@ files = [ [[package]] name = "pydantic" -version = "2.4.2" -description = "Data validation using Python type hints" +version = "1.10.13" +description = "Data validation and settings management using python type hints" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-2.4.2-py3-none-any.whl", hash = "sha256:bc3ddf669d234f4220e6e1c4d96b061abe0998185a8d7855c0126782b7abc8c1"}, - {file = "pydantic-2.4.2.tar.gz", hash = "sha256:94f336138093a5d7f426aac732dcfe7ab4eb4da243c88f891d65deb4a2556ee7"}, + {file = "pydantic-1.10.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:efff03cc7a4f29d9009d1c96ceb1e7a70a65cfe86e89d34e4a5f2ab1e5693737"}, + {file = "pydantic-1.10.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ecea2b9d80e5333303eeb77e180b90e95eea8f765d08c3d278cd56b00345d01"}, + {file = "pydantic-1.10.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1740068fd8e2ef6eb27a20e5651df000978edce6da6803c2bef0bc74540f9548"}, + {file = "pydantic-1.10.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84bafe2e60b5e78bc64a2941b4c071a4b7404c5c907f5f5a99b0139781e69ed8"}, + {file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bc0898c12f8e9c97f6cd44c0ed70d55749eaf783716896960b4ecce2edfd2d69"}, + {file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:654db58ae399fe6434e55325a2c3e959836bd17a6f6a0b6ca8107ea0571d2e17"}, + {file = "pydantic-1.10.13-cp310-cp310-win_amd64.whl", hash = "sha256:75ac15385a3534d887a99c713aa3da88a30fbd6204a5cd0dc4dab3d770b9bd2f"}, + {file = "pydantic-1.10.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c553f6a156deb868ba38a23cf0df886c63492e9257f60a79c0fd8e7173537653"}, + {file = "pydantic-1.10.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5e08865bc6464df8c7d61439ef4439829e3ab62ab1669cddea8dd00cd74b9ffe"}, + {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e31647d85a2013d926ce60b84f9dd5300d44535a9941fe825dc349ae1f760df9"}, + {file = "pydantic-1.10.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:210ce042e8f6f7c01168b2d84d4c9eb2b009fe7bf572c2266e235edf14bacd80"}, + {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8ae5dd6b721459bfa30805f4c25880e0dd78fc5b5879f9f7a692196ddcb5a580"}, + {file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f8e81fc5fb17dae698f52bdd1c4f18b6ca674d7068242b2aff075f588301bbb0"}, + {file = "pydantic-1.10.13-cp311-cp311-win_amd64.whl", hash = "sha256:61d9dce220447fb74f45e73d7ff3b530e25db30192ad8d425166d43c5deb6df0"}, + {file = "pydantic-1.10.13-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4b03e42ec20286f052490423682016fd80fda830d8e4119f8ab13ec7464c0132"}, + {file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f59ef915cac80275245824e9d771ee939133be38215555e9dc90c6cb148aaeb5"}, + {file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a1f9f747851338933942db7af7b6ee8268568ef2ed86c4185c6ef4402e80ba8"}, + {file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:97cce3ae7341f7620a0ba5ef6cf043975cd9d2b81f3aa5f4ea37928269bc1b87"}, + {file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:854223752ba81e3abf663d685f105c64150873cc6f5d0c01d3e3220bcff7d36f"}, + {file = "pydantic-1.10.13-cp37-cp37m-win_amd64.whl", hash = "sha256:b97c1fac8c49be29486df85968682b0afa77e1b809aff74b83081cc115e52f33"}, + {file = "pydantic-1.10.13-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c958d053453a1c4b1c2062b05cd42d9d5c8eb67537b8d5a7e3c3032943ecd261"}, + {file = "pydantic-1.10.13-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c5370a7edaac06daee3af1c8b1192e305bc102abcbf2a92374b5bc793818599"}, + {file = "pydantic-1.10.13-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d6f6e7305244bddb4414ba7094ce910560c907bdfa3501e9db1a7fd7eaea127"}, + {file = "pydantic-1.10.13-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3a3c792a58e1622667a2837512099eac62490cdfd63bd407993aaf200a4cf1f"}, + {file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c636925f38b8db208e09d344c7aa4f29a86bb9947495dd6b6d376ad10334fb78"}, + {file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:678bcf5591b63cc917100dc50ab6caebe597ac67e8c9ccb75e698f66038ea953"}, + {file = "pydantic-1.10.13-cp38-cp38-win_amd64.whl", hash = "sha256:6cf25c1a65c27923a17b3da28a0bdb99f62ee04230c931d83e888012851f4e7f"}, + {file = "pydantic-1.10.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8ef467901d7a41fa0ca6db9ae3ec0021e3f657ce2c208e98cd511f3161c762c6"}, + {file = "pydantic-1.10.13-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:968ac42970f57b8344ee08837b62f6ee6f53c33f603547a55571c954a4225691"}, + {file = "pydantic-1.10.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9849f031cf8a2f0a928fe885e5a04b08006d6d41876b8bbd2fc68a18f9f2e3fd"}, + {file = "pydantic-1.10.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:56e3ff861c3b9c6857579de282ce8baabf443f42ffba355bf070770ed63e11e1"}, + {file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f00790179497767aae6bcdc36355792c79e7bbb20b145ff449700eb076c5f96"}, + {file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:75b297827b59bc229cac1a23a2f7a4ac0031068e5be0ce385be1462e7e17a35d"}, + {file = "pydantic-1.10.13-cp39-cp39-win_amd64.whl", hash = "sha256:e70ca129d2053fb8b728ee7d1af8e553a928d7e301a311094b8a0501adc8763d"}, + {file = "pydantic-1.10.13-py3-none-any.whl", hash = "sha256:b87326822e71bd5f313e7d3bfdc77ac3247035ac10b0c0618bd99dcf95b1e687"}, + {file = "pydantic-1.10.13.tar.gz", hash = "sha256:32c8b48dcd3b2ac4e78b0ba4af3a2c2eb6048cb75202f0ea7b34feb740efc340"}, ] [package.dependencies] -annotated-types = ">=0.4.0" -pydantic-core = "2.10.1" -typing-extensions = ">=4.6.1" - -[package.extras] -email = ["email-validator (>=2.0.0)"] - -[[package]] -name = "pydantic-core" -version = "2.10.1" -description = "" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pydantic_core-2.10.1-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:d64728ee14e667ba27c66314b7d880b8eeb050e58ffc5fec3b7a109f8cddbd63"}, - {file = "pydantic_core-2.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:48525933fea744a3e7464c19bfede85df4aba79ce90c60b94d8b6e1eddd67096"}, - {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef337945bbd76cce390d1b2496ccf9f90b1c1242a3a7bc242ca4a9fc5993427a"}, - {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a1392e0638af203cee360495fd2cfdd6054711f2db5175b6e9c3c461b76f5175"}, - {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0675ba5d22de54d07bccde38997e780044dcfa9a71aac9fd7d4d7a1d2e3e65f7"}, - {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:128552af70a64660f21cb0eb4876cbdadf1a1f9d5de820fed6421fa8de07c893"}, - {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f6e6aed5818c264412ac0598b581a002a9f050cb2637a84979859e70197aa9e"}, - {file = "pydantic_core-2.10.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ecaac27da855b8d73f92123e5f03612b04c5632fd0a476e469dfc47cd37d6b2e"}, - {file = "pydantic_core-2.10.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b3c01c2fb081fced3bbb3da78510693dc7121bb893a1f0f5f4b48013201f362e"}, - {file = "pydantic_core-2.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:92f675fefa977625105708492850bcbc1182bfc3e997f8eecb866d1927c98ae6"}, - {file = "pydantic_core-2.10.1-cp310-none-win32.whl", hash = "sha256:420a692b547736a8d8703c39ea935ab5d8f0d2573f8f123b0a294e49a73f214b"}, - {file = "pydantic_core-2.10.1-cp310-none-win_amd64.whl", hash = "sha256:0880e239827b4b5b3e2ce05e6b766a7414e5f5aedc4523be6b68cfbc7f61c5d0"}, - {file = "pydantic_core-2.10.1-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:073d4a470b195d2b2245d0343569aac7e979d3a0dcce6c7d2af6d8a920ad0bea"}, - {file = "pydantic_core-2.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:600d04a7b342363058b9190d4e929a8e2e715c5682a70cc37d5ded1e0dd370b4"}, - {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39215d809470f4c8d1881758575b2abfb80174a9e8daf8f33b1d4379357e417c"}, - {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eeb3d3d6b399ffe55f9a04e09e635554012f1980696d6b0aca3e6cf42a17a03b"}, - {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7a7902bf75779bc12ccfc508bfb7a4c47063f748ea3de87135d433a4cca7a2f"}, - {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3625578b6010c65964d177626fde80cf60d7f2e297d56b925cb5cdeda6e9925a"}, - {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:caa48fc31fc7243e50188197b5f0c4228956f97b954f76da157aae7f67269ae8"}, - {file = "pydantic_core-2.10.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:07ec6d7d929ae9c68f716195ce15e745b3e8fa122fc67698ac6498d802ed0fa4"}, - {file = "pydantic_core-2.10.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e6f31a17acede6a8cd1ae2d123ce04d8cca74056c9d456075f4f6f85de055607"}, - {file = "pydantic_core-2.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d8f1ebca515a03e5654f88411420fea6380fc841d1bea08effb28184e3d4899f"}, - {file = "pydantic_core-2.10.1-cp311-none-win32.whl", hash = "sha256:6db2eb9654a85ada248afa5a6db5ff1cf0f7b16043a6b070adc4a5be68c716d6"}, - {file = "pydantic_core-2.10.1-cp311-none-win_amd64.whl", hash = "sha256:4a5be350f922430997f240d25f8219f93b0c81e15f7b30b868b2fddfc2d05f27"}, - {file = "pydantic_core-2.10.1-cp311-none-win_arm64.whl", hash = "sha256:5fdb39f67c779b183b0c853cd6b45f7db84b84e0571b3ef1c89cdb1dfc367325"}, - {file = "pydantic_core-2.10.1-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:b1f22a9ab44de5f082216270552aa54259db20189e68fc12484873d926426921"}, - {file = "pydantic_core-2.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8572cadbf4cfa95fb4187775b5ade2eaa93511f07947b38f4cd67cf10783b118"}, - {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:db9a28c063c7c00844ae42a80203eb6d2d6bbb97070cfa00194dff40e6f545ab"}, - {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e2a35baa428181cb2270a15864ec6286822d3576f2ed0f4cd7f0c1708472aff"}, - {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05560ab976012bf40f25d5225a58bfa649bb897b87192a36c6fef1ab132540d7"}, - {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d6495008733c7521a89422d7a68efa0a0122c99a5861f06020ef5b1f51f9ba7c"}, - {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ac492c686defc8e6133e3a2d9eaf5261b3df26b8ae97450c1647286750b901"}, - {file = "pydantic_core-2.10.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8282bab177a9a3081fd3d0a0175a07a1e2bfb7fcbbd949519ea0980f8a07144d"}, - {file = "pydantic_core-2.10.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:aafdb89fdeb5fe165043896817eccd6434aee124d5ee9b354f92cd574ba5e78f"}, - {file = "pydantic_core-2.10.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f6defd966ca3b187ec6c366604e9296f585021d922e666b99c47e78738b5666c"}, - {file = "pydantic_core-2.10.1-cp312-none-win32.whl", hash = "sha256:7c4d1894fe112b0864c1fa75dffa045720a194b227bed12f4be7f6045b25209f"}, - {file = "pydantic_core-2.10.1-cp312-none-win_amd64.whl", hash = "sha256:5994985da903d0b8a08e4935c46ed8daf5be1cf217489e673910951dc533d430"}, - {file = "pydantic_core-2.10.1-cp312-none-win_arm64.whl", hash = "sha256:0d8a8adef23d86d8eceed3e32e9cca8879c7481c183f84ed1a8edc7df073af94"}, - {file = "pydantic_core-2.10.1-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:9badf8d45171d92387410b04639d73811b785b5161ecadabf056ea14d62d4ede"}, - {file = "pydantic_core-2.10.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:ebedb45b9feb7258fac0a268a3f6bec0a2ea4d9558f3d6f813f02ff3a6dc6698"}, - {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cfe1090245c078720d250d19cb05d67e21a9cd7c257698ef139bc41cf6c27b4f"}, - {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e357571bb0efd65fd55f18db0a2fb0ed89d0bb1d41d906b138f088933ae618bb"}, - {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3dcd587b69bbf54fc04ca157c2323b8911033e827fffaecf0cafa5a892a0904"}, - {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c120c9ce3b163b985a3b966bb701114beb1da4b0468b9b236fc754783d85aa3"}, - {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15d6bca84ffc966cc9976b09a18cf9543ed4d4ecbd97e7086f9ce9327ea48891"}, - {file = "pydantic_core-2.10.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5cabb9710f09d5d2e9e2748c3e3e20d991a4c5f96ed8f1132518f54ab2967221"}, - {file = "pydantic_core-2.10.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:82f55187a5bebae7d81d35b1e9aaea5e169d44819789837cdd4720d768c55d15"}, - {file = "pydantic_core-2.10.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1d40f55222b233e98e3921df7811c27567f0e1a4411b93d4c5c0f4ce131bc42f"}, - {file = "pydantic_core-2.10.1-cp37-none-win32.whl", hash = "sha256:14e09ff0b8fe6e46b93d36a878f6e4a3a98ba5303c76bb8e716f4878a3bee92c"}, - {file = "pydantic_core-2.10.1-cp37-none-win_amd64.whl", hash = "sha256:1396e81b83516b9d5c9e26a924fa69164156c148c717131f54f586485ac3c15e"}, - {file = "pydantic_core-2.10.1-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:6835451b57c1b467b95ffb03a38bb75b52fb4dc2762bb1d9dbed8de31ea7d0fc"}, - {file = "pydantic_core-2.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b00bc4619f60c853556b35f83731bd817f989cba3e97dc792bb8c97941b8053a"}, - {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fa467fd300a6f046bdb248d40cd015b21b7576c168a6bb20aa22e595c8ffcdd"}, - {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d99277877daf2efe074eae6338453a4ed54a2d93fb4678ddfe1209a0c93a2468"}, - {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa7db7558607afeccb33c0e4bf1c9a9a835e26599e76af6fe2fcea45904083a6"}, - {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aad7bd686363d1ce4ee930ad39f14e1673248373f4a9d74d2b9554f06199fb58"}, - {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:443fed67d33aa85357464f297e3d26e570267d1af6fef1c21ca50921d2976302"}, - {file = "pydantic_core-2.10.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:042462d8d6ba707fd3ce9649e7bf268633a41018d6a998fb5fbacb7e928a183e"}, - {file = "pydantic_core-2.10.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:ecdbde46235f3d560b18be0cb706c8e8ad1b965e5c13bbba7450c86064e96561"}, - {file = "pydantic_core-2.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ed550ed05540c03f0e69e6d74ad58d026de61b9eaebebbaaf8873e585cbb18de"}, - {file = "pydantic_core-2.10.1-cp38-none-win32.whl", hash = "sha256:8cdbbd92154db2fec4ec973d45c565e767ddc20aa6dbaf50142676484cbff8ee"}, - {file = "pydantic_core-2.10.1-cp38-none-win_amd64.whl", hash = "sha256:9f6f3e2598604956480f6c8aa24a3384dbf6509fe995d97f6ca6103bb8c2534e"}, - {file = "pydantic_core-2.10.1-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:655f8f4c8d6a5963c9a0687793da37b9b681d9ad06f29438a3b2326d4e6b7970"}, - {file = "pydantic_core-2.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e570ffeb2170e116a5b17e83f19911020ac79d19c96f320cbfa1fa96b470185b"}, - {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64322bfa13e44c6c30c518729ef08fda6026b96d5c0be724b3c4ae4da939f875"}, - {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:485a91abe3a07c3a8d1e082ba29254eea3e2bb13cbbd4351ea4e5a21912cc9b0"}, - {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7c2b8eb9fc872e68b46eeaf835e86bccc3a58ba57d0eedc109cbb14177be531"}, - {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a5cb87bdc2e5f620693148b5f8f842d293cae46c5f15a1b1bf7ceeed324a740c"}, - {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25bd966103890ccfa028841a8f30cebcf5875eeac8c4bde4fe221364c92f0c9a"}, - {file = "pydantic_core-2.10.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f323306d0556351735b54acbf82904fe30a27b6a7147153cbe6e19aaaa2aa429"}, - {file = "pydantic_core-2.10.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0c27f38dc4fbf07b358b2bc90edf35e82d1703e22ff2efa4af4ad5de1b3833e7"}, - {file = "pydantic_core-2.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f1365e032a477c1430cfe0cf2856679529a2331426f8081172c4a74186f1d595"}, - {file = "pydantic_core-2.10.1-cp39-none-win32.whl", hash = "sha256:a1c311fd06ab3b10805abb72109f01a134019739bd3286b8ae1bc2fc4e50c07a"}, - {file = "pydantic_core-2.10.1-cp39-none-win_amd64.whl", hash = "sha256:ae8a8843b11dc0b03b57b52793e391f0122e740de3df1474814c700d2622950a"}, - {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d43002441932f9a9ea5d6f9efaa2e21458221a3a4b417a14027a1d530201ef1b"}, - {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fcb83175cc4936a5425dde3356f079ae03c0802bbdf8ff82c035f8a54b333521"}, - {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:962ed72424bf1f72334e2f1e61b68f16c0e596f024ca7ac5daf229f7c26e4208"}, - {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2cf5bb4dd67f20f3bbc1209ef572a259027c49e5ff694fa56bed62959b41e1f9"}, - {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e544246b859f17373bed915182ab841b80849ed9cf23f1f07b73b7c58baee5fb"}, - {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c0877239307b7e69d025b73774e88e86ce82f6ba6adf98f41069d5b0b78bd1bf"}, - {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:53df009d1e1ba40f696f8995683e067e3967101d4bb4ea6f667931b7d4a01357"}, - {file = "pydantic_core-2.10.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a1254357f7e4c82e77c348dabf2d55f1d14d19d91ff025004775e70a6ef40ada"}, - {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:524ff0ca3baea164d6d93a32c58ac79eca9f6cf713586fdc0adb66a8cdeab96a"}, - {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f0ac9fb8608dbc6eaf17956bf623c9119b4db7dbb511650910a82e261e6600f"}, - {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:320f14bd4542a04ab23747ff2c8a778bde727158b606e2661349557f0770711e"}, - {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:63974d168b6233b4ed6a0046296803cb13c56637a7b8106564ab575926572a55"}, - {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:417243bf599ba1f1fef2bb8c543ceb918676954734e2dcb82bf162ae9d7bd514"}, - {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:dda81e5ec82485155a19d9624cfcca9be88a405e2857354e5b089c2a982144b2"}, - {file = "pydantic_core-2.10.1-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:14cfbb00959259e15d684505263d5a21732b31248a5dd4941f73a3be233865b9"}, - {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:631cb7415225954fdcc2a024119101946793e5923f6c4d73a5914d27eb3d3a05"}, - {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:bec7dd208a4182e99c5b6c501ce0b1f49de2802448d4056091f8e630b28e9a52"}, - {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:149b8a07712f45b332faee1a2258d8ef1fb4a36f88c0c17cb687f205c5dc6e7d"}, - {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d966c47f9dd73c2d32a809d2be529112d509321c5310ebf54076812e6ecd884"}, - {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7eb037106f5c6b3b0b864ad226b0b7ab58157124161d48e4b30c4a43fef8bc4b"}, - {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:154ea7c52e32dce13065dbb20a4a6f0cc012b4f667ac90d648d36b12007fa9f7"}, - {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e562617a45b5a9da5be4abe72b971d4f00bf8555eb29bb91ec2ef2be348cd132"}, - {file = "pydantic_core-2.10.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:f23b55eb5464468f9e0e9a9935ce3ed2a870608d5f534025cd5536bca25b1402"}, - {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:e9121b4009339b0f751955baf4543a0bfd6bc3f8188f8056b1a25a2d45099934"}, - {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:0523aeb76e03f753b58be33b26540880bac5aa54422e4462404c432230543f33"}, - {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e0e2959ef5d5b8dc9ef21e1a305a21a36e254e6a34432d00c72a92fdc5ecda5"}, - {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da01bec0a26befab4898ed83b362993c844b9a607a86add78604186297eb047e"}, - {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f2e9072d71c1f6cfc79a36d4484c82823c560e6f5599c43c1ca6b5cdbd54f881"}, - {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f36a3489d9e28fe4b67be9992a23029c3cec0babc3bd9afb39f49844a8c721c5"}, - {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f64f82cc3443149292b32387086d02a6c7fb39b8781563e0ca7b8d7d9cf72bd7"}, - {file = "pydantic_core-2.10.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b4a6db486ac8e99ae696e09efc8b2b9fea67b63c8f88ba7a1a16c24a057a0776"}, - {file = "pydantic_core-2.10.1.tar.gz", hash = "sha256:0f8682dbdd2f67f8e1edddcbffcc29f60a6182b4901c367fc8c1c40d30bb0a82"}, -] - -[package.dependencies] -typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" - -[[package]] -name = "pydantic-extra-types" -version = "2.1.0" -description = "Extra Pydantic types." -optional = false -python-versions = ">=3.7" -files = [ - {file = "pydantic_extra_types-2.1.0-py3-none-any.whl", hash = "sha256:1b8aa83a2986b0bc6a7179834fdb423c5e0bcef6b2b4cd9261bf753ad7dcc483"}, - {file = "pydantic_extra_types-2.1.0.tar.gz", hash = "sha256:d07b869e733d33712b07d6b8cd7b0223077c23ae5a1e23bd0699a00401259ec7"}, -] - -[package.dependencies] -pydantic = ">=2.0.3" - -[package.extras] -all = ["phonenumbers (>=8,<9)", "pycountry (>=22,<23)"] - -[[package]] -name = "pydata-sphinx-theme" -version = "0.13.3" -description = "Bootstrap-based Sphinx theme from the PyData community" -optional = false -python-versions = ">=3.7" -files = [ - {file = "pydata_sphinx_theme-0.13.3-py3-none-any.whl", hash = "sha256:bf41ca6c1c6216e929e28834e404bfc90e080b51915bbe7563b5e6fda70354f0"}, - {file = "pydata_sphinx_theme-0.13.3.tar.gz", hash = "sha256:827f16b065c4fd97e847c11c108bf632b7f2ff53a3bca3272f63f3f3ff782ecc"}, -] - -[package.dependencies] -accessible-pygments = "*" -Babel = "*" -beautifulsoup4 = "*" -docutils = "!=0.17.0" -packaging = "*" -pygments = ">=2.7" -sphinx = ">=4.2" -typing-extensions = "*" +typing-extensions = ">=4.2.0" [package.extras] -dev = ["nox", "pre-commit", "pydata-sphinx-theme[doc,test]", "pyyaml"] -doc = ["ablog (>=0.11.0rc2)", "colorama", "ipyleaflet", "jupyter_sphinx", "linkify-it-py", "matplotlib", "myst-nb", "nbsphinx", "numpy", "numpydoc", "pandas", "plotly", "rich", "sphinx-copybutton", "sphinx-design", "sphinx-favicon (>=1.0.1)", "sphinx-sitemap", "sphinx-togglebutton", "sphinxcontrib-youtube", "sphinxext-rediraffe", "xarray"] -test = ["codecov", "pytest", "pytest-cov", "pytest-regressions"] +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] [[package]] name = "pydocstyle" @@ -2738,57 +2820,6 @@ files = [ [package.extras] plugins = ["importlib-metadata"] -[[package]] -name = "pyside6" -version = "6.5.3" -description = "Python bindings for the Qt cross-platform application and UI framework" -optional = false -python-versions = "<3.12,>=3.7" -files = [ - {file = "PySide6-6.5.3-cp37-abi3-macosx_11_0_universal2.whl", hash = "sha256:be53e7c64710fc4307afd33147e241a06cd97b18fae887ee611d8d4b373dbb04"}, - {file = "PySide6-6.5.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:84f3d3e278e5ea00f1558ac7e1eeb382bba1df7732bdb025ee654e7b4b3cd451"}, - {file = "PySide6-6.5.3-cp37-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:48f4579ca49225cfff8f512178551bdf6aa9031198527f71799bcc061a0f2327"}, - {file = "PySide6-6.5.3-cp37-abi3-win_amd64.whl", hash = "sha256:aaaf5acfaaf9575740df03ee1aa706e2f38d8fcca2255acbbd3a5701f6f2f416"}, -] - -[package.dependencies] -PySide6-Addons = "6.5.3" -PySide6-Essentials = "6.5.3" -shiboken6 = "6.5.3" - -[[package]] -name = "pyside6-addons" -version = "6.5.3" -description = "Python bindings for the Qt cross-platform application and UI framework (Addons)" -optional = false -python-versions = "<3.12,>=3.7" -files = [ - {file = "PySide6_Addons-6.5.3-cp37-abi3-macosx_11_0_universal2.whl", hash = "sha256:047162b158ee929d43c21cdc3ac48e75fec612f2e5492b317190fac98d2de5c6"}, - {file = "PySide6_Addons-6.5.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:e5bc1fa95351182dc2c003e07320d5509218ccc0840d10197d7d452aa5de5d2e"}, - {file = "PySide6_Addons-6.5.3-cp37-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:be0dcfb15d44c2973c3c122058f1df8c3c9d93abd4170534e06dbf986aa30e26"}, - {file = "PySide6_Addons-6.5.3-cp37-abi3-win_amd64.whl", hash = "sha256:dd1d294d48798bd297bde02d3ea02f313a86e38ed3944519228466bdfb537961"}, -] - -[package.dependencies] -PySide6-Essentials = "6.5.3" -shiboken6 = "6.5.3" - -[[package]] -name = "pyside6-essentials" -version = "6.5.3" -description = "Python bindings for the Qt cross-platform application and UI framework (Essentials)" -optional = false -python-versions = "<3.12,>=3.7" -files = [ - {file = "PySide6_Essentials-6.5.3-cp37-abi3-macosx_11_0_universal2.whl", hash = "sha256:4d9c95ded938e557052fc67efe68d57108856df141a1b499497fd7999419e3eb"}, - {file = "PySide6_Essentials-6.5.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:45580138be91f5fdcefb4d28dadb56d3640eb658575af97b49057e10c22a024d"}, - {file = "PySide6_Essentials-6.5.3-cp37-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:8244bc185b0243ba7c4491033e592b247e44a63d69213e9a45ee38e87e0f1f90"}, - {file = "PySide6_Essentials-6.5.3-cp37-abi3-win_amd64.whl", hash = "sha256:f928b98ec349c87f9ccc63a482917779f59fa646893722c53c2fe2a1e4f335e0"}, -] - -[package.dependencies] -shiboken6 = "6.5.3" - [[package]] name = "pytest" version = "7.4.2" @@ -2866,6 +2897,17 @@ files = [ [package.dependencies] six = ">=1.5" +[[package]] +name = "python-json-logger" +version = "2.0.7" +description = "A python library adding a json log formatter" +optional = false +python-versions = ">=3.6" +files = [ + {file = "python-json-logger-2.0.7.tar.gz", hash = "sha256:23e7ec02d34237c5aa1e29a070193a4ea87583bb4e7f8fd06d3de8264c4b2e1c"}, + {file = "python_json_logger-2.0.7-py3-none-any.whl", hash = "sha256:f380b826a991ebbe3de4d897aeec42760035ac760345e57b812938dc8b35e2bd"}, +] + [[package]] name = "pytz" version = "2023.3.post1" @@ -2879,13 +2921,13 @@ files = [ [[package]] name = "pyupgrade" -version = "3.14.0" +version = "3.15.0" description = "A tool to automatically upgrade syntax for newer versions." optional = false python-versions = ">=3.8.1" files = [ - {file = "pyupgrade-3.14.0-py2.py3-none-any.whl", hash = "sha256:221923c5cd6171e4adb78bfd331ce95500112294c36fb61a0947c55c78cb1924"}, - {file = "pyupgrade-3.14.0.tar.gz", hash = "sha256:e5caa64798256e341afcee6fe42be8d75e4f88f20809b25dc6174548dbc3bace"}, + {file = "pyupgrade-3.15.0-py2.py3-none-any.whl", hash = "sha256:8dc8ebfaed43566e2c65994162795017c7db11f531558a74bc8aa077907bc305"}, + {file = "pyupgrade-3.15.0.tar.gz", hash = "sha256:a7fde381060d7c224f55aef7a30fae5ac93bbc428367d27e70a603bc2acd4f00"}, ] [package.dependencies] @@ -2914,6 +2956,21 @@ files = [ {file = "pywin32-306-cp39-cp39-win_amd64.whl", hash = "sha256:39b61c15272833b5c329a2989999dcae836b1eed650252ab1b7bfbe1d59f30f4"}, ] +[[package]] +name = "pywinpty" +version = "2.0.12" +description = "Pseudo terminal support for Windows from Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pywinpty-2.0.12-cp310-none-win_amd64.whl", hash = "sha256:21319cd1d7c8844fb2c970fb3a55a3db5543f112ff9cfcd623746b9c47501575"}, + {file = "pywinpty-2.0.12-cp311-none-win_amd64.whl", hash = "sha256:853985a8f48f4731a716653170cd735da36ffbdc79dcb4c7b7140bce11d8c722"}, + {file = "pywinpty-2.0.12-cp312-none-win_amd64.whl", hash = "sha256:1617b729999eb6713590e17665052b1a6ae0ad76ee31e60b444147c5b6a35dca"}, + {file = "pywinpty-2.0.12-cp38-none-win_amd64.whl", hash = "sha256:189380469ca143d06e19e19ff3fba0fcefe8b4a8cc942140a6b863aed7eebb2d"}, + {file = "pywinpty-2.0.12-cp39-none-win_amd64.whl", hash = "sha256:7520575b6546db23e693cbd865db2764097bd6d4ef5dc18c92555904cd62c3d4"}, + {file = "pywinpty-2.0.12.tar.gz", hash = "sha256:8197de460ae8ebb7f5d1701dfa1b5df45b157bb832e92acba316305e18ca00dd"}, +] + [[package]] name = "pyyaml" version = "6.0.1" @@ -2926,6 +2983,7 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -2933,8 +2991,15 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -2951,6 +3016,7 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -2958,6 +3024,7 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -3068,6 +3135,79 @@ files = [ [package.dependencies] cffi = {version = "*", markers = "implementation_name == \"pypy\""} +[[package]] +name = "qtconsole" +version = "5.4.4" +description = "Jupyter Qt console" +optional = false +python-versions = ">= 3.7" +files = [ + {file = "qtconsole-5.4.4-py3-none-any.whl", hash = "sha256:a3b69b868e041c2c698bdc75b0602f42e130ffb256d6efa48f9aa756c97672aa"}, + {file = "qtconsole-5.4.4.tar.gz", hash = "sha256:b7ffb53d74f23cee29f4cdb55dd6fabc8ec312d94f3c46ba38e1dde458693dfb"}, +] + +[package.dependencies] +ipykernel = ">=4.1" +ipython-genutils = "*" +jupyter-client = ">=4.1" +jupyter-core = "*" +packaging = "*" +pygments = "*" +pyzmq = ">=17.1" +qtpy = ">=2.4.0" +traitlets = "<5.2.1 || >5.2.1,<5.2.2 || >5.2.2" + +[package.extras] +doc = ["Sphinx (>=1.3)"] +test = ["flaky", "pytest", "pytest-qt"] + +[[package]] +name = "qtpy" +version = "2.4.0" +description = "Provides an abstraction layer on top of the various Qt bindings (PyQt5/6 and PySide2/6)." +optional = false +python-versions = ">=3.7" +files = [ + {file = "QtPy-2.4.0-py3-none-any.whl", hash = "sha256:4d4f045a41e09ac9fa57fcb47ef05781aa5af294a0a646acc1b729d14225e741"}, + {file = "QtPy-2.4.0.tar.gz", hash = "sha256:db2d508167aa6106781565c8da5c6f1487debacba33519cedc35fa8997d424d4"}, +] + +[package.dependencies] +packaging = "*" + +[package.extras] +test = ["pytest (>=6,!=7.0.0,!=7.0.1)", "pytest-cov (>=3.0.0)", "pytest-qt"] + +[[package]] +name = "quartodoc" +version = "0.6.3" +description = "Generate API documentation with Quarto." +optional = false +python-versions = ">=3.9" +files = [ + {file = "quartodoc-0.6.3-py3-none-any.whl", hash = "sha256:3d3d69a85d5a89793d06877a6cf3718d8e713d699b4e2a8e794b4baf9c6e842e"}, + {file = "quartodoc-0.6.3.tar.gz", hash = "sha256:c299451e49b8be2ff0330210d8d294e8cbc66526dd9ae7c9eae72c3008a7a16b"}, +] + +[package.dependencies] +click = "*" +griffe = "<=0.32.3" +importlib-metadata = ">=5.1.0" +importlib-resources = ">=5.10.2" +plum-dispatch = [ + {version = "<2.0.0", markers = "python_version < \"3.10\""}, + {version = ">2.0.0", markers = "python_version >= \"3.10\""}, +] +pydantic = "<2.0" +pyyaml = "*" +sphobjinv = ">=2.3.1" +tabulate = ">=0.9.0" +typing-extensions = ">=4.4.0" +watchdog = ">=3.0.0" + +[package.extras] +dev = ["jupyterlab", "jupytext", "pre-commit", "pytest", "syrupy"] + [[package]] name = "referencing" version = "0.30.2" @@ -3117,6 +3257,31 @@ files = [ [package.dependencies] docutils = ">=0.11,<1.0" +[[package]] +name = "rfc3339-validator" +version = "0.1.4" +description = "A pure python RFC3339 validator" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa"}, + {file = "rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b"}, +] + +[package.dependencies] +six = "*" + +[[package]] +name = "rfc3986-validator" +version = "0.1.1" +description = "Pure python rfc3986 validator" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9"}, + {file = "rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055"}, +] + [[package]] name = "rpds-py" version = "0.10.4" @@ -3252,30 +3417,36 @@ python-versions = ">=3.6" files = [ {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462"}, + {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:d92f81886165cb14d7b067ef37e142256f1c6a90a65cd156b063a43da1708cfd"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win32.whl", hash = "sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d"}, {file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win_amd64.whl", hash = "sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248"}, + {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:b5edda50e5e9e15e54a6a8a0070302b00c518a9d32accc2346ad6c984aacd279"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win32.whl", hash = "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7"}, {file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl", hash = "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2"}, + {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:7048c338b6c86627afb27faecf418768acb6331fc24cfa56c93e8c9780f815fa"}, {file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92"}, {file = "ruamel.yaml.clib-0.2.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a5aa27bad2bb83670b71683aae140a1f52b0857a2deff56ad3f6c13a017a26ed"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c58ecd827313af6864893e7af0a3bb85fd529f862b6adbefe14643947cfe2942"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f481f16baec5290e45aebdc2a5168ebc6d35189ae6fea7a58787613a25f6e875"}, + {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:3fcc54cb0c8b811ff66082de1680b4b14cf8a81dce0d4fbf665c2265a81e07a1"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7f67a1ee819dc4562d444bbafb135832b0b909f81cc90f7aa00260968c9ca1b3"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win32.whl", hash = "sha256:75e1ed13e1f9de23c5607fe6bd1aeaae21e523b32d83bb33918245361e9cc51b"}, {file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win_amd64.whl", hash = "sha256:3f215c5daf6a9d7bbed4a0a4f760f3113b10e82ff4c5c44bec20a68c8014f675"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337"}, + {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:665f58bfd29b167039f714c6998178d27ccd83984084c286110ef26b230f259f"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win32.whl", hash = "sha256:955eae71ac26c1ab35924203fda6220f84dce57d6d7884f189743e2abe3a9fbe"}, {file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win_amd64.whl", hash = "sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf"}, + {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:9eb5dee2772b0f704ca2e45b1713e4e5198c18f515b52743576d196348f374d3"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win32.whl", hash = "sha256:84b554931e932c46f94ab306913ad7e11bba988104c5cff26d90d03f68258cd5"}, {file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win_amd64.whl", hash = "sha256:25ac8c08322002b06fa1d49d1646181f0b2c72f5cbc15a85e80b4c30a544bb15"}, @@ -3322,6 +3493,22 @@ setuptools = ">=19.3" github = ["jinja2 (>=3.1.0)", "pygithub (>=1.43.3)"] gitlab = ["python-gitlab (>=1.3.0)"] +[[package]] +name = "send2trash" +version = "1.8.2" +description = "Send file to trash natively under Mac OS X, Windows and Linux" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +files = [ + {file = "Send2Trash-1.8.2-py3-none-any.whl", hash = "sha256:a384719d99c07ce1eefd6905d2decb6f8b7ed054025bb0e618919f945de4f679"}, + {file = "Send2Trash-1.8.2.tar.gz", hash = "sha256:c132d59fa44b9ca2b1699af5c86f57ce9f4c5eb56629d5d55fbb7a35f84e2312"}, +] + +[package.extras] +nativelib = ["pyobjc-framework-Cocoa", "pywin32"] +objc = ["pyobjc-framework-Cocoa"] +win32 = ["pywin32"] + [[package]] name = "setuptools" version = "68.2.2" @@ -3338,19 +3525,6 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] -[[package]] -name = "shiboken6" -version = "6.5.3" -description = "Python/C++ bindings helper module" -optional = false -python-versions = "<3.12,>=3.7" -files = [ - {file = "shiboken6-6.5.3-cp37-abi3-macosx_11_0_universal2.whl", hash = "sha256:faaca92dcbbf26c0ae13f189746c38482e40859e0897b0ed4dee5e04f69fda71"}, - {file = "shiboken6-6.5.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:4cdda98df511243c40f1dd4d9eac25a7191c2583ac673147ecdae0ffa3b9223f"}, - {file = "shiboken6-6.5.3-cp37-abi3-manylinux_2_31_aarch64.whl", hash = "sha256:1bc928ca9f1c1d16ff8fe0585627738a15552bb3329c04fca2c74a443618a6b3"}, - {file = "shiboken6-6.5.3-cp37-abi3-win_amd64.whl", hash = "sha256:a013367e38a12b3f69ba02e79f133df4fba8d21b55a78c6999cdb31c25609524"}, -] - [[package]] name = "six" version = "1.16.0" @@ -3362,6 +3536,17 @@ files = [ {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, ] +[[package]] +name = "sniffio" +version = "1.3.0" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, +] + [[package]] name = "snowballstemmer" version = "2.2.0" @@ -3385,323 +3570,20 @@ files = [ ] [[package]] -name = "sphinx" -version = "7.2.6" -description = "Python documentation generator" -optional = false -python-versions = ">=3.9" -files = [ - {file = "sphinx-7.2.6-py3-none-any.whl", hash = "sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560"}, - {file = "sphinx-7.2.6.tar.gz", hash = "sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5"}, -] - -[package.dependencies] -alabaster = ">=0.7,<0.8" -babel = ">=2.9" -colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -docutils = ">=0.18.1,<0.21" -imagesize = ">=1.3" -importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""} -Jinja2 = ">=3.0" -packaging = ">=21.0" -Pygments = ">=2.14" -requests = ">=2.25.0" -snowballstemmer = ">=2.0" -sphinxcontrib-applehelp = "*" -sphinxcontrib-devhelp = "*" -sphinxcontrib-htmlhelp = ">=2.0.0" -sphinxcontrib-jsmath = "*" -sphinxcontrib-qthelp = "*" -sphinxcontrib-serializinghtml = ">=1.1.9" - -[package.extras] -docs = ["sphinxcontrib-websupport"] -lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-simplify", "isort", "mypy (>=0.990)", "ruff", "sphinx-lint", "types-requests"] -test = ["cython (>=3.0)", "filelock", "html5lib", "pytest (>=4.6)", "setuptools (>=67.0)"] - -[[package]] -name = "sphinx-autobuild" -version = "2021.3.14" -description = "Rebuild Sphinx documentation on changes, with live-reload in the browser." +name = "sphobjinv" +version = "2.3.1" +description = "Sphinx objects.inv Inspection/Manipulation Tool" optional = false python-versions = ">=3.6" files = [ - {file = "sphinx-autobuild-2021.3.14.tar.gz", hash = "sha256:de1ca3b66e271d2b5b5140c35034c89e47f263f2cd5db302c9217065f7443f05"}, - {file = "sphinx_autobuild-2021.3.14-py3-none-any.whl", hash = "sha256:8fe8cbfdb75db04475232f05187c776f46f6e9e04cacf1e49ce81bdac649ccac"}, -] - -[package.dependencies] -colorama = "*" -livereload = "*" -sphinx = "*" - -[package.extras] -test = ["pytest", "pytest-cov"] - -[[package]] -name = "sphinx-autodoc-typehints" -version = "1.24.0" -description = "Type hints (PEP 484) support for the Sphinx autodoc extension" -optional = false -python-versions = ">=3.8" -files = [ - {file = "sphinx_autodoc_typehints-1.24.0-py3-none-any.whl", hash = "sha256:6a73c0c61a9144ce2ed5ef2bed99d615254e5005c1cc32002017d72d69fb70e6"}, - {file = "sphinx_autodoc_typehints-1.24.0.tar.gz", hash = "sha256:94e440066941bb237704bb880785e2d05e8ae5406c88674feefbb938ad0dc6af"}, + {file = "sphobjinv-2.3.1-py3-none-any.whl", hash = "sha256:f3efe68bb0ba6e32cb50df064fe6349b8f94681589b400dea753a2860dd576b5"}, + {file = "sphobjinv-2.3.1.tar.gz", hash = "sha256:1442a47fc93587a0177be95346904e388ef85a8366f90a1835a7c3eeeb122eb7"}, ] [package.dependencies] -sphinx = ">=7.0.1" - -[package.extras] -docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)"] -numpy = ["nptyping (>=2.5)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "sphobjinv (>=2.3.1)", "typing-extensions (>=4.6.3)"] - -[[package]] -name = "sphinx-copybutton" -version = "0.5.2" -description = "Add a copy button to each of your code cells." -optional = false -python-versions = ">=3.7" -files = [ - {file = "sphinx-copybutton-0.5.2.tar.gz", hash = "sha256:4cf17c82fb9646d1bc9ca92ac280813a3b605d8c421225fd9913154103ee1fbd"}, - {file = "sphinx_copybutton-0.5.2-py3-none-any.whl", hash = "sha256:fb543fd386d917746c9a2c50360c7905b605726b9355cd26e9974857afeae06e"}, -] - -[package.dependencies] -sphinx = ">=1.8" - -[package.extras] -code-style = ["pre-commit (==2.12.1)"] -rtd = ["ipython", "myst-nb", "sphinx", "sphinx-book-theme", "sphinx-examples"] - -[[package]] -name = "sphinx-design" -version = "0.5.0" -description = "A sphinx extension for designing beautiful, view size responsive web components." -optional = false -python-versions = ">=3.8" -files = [ - {file = "sphinx_design-0.5.0-py3-none-any.whl", hash = "sha256:1af1267b4cea2eedd6724614f19dcc88fe2e15aff65d06b2f6252cee9c4f4c1e"}, - {file = "sphinx_design-0.5.0.tar.gz", hash = "sha256:e8e513acea6f92d15c6de3b34e954458f245b8e761b45b63950f65373352ab00"}, -] - -[package.dependencies] -sphinx = ">=5,<8" - -[package.extras] -code-style = ["pre-commit (>=3,<4)"] -rtd = ["myst-parser (>=1,<3)"] -testing = ["myst-parser (>=1,<3)", "pytest (>=7.1,<8.0)", "pytest-cov", "pytest-regressions"] -theme-furo = ["furo (>=2023.7.0,<2023.8.0)"] -theme-pydata = ["pydata-sphinx-theme (>=0.13.0,<0.14.0)"] -theme-rtd = ["sphinx-rtd-theme (>=1.0,<2.0)"] -theme-sbt = ["sphinx-book-theme (>=1.0,<2.0)"] - -[[package]] -name = "sphinx-social-cards" -version = "0.3.0" -description = "Generate social media cards for documentation pages with Sphinx" -optional = false -python-versions = ">=3.8" -files = [ - {file = "sphinx-social-cards-0.3.0.tar.gz", hash = "sha256:149b18921f5244768a1200e3554d596fd093a7562df96f0d76ce32e8bb6cc70f"}, - {file = "sphinx_social_cards-0.3.0-py3-none-any.whl", hash = "sha256:322a044b54a8241423c157c4e43a09bba22a02b658ecb24cc146e40034bf8027"}, -] - -[package.dependencies] -pydantic = ">=2.0" -pydantic-extra-types = "*" -PySide6 = "*" -pyyaml = "*" -requests = "*" -sphinx = "*" -typing-extensions = "*" - -[package.extras] -github = ["appdirs"] - -[[package]] -name = "sphinxcontrib-applehelp" -version = "1.0.7" -description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" -optional = false -python-versions = ">=3.9" -files = [ - {file = "sphinxcontrib_applehelp-1.0.7-py3-none-any.whl", hash = "sha256:094c4d56209d1734e7d252f6e0b3ccc090bd52ee56807a5d9315b19c122ab15d"}, - {file = "sphinxcontrib_applehelp-1.0.7.tar.gz", hash = "sha256:39fdc8d762d33b01a7d8f026a3b7d71563ea3b72787d5f00ad8465bd9d6dfbfa"}, -] - -[package.dependencies] -Sphinx = ">=5" - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["pytest"] - -[[package]] -name = "sphinxcontrib-devhelp" -version = "1.0.5" -description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" -optional = false -python-versions = ">=3.9" -files = [ - {file = "sphinxcontrib_devhelp-1.0.5-py3-none-any.whl", hash = "sha256:fe8009aed765188f08fcaadbb3ea0d90ce8ae2d76710b7e29ea7d047177dae2f"}, - {file = "sphinxcontrib_devhelp-1.0.5.tar.gz", hash = "sha256:63b41e0d38207ca40ebbeabcf4d8e51f76c03e78cd61abe118cf4435c73d4212"}, -] - -[package.dependencies] -Sphinx = ">=5" - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["pytest"] - -[[package]] -name = "sphinxcontrib-htmlhelp" -version = "2.0.4" -description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" -optional = false -python-versions = ">=3.9" -files = [ - {file = "sphinxcontrib_htmlhelp-2.0.4-py3-none-any.whl", hash = "sha256:8001661c077a73c29beaf4a79968d0726103c5605e27db92b9ebed8bab1359e9"}, - {file = "sphinxcontrib_htmlhelp-2.0.4.tar.gz", hash = "sha256:6c26a118a05b76000738429b724a0568dbde5b72391a688577da08f11891092a"}, -] - -[package.dependencies] -Sphinx = ">=5" - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["html5lib", "pytest"] - -[[package]] -name = "sphinxcontrib-jsmath" -version = "1.0.1" -description = "A sphinx extension which renders display math in HTML via JavaScript" -optional = false -python-versions = ">=3.5" -files = [ - {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, - {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, -] - -[package.extras] -test = ["flake8", "mypy", "pytest"] - -[[package]] -name = "sphinxcontrib-qthelp" -version = "1.0.6" -description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" -optional = false -python-versions = ">=3.9" -files = [ - {file = "sphinxcontrib_qthelp-1.0.6-py3-none-any.whl", hash = "sha256:bf76886ee7470b934e363da7a954ea2825650013d367728588732c7350f49ea4"}, - {file = "sphinxcontrib_qthelp-1.0.6.tar.gz", hash = "sha256:62b9d1a186ab7f5ee3356d906f648cacb7a6bdb94d201ee7adf26db55092982d"}, -] - -[package.dependencies] -Sphinx = ">=5" - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["pytest"] - -[[package]] -name = "sphinxcontrib-serializinghtml" -version = "1.1.9" -description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" -optional = false -python-versions = ">=3.9" -files = [ - {file = "sphinxcontrib_serializinghtml-1.1.9-py3-none-any.whl", hash = "sha256:9b36e503703ff04f20e9675771df105e58aa029cfcbc23b8ed716019b7416ae1"}, - {file = "sphinxcontrib_serializinghtml-1.1.9.tar.gz", hash = "sha256:0c64ff898339e1fac29abd2bf5f11078f3ec413cfe9c046d3120d7ca65530b54"}, -] - -[package.dependencies] -Sphinx = ">=5" - -[package.extras] -lint = ["docutils-stubs", "flake8", "mypy"] -test = ["pytest"] - -[[package]] -name = "sqlalchemy" -version = "2.0.21" -description = "Database Abstraction Library" -optional = false -python-versions = ">=3.7" -files = [ - {file = "SQLAlchemy-2.0.21-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1e7dc99b23e33c71d720c4ae37ebb095bebebbd31a24b7d99dfc4753d2803ede"}, - {file = "SQLAlchemy-2.0.21-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7f0c4ee579acfe6c994637527c386d1c22eb60bc1c1d36d940d8477e482095d4"}, - {file = "SQLAlchemy-2.0.21-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f7d57a7e140efe69ce2d7b057c3f9a595f98d0bbdfc23fd055efdfbaa46e3a5"}, - {file = "SQLAlchemy-2.0.21-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ca38746eac23dd7c20bec9278d2058c7ad662b2f1576e4c3dbfcd7c00cc48fa"}, - {file = "SQLAlchemy-2.0.21-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3cf229704074bce31f7f47d12883afee3b0a02bb233a0ba45ddbfe542939cca4"}, - {file = "SQLAlchemy-2.0.21-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fb87f763b5d04a82ae84ccff25554ffd903baafba6698e18ebaf32561f2fe4aa"}, - {file = "SQLAlchemy-2.0.21-cp310-cp310-win32.whl", hash = "sha256:89e274604abb1a7fd5c14867a412c9d49c08ccf6ce3e1e04fffc068b5b6499d4"}, - {file = "SQLAlchemy-2.0.21-cp310-cp310-win_amd64.whl", hash = "sha256:e36339a68126ffb708dc6d1948161cea2a9e85d7d7b0c54f6999853d70d44430"}, - {file = "SQLAlchemy-2.0.21-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bf8eebccc66829010f06fbd2b80095d7872991bfe8415098b9fe47deaaa58063"}, - {file = "SQLAlchemy-2.0.21-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b977bfce15afa53d9cf6a632482d7968477625f030d86a109f7bdfe8ce3c064a"}, - {file = "SQLAlchemy-2.0.21-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ff3dc2f60dbf82c9e599c2915db1526d65415be323464f84de8db3e361ba5b9"}, - {file = "SQLAlchemy-2.0.21-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44ac5c89b6896f4740e7091f4a0ff2e62881da80c239dd9408f84f75a293dae9"}, - {file = "SQLAlchemy-2.0.21-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:87bf91ebf15258c4701d71dcdd9c4ba39521fb6a37379ea68088ce8cd869b446"}, - {file = "SQLAlchemy-2.0.21-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b69f1f754d92eb1cc6b50938359dead36b96a1dcf11a8670bff65fd9b21a4b09"}, - {file = "SQLAlchemy-2.0.21-cp311-cp311-win32.whl", hash = "sha256:af520a730d523eab77d754f5cf44cc7dd7ad2d54907adeb3233177eeb22f271b"}, - {file = "SQLAlchemy-2.0.21-cp311-cp311-win_amd64.whl", hash = "sha256:141675dae56522126986fa4ca713739d00ed3a6f08f3c2eb92c39c6dfec463ce"}, - {file = "SQLAlchemy-2.0.21-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7614f1eab4336df7dd6bee05bc974f2b02c38d3d0c78060c5faa4cd1ca2af3b8"}, - {file = "SQLAlchemy-2.0.21-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d59cb9e20d79686aa473e0302e4a82882d7118744d30bb1dfb62d3c47141b3ec"}, - {file = "SQLAlchemy-2.0.21-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a95aa0672e3065d43c8aa80080cdd5cc40fe92dc873749e6c1cf23914c4b83af"}, - {file = "SQLAlchemy-2.0.21-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8c323813963b2503e54d0944813cd479c10c636e3ee223bcbd7bd478bf53c178"}, - {file = "SQLAlchemy-2.0.21-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:419b1276b55925b5ac9b4c7044e999f1787c69761a3c9756dec6e5c225ceca01"}, - {file = "SQLAlchemy-2.0.21-cp37-cp37m-win32.whl", hash = "sha256:4615623a490e46be85fbaa6335f35cf80e61df0783240afe7d4f544778c315a9"}, - {file = "SQLAlchemy-2.0.21-cp37-cp37m-win_amd64.whl", hash = "sha256:cca720d05389ab1a5877ff05af96551e58ba65e8dc65582d849ac83ddde3e231"}, - {file = "SQLAlchemy-2.0.21-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b4eae01faee9f2b17f08885e3f047153ae0416648f8e8c8bd9bc677c5ce64be9"}, - {file = "SQLAlchemy-2.0.21-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3eb7c03fe1cd3255811cd4e74db1ab8dca22074d50cd8937edf4ef62d758cdf4"}, - {file = "SQLAlchemy-2.0.21-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2d494b6a2a2d05fb99f01b84cc9af9f5f93bf3e1e5dbdafe4bed0c2823584c1"}, - {file = "SQLAlchemy-2.0.21-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b19ae41ef26c01a987e49e37c77b9ad060c59f94d3b3efdfdbf4f3daaca7b5fe"}, - {file = "SQLAlchemy-2.0.21-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:fc6b15465fabccc94bf7e38777d665b6a4f95efd1725049d6184b3a39fd54880"}, - {file = "SQLAlchemy-2.0.21-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:014794b60d2021cc8ae0f91d4d0331fe92691ae5467a00841f7130fe877b678e"}, - {file = "SQLAlchemy-2.0.21-cp38-cp38-win32.whl", hash = "sha256:0268256a34806e5d1c8f7ee93277d7ea8cc8ae391f487213139018b6805aeaf6"}, - {file = "SQLAlchemy-2.0.21-cp38-cp38-win_amd64.whl", hash = "sha256:73c079e21d10ff2be54a4699f55865d4b275fd6c8bd5d90c5b1ef78ae0197301"}, - {file = "SQLAlchemy-2.0.21-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:785e2f2c1cb50d0a44e2cdeea5fd36b5bf2d79c481c10f3a88a8be4cfa2c4615"}, - {file = "SQLAlchemy-2.0.21-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c111cd40910ffcb615b33605fc8f8e22146aeb7933d06569ac90f219818345ef"}, - {file = "SQLAlchemy-2.0.21-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9cba4e7369de663611ce7460a34be48e999e0bbb1feb9130070f0685e9a6b66"}, - {file = "SQLAlchemy-2.0.21-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50a69067af86ec7f11a8e50ba85544657b1477aabf64fa447fd3736b5a0a4f67"}, - {file = "SQLAlchemy-2.0.21-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ccb99c3138c9bde118b51a289d90096a3791658da9aea1754667302ed6564f6e"}, - {file = "SQLAlchemy-2.0.21-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:513fd5b6513d37e985eb5b7ed89da5fd9e72354e3523980ef00d439bc549c9e9"}, - {file = "SQLAlchemy-2.0.21-cp39-cp39-win32.whl", hash = "sha256:f9fefd6298433b6e9188252f3bff53b9ff0443c8fde27298b8a2b19f6617eeb9"}, - {file = "SQLAlchemy-2.0.21-cp39-cp39-win_amd64.whl", hash = "sha256:2e617727fe4091cedb3e4409b39368f424934c7faa78171749f704b49b4bb4ce"}, - {file = "SQLAlchemy-2.0.21-py3-none-any.whl", hash = "sha256:ea7da25ee458d8f404b93eb073116156fd7d8c2a776d8311534851f28277b4ce"}, - {file = "SQLAlchemy-2.0.21.tar.gz", hash = "sha256:05b971ab1ac2994a14c56b35eaaa91f86ba080e9ad481b20d99d77f381bb6258"}, -] - -[package.dependencies] -greenlet = {version = "!=0.4.17", markers = "platform_machine == \"win32\" or platform_machine == \"WIN32\" or platform_machine == \"AMD64\" or platform_machine == \"amd64\" or platform_machine == \"x86_64\" or platform_machine == \"ppc64le\" or platform_machine == \"aarch64\""} -typing-extensions = ">=4.2.0" - -[package.extras] -aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"] -aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing-extensions (!=3.10.0.1)"] -asyncio = ["greenlet (!=0.4.17)"] -asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] -mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"] -mssql = ["pyodbc"] -mssql-pymssql = ["pymssql"] -mssql-pyodbc = ["pyodbc"] -mypy = ["mypy (>=0.910)"] -mysql = ["mysqlclient (>=1.4.0)"] -mysql-connector = ["mysql-connector-python"] -oracle = ["cx-oracle (>=7)"] -oracle-oracledb = ["oracledb (>=1.0.1)"] -postgresql = ["psycopg2 (>=2.7)"] -postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] -postgresql-pg8000 = ["pg8000 (>=1.29.1)"] -postgresql-psycopg = ["psycopg (>=3.0.7)"] -postgresql-psycopg2binary = ["psycopg2-binary"] -postgresql-psycopg2cffi = ["psycopg2cffi"] -postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] -pymysql = ["pymysql"] -sqlcipher = ["sqlcipher3-binary"] +attrs = ">=19.2" +certifi = "*" +jsonschema = ">=3.0" [[package]] name = "stack-data" @@ -3750,6 +3632,44 @@ files = [ [package.extras] doc = ["reno", "sphinx", "tornado (>=4.5)"] +[[package]] +name = "terminado" +version = "0.17.1" +description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." +optional = false +python-versions = ">=3.7" +files = [ + {file = "terminado-0.17.1-py3-none-any.whl", hash = "sha256:8650d44334eba354dd591129ca3124a6ba42c3d5b70df5051b6921d506fdaeae"}, + {file = "terminado-0.17.1.tar.gz", hash = "sha256:6ccbbcd3a4f8a25a5ec04991f39a0b8db52dfcd487ea0e578d977e6752380333"}, +] + +[package.dependencies] +ptyprocess = {version = "*", markers = "os_name != \"nt\""} +pywinpty = {version = ">=1.1.0", markers = "os_name == \"nt\""} +tornado = ">=6.1.0" + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] +test = ["pre-commit", "pytest (>=7.0)", "pytest-timeout"] + +[[package]] +name = "tinycss2" +version = "1.2.1" +description = "A tiny CSS parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tinycss2-1.2.1-py3-none-any.whl", hash = "sha256:2b80a96d41e7c3914b8cda8bc7f705a4d9c49275616e886103dd839dfc847847"}, + {file = "tinycss2-1.2.1.tar.gz", hash = "sha256:8cff3a8f066c2ec677c06dbc7b45619804a6938478d9d73c284b29d14ecb0627"}, +] + +[package.dependencies] +webencodings = ">=0.4" + +[package.extras] +doc = ["sphinx", "sphinx_rtd_theme"] +test = ["flake8", "isort", "pytest"] + [[package]] name = "tokenize-rt" version = "5.2.0" @@ -3848,6 +3768,17 @@ files = [ {file = "types_awscrt-0.19.2.tar.gz", hash = "sha256:d8c379420ba75b1e43687d12b0b772a5bb17f352859a2bef6aa8f0abde123f55"}, ] +[[package]] +name = "types-python-dateutil" +version = "2.8.19.14" +description = "Typing stubs for python-dateutil" +optional = false +python-versions = "*" +files = [ + {file = "types-python-dateutil-2.8.19.14.tar.gz", hash = "sha256:1f4f10ac98bb8b16ade9dbee3518d9ace017821d94b057a425b069f834737f4b"}, + {file = "types_python_dateutil-2.8.19.14-py3-none-any.whl", hash = "sha256:f977b8de27787639986b4e28963263fd0e5158942b3ecef91b9335c130cb1ce9"}, +] + [[package]] name = "types-pytz" version = "2023.3.1.1" @@ -3893,18 +3824,18 @@ files = [ ] [[package]] -name = "uc-micro-py" -version = "1.0.2" -description = "Micro subset of unicode data files for linkify-it-py projects." +name = "uri-template" +version = "1.3.0" +description = "RFC 6570 URI Template Processor" optional = false python-versions = ">=3.7" files = [ - {file = "uc-micro-py-1.0.2.tar.gz", hash = "sha256:30ae2ac9c49f39ac6dce743bd187fcd2b574b16ca095fa74cd9396795c954c54"}, - {file = "uc_micro_py-1.0.2-py3-none-any.whl", hash = "sha256:8c9110c309db9d9e87302e2f4ad2c3152770930d88ab385cd544e7a7e75f3de0"}, + {file = "uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7"}, + {file = "uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363"}, ] [package.extras] -test = ["coverage", "pytest", "pytest-cov"] +dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake8-commas", "flake8-comprehensions", "flake8-continuation", "flake8-datetimez", "flake8-docstrings", "flake8-import-order", "flake8-literal", "flake8-modern-annotations", "flake8-noqa", "flake8-pyproject", "flake8-requirements", "flake8-typechecking-import", "flake8-use-fstring", "mypy", "pep8-naming", "types-PyYAML"] [[package]] name = "urllib3" @@ -3922,6 +3853,23 @@ brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotl secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +[[package]] +name = "urllib3" +version = "2.0.6" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.7" +files = [ + {file = "urllib3-2.0.6-py3-none-any.whl", hash = "sha256:7a7c7003b000adf9e7ca2a377c9688bbc54ed41b985789ed576570342a375cd2"}, + {file = "urllib3-2.0.6.tar.gz", hash = "sha256:b19e1a85d206b56d7df1d5e683df4a7725252a964e3993648dd0fb5a1c157564"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + [[package]] name = "virtualenv" version = "20.24.5" @@ -3992,15 +3940,41 @@ files = [ {file = "wcwidth-0.2.8.tar.gz", hash = "sha256:8705c569999ffbb4f6a87c6d1b80f324bd6db952f5eb0b95bc07517f4c1813d4"}, ] +[[package]] +name = "webcolors" +version = "1.13" +description = "A library for working with the color formats defined by HTML and CSS." +optional = false +python-versions = ">=3.7" +files = [ + {file = "webcolors-1.13-py3-none-any.whl", hash = "sha256:29bc7e8752c0a1bd4a1f03c14d6e6a72e93d82193738fa860cbff59d0fcc11bf"}, + {file = "webcolors-1.13.tar.gz", hash = "sha256:c225b674c83fa923be93d235330ce0300373d02885cef23238813b0d5668304a"}, +] + +[package.extras] +docs = ["furo", "sphinx", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-notfound-page", "sphinxext-opengraph"] +tests = ["pytest", "pytest-cov"] + +[[package]] +name = "webencodings" +version = "0.5.1" +description = "Character encoding aliases for legacy web content" +optional = false +python-versions = "*" +files = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] + [[package]] name = "websocket-client" -version = "1.6.3" +version = "1.6.4" description = "WebSocket client for Python with low level API options" optional = false python-versions = ">=3.8" files = [ - {file = "websocket-client-1.6.3.tar.gz", hash = "sha256:3aad25d31284266bcfcfd1fd8a743f63282305a364b8d0948a43bd606acc652f"}, - {file = "websocket_client-1.6.3-py3-none-any.whl", hash = "sha256:6cfc30d051ebabb73a5fa246efdcc14c8fbebbd0330f8984ac3bb6d9edd2ad03"}, + {file = "websocket-client-1.6.4.tar.gz", hash = "sha256:b3324019b3c28572086c4a319f91d1dcd44e6e11cd340232978c684a7650d0df"}, + {file = "websocket_client-1.6.4-py3-none-any.whl", hash = "sha256:084072e0a7f5f347ef2ac3d8698a5e0b4ffbfcab607628cadabc650fc9a83a24"}, ] [package.extras] @@ -4008,6 +3982,17 @@ docs = ["Sphinx (>=6.0)", "sphinx-rtd-theme (>=1.1.0)"] optional = ["python-socks", "wsaccel"] test = ["websockets"] +[[package]] +name = "widgetsnbextension" +version = "4.0.9" +description = "Jupyter interactive widgets for Jupyter Notebook" +optional = false +python-versions = ">=3.7" +files = [ + {file = "widgetsnbextension-4.0.9-py3-none-any.whl", hash = "sha256:91452ca8445beb805792f206e560c1769284267a30ceb1cec9f5bcc887d15175"}, + {file = "widgetsnbextension-4.0.9.tar.gz", hash = "sha256:3c1f5e46dc1166dfd40a42d685e6a51396fd34ff878742a3e47c6f0cc4a2a385"}, +] + [[package]] name = "xdoctest" version = "1.1.1" @@ -4059,4 +4044,4 @@ plot = ["plotly"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<4.0" -content-hash = "f7d10b778061e5e832f9ffdad4031a07e8cc62c517c61af62e47a43951cc1d55" +content-hash = "1747c1b5ec5175ae3bee9752b29402ee18147d0c246ef1b3450e98ebadd64132" diff --git a/python/pyproject.toml b/python/pyproject.toml index 93b6ceebf..2349daf5c 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -3,9 +3,7 @@ name = "kaskada" version = "0.6.0-a.2" description = "Kaskada query builder and local execution engine." requires-python = ">=3.9,<4.0" -classifiers = [ - "Development Status :: 3 - Alpha", -] +classifiers = ["Development Status :: 3 - Alpha"] # We need to list dependencies here for maturin to put them in the package. # They should match what poetry believes we need. dependencies = [ @@ -15,12 +13,8 @@ dependencies = [ ] [project.optional-dependencies] -plot = [ - "plotly >= 5.0.0, < 6.0.0", -] -explain = [ - "graphviz >= 0.20.1, < 1.0.0", -] +plot = ["plotly >= 5.0.0, < 6.0.0"] +explain = ["graphviz >= 0.20.1, < 1.0.0"] [tool.poetry] name = "kaskada" @@ -37,7 +31,7 @@ python = ">=3.9,<4.0" pyarrow = "^12.0.1" typing-extensions = "^4.7.1" graphviz = { version = "^0.20.1", optional = true } -plotly = {version = "^5.16.1", optional = true} +plotly = { version = "^5.16.1", optional = true } [tool.poetry.extras] plot = ["plotly"] @@ -79,28 +73,18 @@ mypy = ">=0.930" pandas-stubs = "^2.0.2" typeguard = ">=2.13.3" graphviz = { version = "^0.20.1" } -boto3-stubs = {extras = ["s3"], version = "^1.28.62"} +boto3-stubs = { extras = ["s3"], version = "^1.28.62" } [tool.poetry.group.docs] # Dependencies for documentation. optional = true [tool.poetry.group.docs.dependencies] -sphinx = ">=6.0.0" -sphinx-autobuild = ">=2021.3.14" -sphinx-autodoc-typehints = ">=1.23.0" -sphinx-copybutton = "^0.5.2" -sphinx-design = "^0.5.0" -myst-parser = {version = ">=0.16.1"} -# Use myst-nb from git since the currently released version (0.17.2) pins -# Sphinx to < 6. Once a new release occurs we can upgrade to `0.18.0` or newer. -# https://github.com/executablebooks/MyST-NB/issues/530 -myst-nb = { git = "https://github.com/executablebooks/MyST-NB.git", rev = "59854c270deb76f297f228477be5d5088babd143" } -plotly = {version = "^5.16.1"} -linkify-it-py = "^2.0.2" -pydata-sphinx-theme = "^0.13.3" -ablog = "^0.11.4.post1" -sphinx-social-cards = { version = "^0.3.0", python = ">=3.9,<3.12" } +plotly = { version = "^5.16.1" } +quartodoc = "~0.6.3" +nbformat = "^5.9.2" +nbclient = "^0.8.0" +jupyter = "^1.0.0" [tool.poetry.group.test] # Dependencies for testing @@ -108,11 +92,11 @@ optional = true [tool.poetry.group.test.dependencies] boto3 = "^1.28.54" -coverage = { extras = ["toml"], version = ">=6.2"} +coverage = { extras = ["toml"], version = ">=6.2" } pytest = ">=6.2.5" pytest-asyncio = "^0.21.1" pytest-docker-fixtures = "^1.3.17" -xdoctest = {extras = ["colors"], version = ">=0.15.10"} +xdoctest = { extras = ["colors"], version = ">=0.15.10" } [tool.poetry.group.release] # Dependencies for performing the @@ -163,7 +147,5 @@ show_error_context = true # pyproject.toml [tool.pytest.ini_options] -testpaths = [ - "pytests", -] +testpaths = ["pytests"] asyncio_mode = "auto" From 8200eea902f171b40011d6694a8457b1a25dbf4e Mon Sep 17 00:00:00 2001 From: Eric Pinzur <2641606+epinzur@users.noreply.github.com> Date: Wed, 11 Oct 2023 00:22:04 +0200 Subject: [PATCH 13/14] Add doc linting to quarto docs (#805) --- .github/workflows/ci_python.yml | 9 ++ python/docs/_scripts/builder.py | 21 ++--- python/docs/_scripts/lint_reference.py | 19 ++++ python/docs/_scripts/linter.py | 120 +++++++++++++++++++++++++ python/docs/_scripts/renderer.py | 80 ++++++++++------- python/noxfile.py | 7 ++ python/pysrc/kaskada/_timestream.py | 4 +- 7 files changed, 212 insertions(+), 48 deletions(-) create mode 100644 python/docs/_scripts/lint_reference.py create mode 100644 python/docs/_scripts/linter.py diff --git a/.github/workflows/ci_python.yml b/.github/workflows/ci_python.yml index d99fb7e4c..339ad6df4 100644 --- a/.github/workflows/ci_python.yml +++ b/.github/workflows/ci_python.yml @@ -227,6 +227,15 @@ jobs: echo "::endgroup::" deactivate done + - name: Lint reference docs + run: | + poetry env use 3.11 + source $(poetry env info --path)/bin/activate + poetry install --with=docs + pip install ${WHEEL} --force-reinstall + cd docs + python _scripts/lint_reference.py + deactivate - name: Set up Quarto uses: quarto-dev/quarto-actions/setup@v2 - name: Build docs diff --git a/python/docs/_scripts/builder.py b/python/docs/_scripts/builder.py index 57e03b08b..b4453187c 100644 --- a/python/docs/_scripts/builder.py +++ b/python/docs/_scripts/builder.py @@ -3,7 +3,7 @@ import logging import sys from pathlib import Path -from typing import Any, Union +from typing import Any from pydantic import ValidationError from quartodoc import blueprint, collect, layout @@ -12,6 +12,7 @@ from renderer import Renderer from summarizer import Summarizer + # `preview()` can be used to help debug doc generation. # use it on a `section` or `page` element to see a visual # representation of the element contents. Use the `max_depth` @@ -137,12 +138,6 @@ def build(self): inv = create_inventory(self.package, "0.0.9999", self.items) convert_inventory(inv, self.out_inventory) - def get_package(self, item: Union[layout.Section, layout.Page]) -> str: - if item.package and f"{item.package}" != "": - return item.package - else: - return self.package - def write_pages(self): root = layout.Section( title=self.title, @@ -181,16 +176,14 @@ def write_pages(self): _log.info(f"Rendering {page.path}") # preview(page, max_depth=4) page_text = self.renderer.render(page) - page_path = location / \ - (page.path + self.out_page_suffix) + page_path = location / (page.path + self.out_page_suffix) self.write_page_if_not_exists(page_path, page_text) if page.path in self.page_map: del self.page_map[page.path] self.update_page_items(page, location, is_flat) else: - raise NotImplementedError( - f"Unsupported section item: {type(page)}") + raise NotImplementedError(f"Unsupported section item: {type(page)}") if len(self.page_map.keys()) > 0: _log.warning(f"Extra pages: {self.page_map.keys()}") @@ -214,8 +207,7 @@ def update_page_items(self, page: layout.Page, location: Path, is_flat: bool): ) self.update_items(doc, page_path) else: - raise NotImplementedError( - f"Unsupported page item: {type(doc)}") + raise NotImplementedError(f"Unsupported page item: {type(doc)}") def update_items(self, doc: layout.Doc, page_path: str): name = doc.obj.path @@ -293,8 +285,7 @@ def from_quarto_config(cls, quarto_cfg: "str | dict"): cfg = quarto_cfg.get("quartodoc") if cfg is None: - raise KeyError( - "No `quartodoc:` section found in your _quarto.yml.") + raise KeyError("No `quartodoc:` section found in your _quarto.yml.") return Builder( **{k: v for k, v in cfg.items()}, diff --git a/python/docs/_scripts/lint_reference.py b/python/docs/_scripts/lint_reference.py new file mode 100644 index 000000000..09f6b390d --- /dev/null +++ b/python/docs/_scripts/lint_reference.py @@ -0,0 +1,19 @@ +import logging +import sys + +from linter import Linter + + +if __name__ == "__main__": + root = logging.getLogger("quartodoc") + root.setLevel(logging.WARNING) + + handler = logging.StreamHandler(sys.stdout) + handler.setLevel(logging.INFO) + formatter = logging.Formatter( + "%(asctime)s - %(name)s - %(levelname)s - %(message)s" + ) + handler.setFormatter(formatter) + root.addHandler(handler) + + Linter.from_quarto_config("_reference.yml").lint() diff --git a/python/docs/_scripts/linter.py b/python/docs/_scripts/linter.py new file mode 100644 index 000000000..3d622f929 --- /dev/null +++ b/python/docs/_scripts/linter.py @@ -0,0 +1,120 @@ +from __future__ import annotations + +import logging +import sys +from pathlib import Path +from typing import Any + +from pydantic import ValidationError +from quartodoc import blueprint, collect, layout +from quartodoc.validation import fmt + + +_log = logging.getLogger("quartodoc") + + +def load_layout(sections: dict, package: str, options=None): + try: + return layout.Layout(sections=sections, package=package, options=options) + except ValidationError as e: + msg = "Configuration error for YAML:\n - " + errors = [fmt(err) for err in e.errors() if fmt(err)] + first_error = errors[ + 0 + ] # we only want to show one error at a time b/c it is confusing otherwise + msg += first_error + raise ValueError(msg) from None + + +class Linter: + """Base class for linting API docs. + + Parameters + ---------- + package: str + The name of the package. + sections: ConfigSection + A list of sections, with items to document. + options: + Default options to set for all pieces of content (e.g. include_attributes). + source_dir: + A directory where source files to be documented live. This is only necessary + if you are not documenting a package, but collection of scripts. Use a "." + to refer to the current directory. + parser: + Docstring parser to use. This correspond to different docstring styles, + and can be one of "google", "sphinx", and "numpy". Defaults to "numpy". + + """ + + package: str + sections: list[Any] + options: dict | None + source_dir: str | None + parser: str + + def __init__( + self, + package: str, + sections: list[Any] = tuple(), + options: dict | None = None, + source_dir: str | None = None, + parser="google", + ): + self.package = package + self.sections = sections + self.options = options + self.parser = parser + + if source_dir: + self.source_dir = str(Path(source_dir).absolute()) + sys.path.append(self.source_dir) + + def get_items(self, use_sections: bool): + sections = self.sections if use_sections else [] + + layout = load_layout( + sections=sections, package=self.package, options=self.options + ) + + _, items = collect(blueprint(layout, parser=self.parser), base_dir="") + + return [item.name for item in items] + + def lint(self): + """Lints the config and lets you know about any missing items""" + + ref_items = self.get_items(True) + pkg_items = self.get_items(False) + + issue_count = 0 + for pkg_item in pkg_items: + if pkg_item not in ref_items: + _log.warning(f"Missing item: {pkg_item}") + issue_count += 1 + + if issue_count > 0: + _log.error("Encountered un-documented items. Please fix.") + sys.exit(1) + + @classmethod + def from_quarto_config(cls, quarto_cfg: "str | dict"): + """Construct a Builder from a configuration object (or yaml file).""" + + # TODO: validation / config model loading + if isinstance(quarto_cfg, str): + import yaml + + quarto_cfg = yaml.safe_load(open(quarto_cfg)) + + cfg = quarto_cfg.get("quartodoc") + if cfg is None: + raise KeyError("No `quartodoc:` section found in your _quarto.yml.") + + return Linter( + **{ + k: v + for k, v in cfg.items() + if k in ["package", "sections", "options", "parser"] + }, + ) diff --git a/python/docs/_scripts/renderer.py b/python/docs/_scripts/renderer.py index 704e5cc37..84cb58e58 100644 --- a/python/docs/_scripts/renderer.py +++ b/python/docs/_scripts/renderer.py @@ -54,10 +54,10 @@ class Renderer: summarizer = Summarizer() - def _get_display_name(self, el: "dc.Alias | dc.Object"): + def _get_display_name(self, el: "dc.Alias | dc.Object") -> str: parts = el.path.split(".")[1:] name = parts.pop() - prefix = ".".join(parts) + prefix = ".".join(parts) if len(parts) > 0 else "kaskada" display_name = f"**{prefix}.**[**{name}**]{{.red}}" if isinstance(el, dc.Object): @@ -90,7 +90,9 @@ def _render_definition_list( if title_class: rows.insert(0, f":::{{.{title_class}}}") rows.append(":::") - return "\n" + "\n".join(rows) + text = "\n\n".join(rows) + # fix extra indenting for nested definition lists + return text.replace("\n\n \n\n", "\n\n") def _render_header(self, title: str, order: Optional[int] = None) -> str: text = ["---"] @@ -100,7 +102,7 @@ def _render_header(self, title: str, order: Optional[int] = None) -> str: text.append("---") return "\n".join(text) - def _render_table(self, rows, headers): + def _render_table(self, rows, headers) -> str: table = tabulate(rows, headers=headers, tablefmt="github") return table @@ -109,6 +111,10 @@ def _render_table(self, rows, headers): @dispatch def render_annotation(self, el: str) -> str: # noqa: F811 + # hack to get Timestream in the correct format for the kaskada.Arg + # alias docs + if el == "'Timestream'": + return "[Timestream](`kaskada.Timestream`)" return sanitize(el) @dispatch @@ -126,14 +132,21 @@ def render_annotation(self, el: expr.Expression) -> str: # noqa: F811 text = "".join(map(self.render_annotation, el)) return text.lstrip(".") + @dispatch + def render_annotation(self, el: dc.Attribute) -> str: # noqa: F811 + text = "".join(map(self.render_annotation, el.value)) + return text.lstrip(".") + # signature method -------------------------------------------------------- @dispatch - def signature(self, el: layout.Doc): # noqa: F811 + def signature(self, el: layout.Doc) -> str: # noqa: F811 return self.signature(el.obj) @dispatch - def signature(self, el: dc.Alias, source: Optional[dc.Alias] = None): # noqa: F811 + def signature( # noqa: F811 + self, el: dc.Alias, source: Optional[dc.Alias] = None + ) -> str: """Return a string representation of an object's signature.""" return self.signature(el.target, el) @@ -155,20 +168,20 @@ def signature( # noqa: F811 @dispatch def signature( # noqa: F811 self, el: Union[dc.Module, dc.Attribute], source: Optional[dc.Alias] = None - ): + ) -> str: name = self._get_display_name(source or el) return f"`{name}`" # render method ----------------------------------------------------------- @dispatch - def render(self, el): # noqa: F811 + def render(self, el) -> str: # noqa: F811 """Return a string representation of an object, or layout element.""" raise NotImplementedError(f"Unsupported type: {type(el)}") @dispatch - def render(self, el: str): # noqa: F811 + def render(self, el: str) -> str: # noqa: F811 return el # render layouts ========================================================== @@ -193,7 +206,7 @@ def render( # noqa: F811 return text @dispatch - def render(self, el: layout.Page, is_flat: bool = False): # noqa: F811 + def render(self, el: layout.Page, is_flat: bool = False) -> str: # noqa: F811 rows = [] if el.summary: if el.summary.name: @@ -210,7 +223,7 @@ def render(self, el: layout.Page, is_flat: bool = False): # noqa: F811 return "\n\n".join(rows) @dispatch - def render(self, el: layout.Doc): # noqa: F811 + def render(self, el: layout.Doc) -> str: # noqa: F811 raise NotImplementedError(f"Unsupported Doc type: {type(el)}") @dispatch @@ -236,21 +249,21 @@ def render( # noqa: F811 # add classes for raw_class in el.members: if raw_class.obj.is_class and isinstance(raw_class, layout.Doc): - body_rows.extend(self.render( - raw_class, is_flat=True).split("\n")) + body_rows.extend(self.render(raw_class, is_flat=True).split("\n")) # add methods for raw_method in el.members: if raw_method.obj.is_function and isinstance(raw_method, layout.Doc): - body_rows.extend(self.render( - raw_method, is_flat=True).split("\n")) + body_rows.extend(self.render(raw_method, is_flat=True).split("\n")) text = self._render_definition_list(sig, body_rows) return "\n\n".join([title, text]) @dispatch - def render(self, el: layout.DocFunction, is_flat: bool = False): # noqa: F811 + def render( # noqa: F811 + self, el: layout.DocFunction, is_flat: bool = False + ) -> str: title = "" if is_flat else self._render_header(el.name) sig = self.signature(el) @@ -260,16 +273,23 @@ def render(self, el: layout.DocFunction, is_flat: bool = False): # noqa: F811 return "\n\n".join([title, text]) @dispatch - def render(self, el: layout.DocAttribute, is_flat: bool = False): # noqa: F811 + def render( # noqa: F811 + self, el: layout.DocAttribute, is_flat: bool = False + ) -> str: link = f"[{el.name}](#{el.anchor})" description = self.summarizer.summarize(el.obj) + # check for alias like "IntStr: TypeAlias = Optional[Union[int, str]]" + if isinstance(el.obj, dc.Alias) and el.obj.target and el.obj.target.value: + alias = f"alias of {self.render_annotation(el.obj.target)}" + return self._render_definition_list(title=link, items=[description, alias]) + return " -- ".join([link, description]) # render griffe objects =================================================== @dispatch - def render(self, el: Union[dc.Object, dc.Alias]): # noqa: F811 + def render(self, el: Union[dc.Object, dc.Alias]) -> str: # noqa: F811 """Render high level objects representing functions, classes, etc..""" str_body = [] @@ -287,11 +307,10 @@ def render(self, el: Union[dc.Object, dc.Alias]): # noqa: F811 # signature parts ------------------------------------------------------------- @dispatch - def render(self, el: dc.Parameters): # noqa: F811 + def render(self, el: dc.Parameters) -> str: # noqa: F811 # index for switch from positional to kw args (via an unnamed *) try: - kw_only = [par.kind for par in el].index( - dc.ParameterKind.keyword_only) + kw_only = [par.kind for par in el].index(dc.ParameterKind.keyword_only) except ValueError: kw_only = None @@ -327,9 +346,8 @@ def render(self, el: dc.Parameters): # noqa: F811 return ", ".join(pars) @dispatch - def render(self, el: dc.Parameter): # noqa: F811 - splats = {dc.ParameterKind.var_keyword, - dc.ParameterKind.var_positional} + def render(self, el: dc.Parameter) -> str: # noqa: F811 + splats = {dc.ParameterKind.var_keyword, dc.ParameterKind.var_positional} has_default = el.default and el.kind not in splats if el.kind == dc.ParameterKind.var_keyword: @@ -353,7 +371,7 @@ def render(self, el: dc.Parameter): # noqa: F811 # note this can be a number of things. for example, opening docstring text, # or a section with a header not included in the numpydoc standard @dispatch - def render(self, el: ds.DocstringSectionText): # noqa: F811 + def render(self, el: ds.DocstringSectionText) -> str: # noqa: F811 new_el = qast.transform(el) if isinstance(new_el, ds.DocstringSectionText): # ensures we don't recurse forever @@ -364,7 +382,7 @@ def render(self, el: ds.DocstringSectionText): # noqa: F811 # parameters ---- @dispatch - def render(self, el: ds.DocstringSectionParameters): # noqa: F811 + def render(self, el: ds.DocstringSectionParameters) -> str: # noqa: F811 # if more than one param, render as un-ordered list prefix = "* " if len(el.value) > 1 else "" follow = " " if len(el.value) > 1 else "" @@ -388,7 +406,7 @@ def render(self, el: ds.DocstringSectionParameters): # noqa: F811 # attributes ---- @dispatch - def render(self, el: ds.DocstringSectionAttributes): # noqa: F811 + def render(self, el: ds.DocstringSectionAttributes) -> str: # noqa: F811 # if more than one param, render as un-ordered list prefix = "* " if len(el.value) > 1 else "" follow = " " if len(el.value) > 1 else "" @@ -410,7 +428,7 @@ def render(self, el: ds.DocstringSectionAttributes): # noqa: F811 # examples ---- @dispatch - def render(self, el: ds.DocstringSectionExamples): # noqa: F811 + def render(self, el: ds.DocstringSectionExamples) -> str: # noqa: F811 # its value is a tuple: DocstringSectionKind["text" | "examples"], str data = map(qast.transform, el.value) return "\n\n".join(list(map(self.render, data))) @@ -428,7 +446,7 @@ def render(self, el: qast.ExampleText): # noqa: F811 # returns ---- @dispatch - def render(self, el: ds.DocstringSectionReturns): # noqa: F811 + def render(self, el: ds.DocstringSectionReturns) -> str: # noqa: F811 # if more than one param, render as un-ordered list prefix = "* " if len(el.value) > 1 else "" follow = " " if len(el.value) > 1 else "" @@ -456,7 +474,7 @@ def render(self, el: ds.DocstringSectionReturns): # noqa: F811 return self._render_definition_list("Returns:", rows, title_class="highlight") @dispatch - def render(self, el: ds.DocstringSectionRaises): # noqa: F811 + def render(self, el: ds.DocstringSectionRaises) -> str: # noqa: F811 # if more than one param, render as un-ordered list prefix = "* " if len(el.value) > 1 else "" follow = " " if len(el.value) > 1 else "" @@ -483,7 +501,7 @@ def render(self, el: ds.DocstringSectionAdmonition) -> str: # noqa: F811 else: rows.append(f"::: {{.callout-tip title={el.title!r}}}") - rows.append(el.value.description) + rows.append(sanitize(el.value.description, allow_markdown=True)) rows.append(":::") return "\n".join(rows) diff --git a/python/noxfile.py b/python/noxfile.py index 50e8c8577..4f62424e1 100644 --- a/python/noxfile.py +++ b/python/noxfile.py @@ -149,6 +149,13 @@ def docs(session: nox.Session) -> None: with session.chdir("docs"): session.run("quarto", "preview", external=True) +@nox.session(name="docs-lint", python=python_versions[0]) +def docs_gen(session: nox.Session) -> None: + """Lints the API reference config and lets you know about any missing items""" + install(session, groups=["docs"]) + + with session.chdir("docs"): + session.run("python", "_scripts/lint_reference.py") @nox.session(name="docs-build", python=python_versions[0]) def docs_build(session: nox.Session) -> None: diff --git a/python/pysrc/kaskada/_timestream.py b/python/pysrc/kaskada/_timestream.py index 3fed6947e..68ccf4508 100644 --- a/python/pysrc/kaskada/_timestream.py +++ b/python/pysrc/kaskada/_timestream.py @@ -990,7 +990,7 @@ def record(self, fields: Callable[[Timestream], Mapping[str, Arg]]) -> Timestrea fields: The fields to include in the record. See Also: - kaskada.record: Function for creating a record from one or more + [](`kaskada.record`): Function for creating a record from one or more timestreams. """ return record(fields(self)) @@ -1356,7 +1356,7 @@ def record(fields: Mapping[str, Arg]) -> Timestream: fields: The fields to include in the record. See Also: - Timestream.record: Method for creating a record from fields computed from + [Timestream.record](`kaskada.Timestream.record`): Method for creating a record from fields computed from a timestream. """ import itertools From 4ce0fb96fda8bde3764cb9b1e847cc2bbcb1c052 Mon Sep 17 00:00:00 2001 From: Eric Pinzur Date: Tue, 10 Oct 2023 17:52:31 -0500 Subject: [PATCH 14/14] fixed issues --- python/docs/_reference.yml | 17 ++++++++++++++--- python/pysrc/kaskada/_timestream.py | 4 ++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/python/docs/_reference.yml b/python/docs/_reference.yml index ece4a7fbb..3a8b39f73 100644 --- a/python/docs/_reference.yml +++ b/python/docs/_reference.yml @@ -9,6 +9,11 @@ quartodoc: dynamic: true sections: + - title: Sessions + options: + children: embedded + contents: + - init_session - title: Timestream options: children: flat @@ -16,8 +21,11 @@ quartodoc: - name: Timestream members: - data_type - - _timestream.LiteralValue - - _timestream.Arg + - is_continuous + - name: LiteralValue + dynamic: false + - name: Arg + dynamic: false - subtitle: Aggregation desc: | The User Guide has details on [aggregations in general](../../../guide/aggregation.qmd). @@ -110,6 +118,7 @@ quartodoc: - Timestream.cast - Timestream.coalesce - Timestream.else_ + - Timestream.explain - Timestream.filter - Timestream.hash - Timestream.if_ @@ -128,8 +137,10 @@ quartodoc: - record - subtitle: String contents: + - Timestream.len - Timestream.lower - Timestream.upper + - Timestream.substring - subtitle: Time contents: - Timestream.shift_by @@ -186,4 +197,4 @@ quartodoc: children: embedded contents: - History - - Snapshot \ No newline at end of file + - Snapshot diff --git a/python/pysrc/kaskada/_timestream.py b/python/pysrc/kaskada/_timestream.py index 68ccf4508..ffef219db 100644 --- a/python/pysrc/kaskada/_timestream.py +++ b/python/pysrc/kaskada/_timestream.py @@ -1356,8 +1356,8 @@ def record(fields: Mapping[str, Arg]) -> Timestream: fields: The fields to include in the record. See Also: - [Timestream.record](`kaskada.Timestream.record`): Method for creating a record from fields computed from - a timestream. + [Timestream.record](`kaskada.Timestream.record`): Method for creating a record + from fields computed from a timestream. """ import itertools