From 5b2efdf05da05510694a623cd2dbc0609a0407d5 Mon Sep 17 00:00:00 2001 From: Anant Dole Date: Wed, 29 May 2024 15:26:40 +0100 Subject: [PATCH] Refactoring ss to wf --- README.md | 2 +- docs/framework/backend-driven-ui.mdx | 24 +++++++++------------- docs/framework/deploy-with-docker.mdx | 8 ++++---- docs/framework/frontend-scripts.mdx | 18 ++++++++--------- docs/framework/introduction.mdx | 10 ++++----- docs/framework/page-routes.mdx | 6 +++--- docs/framework/quickstart-tutorial.mdx | 28 +++++++++++++------------- docs/framework/repeater.mdx | 2 +- docs/framework/sessions.mdx | 8 ++++---- docs/framework/state-schema.mdx | 26 ++++++++++++------------ docs/framework/stylesheets.mdx | 12 +++++------ docs/framework/testing.mdx | 20 +++++++++--------- 12 files changed, 80 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index b87039c47..d3f8109d4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## What is Streamsync? +## What is Framework? [![PyPi](https://img.shields.io/pypi/v/streamsync.svg?label=Version)](https://pypi.org/project/streamsync/) [![CI](https://github.com/streamsync-cloud/streamsync/actions/workflows/ci.yml/badge.svg)](https://github.com/streamsync-cloud/streamsync/actions/workflows/ci.yml) diff --git a/docs/framework/backend-driven-ui.mdx b/docs/framework/backend-driven-ui.mdx index 658da882d..ae09f7c81 100644 --- a/docs/framework/backend-driven-ui.mdx +++ b/docs/framework/backend-driven-ui.mdx @@ -2,14 +2,10 @@ title: "Backend-driven UI" --- -Streamsync facilitates backend-initiated user interface modifications. These changes are made possible through **Code-Managed Components** (CMCs), distinct from *Builder-Managed Components* (BMCs). +Framework facilitates backend-initiated user interface modifications. These changes are made possible through **Code-Managed Components** (CMCs), distinct from *Builder-Managed Components* (BMCs). CMCs, unlike BMCs, are dynamically created and modified via backend code, and cannot be edited (but still can be viewed) within the application builder. It's important to also note that CMCs do not persist in your application's `ui.json` file and exist only during the application runtime, supporting dynamic UI adjustments. - -Experimental feature! This Streamsync feature is still evolving. You may encounter unexpected behaviour. Your feedback is invaluable — please feel free to [share your experience and suggestions](https://github.com/streamsync-cloud/streamsync/discussions). - - To summarise: @@ -26,16 +22,16 @@ To summarise: ## UI manager -Streamsync provides two independent approaches for managing your application's UI: initializing a base UI and making session-specific updates. +Framework provides two independent approaches for managing your application's UI: initializing a base UI and making session-specific updates. ### Initializing base UI The `init_ui()` method sets up a UI manager to configure UI components at the application's startup. This creates a component set that is accessible across all sessions: ```python -import streamsync as ss +import writer as wf -with ss.init_ui() as ui: +with wf.init_ui() as ui: with ui.Page(id="my-page"): ui.Header({"text": "Hello World!"}) ui.ColumnContainer(id="column-container") @@ -179,13 +175,13 @@ In addition to `content`, a set of fields which is specific to the component typ def increment(state): state["counter"] += 1 - initial_state = ss.init_state({"counter": 0}) + initial_state = wf.init_state({"counter": 0}) ... ui.Button( {"text": "My Counter: @{counter}"}, - handlers={"ss-click": increment} + handlers={"wf-click": increment} ) # You have two options for adding a function # to the `handlers` dictionary: @@ -196,7 +192,7 @@ In addition to `content`, a set of fields which is specific to the component typ *A component can be linked to multiple event handlers.* - **`binding: dict[str, str]`**: Links the component to a state variable via [binding](https://www.streamsync.cloud/builder-basics.html#binding). The dictionary key is the bindable event, and the value is the state variable's name: ```python - initial_state = ss.init_state({ + initial_state = wf.init_state({ "header_text": "Default Text" "counter": 0 }) @@ -205,14 +201,14 @@ In addition to `content`, a set of fields which is specific to the component typ ui.TextInput( {"label": "Bound Text"}, - binding={"ss-change": "header_text"} + binding={"wf-change": "header_text"} ) # This input will display "Default Text" # Changing the text in this input will modify the `header_text` variable ui.SliderInput( {"minValue": 0, "maxValue": 300, "stepSize": 1}, - binding={"ss-number-change": "counter"} + binding={"wf-number-change": "counter"} ) # This slider will have 0 as a default value # Sliding it will modify the `counter` variable @@ -221,7 +217,7 @@ In addition to `content`, a set of fields which is specific to the component typ ### Container components -Streamsync provides multiple layout components that can serve as *containers* for other components. +Framework provides multiple layout components that can serve as *containers* for other components. You can use `with` keyword to define such layouts: ```python diff --git a/docs/framework/deploy-with-docker.mdx b/docs/framework/deploy-with-docker.mdx index 47c03f035..0a1be5492 100644 --- a/docs/framework/deploy-with-docker.mdx +++ b/docs/framework/deploy-with-docker.mdx @@ -2,7 +2,7 @@ title: "Deploy with Docker" --- -You can use Docker to deploy Streamsync anywhere. If you're an experienced Docker user, you may want to go straight to the provided Dockerfile. +You can use Docker to deploy Framework anywhere. If you're an experienced Docker user, you may want to go straight to the provided Dockerfile. ## Creating a Docker image @@ -10,7 +10,7 @@ You can use Docker to deploy Streamsync anywhere. If you're an experienced Docke - Make sure you have Docker installed. - Open a terminal and navigate to your app's folder. -- Create a `pyproject.toml` using `poetry init` and install `streamsync` using `poetry add streamsync` +- Create a `pyproject.toml` using `poetry init` and install `writer` using `poetry add writer` ### Creating a Dockerfile @@ -27,7 +27,7 @@ WORKDIR /app RUN pip3 install poetry RUN poetry config virtualenvs.create false RUN poetry install --only main -ENTRYPOINT [ "streamsync", "run" ] +ENTRYPOINT [ "writer", "run" ] EXPOSE 8080 CMD [ ".", "--port", "8080", "--host", "0.0.0.0" ] ``` @@ -35,7 +35,7 @@ CMD [ ".", "--port", "8080", "--host", "0.0.0.0" ] This Dockerfile is just a guideline. It uses an official Python slim base image with a multistage build to reduce the size of the built image. -If you're a Docker expert, feel free to work on your own `Dockerfile`. Streamsync is, after all, a standard Python package. +If you're a Docker expert, feel free to work on your own `Dockerfile`. Framework is, after all, a standard Python package. ### Building the Docker image diff --git a/docs/framework/frontend-scripts.mdx b/docs/framework/frontend-scripts.mdx index 7aaf021ac..386271dba 100644 --- a/docs/framework/frontend-scripts.mdx +++ b/docs/framework/frontend-scripts.mdx @@ -2,11 +2,11 @@ title: "Frontend scripts" --- -Streamsync can import custom JavaScript/ES6 modules from the frontend. Module functions can be triggered from the backend. +Framework can import custom JavaScript/ES6 modules from the frontend. Module functions can be triggered from the backend. ## Importing an ES6 module -Similarly to [stylesheets](/stylesheets), frontend scripts are imported via Streamsync's `mail` capability. This allows you to trigger an import for all or specific sessions at any time during runtime. When the `import_frontend_module` method is called, this triggers a dynamic [import()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import) call in the frontend. +Similarly to [stylesheets](/stylesheets), frontend scripts are imported via Framework's `mail` capability. This allows you to trigger an import for all or specific sessions at any time during runtime. When the `import_frontend_module` method is called, this triggers a dynamic [import()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import) call in the frontend. The `import_frontend_module` method takes the `module_key` and `specifier` arguments. The `module_key` is an identifier used to store the reference to the module, which will be used later to call the module's functions. The `specifier` is the path to the module, such as `/static/mymodule.js`. It needs to be available to the frontend, so storing in the `/static/` folder is recommended. @@ -20,7 +20,7 @@ def handle_click(state): If you want the module to be imported during initialisation, use the initial state. ```py -initial_state = ss.init_state({ +initial_state = wf.init_state({ "counter": 1 }) @@ -61,10 +61,10 @@ def handle_click(state): ## Import a JavaScript script -Streamsync can also import and run JavaScript scripts directly, for their side effects. These are imported via the report's `import_script` method. This method takes two arguments. The first, `script_key` is the identifier used to import the script. The second, `path` is the path to the file. The specified path must be available to the frontend, so storing it in your application's `./static` folder is recommended. +Framework can also import and run JavaScript scripts directly, for their side effects. These are imported via the report's `import_script` method. This method takes two arguments. The first, `script_key` is the identifier used to import the script. The second, `path` is the path to the file. The specified path must be available to the frontend, so storing it in your application's `./static` folder is recommended. ```py -initial_state = ss.init_state({ +initial_state = wf.init_state({ "counter": 1 }) @@ -79,10 +79,10 @@ Importing scripts is useful to import libraries that don't support ES6 modules. ## Importing a script or stylesheet from a URL -Streamsync can also import scripts and stylesheets from URLs. This is useful for importing libraries from CDNs. The `import_script` and `import_stylesheet` methods take a `url` argument, which is the URL to the script or stylesheet. +Framework can also import scripts and stylesheets from URLs. This is useful for importing libraries from CDNs. The `import_script` and `import_stylesheet` methods take a `url` argument, which is the URL to the script or stylesheet. ```python -initial_state = ss.init_state({ +initial_state = wf.init_state({ "my_app": { "title": "My App" }, @@ -93,7 +93,7 @@ initial_state.import_script("lodash", "https://cdnjs.cloudflare.com/ajax/libs/lo ## Frontend core -You can access Streamsync's frontend core via `globalThis.core`, unlocking all sorts of functionality. Notably, you can use `getUserState()` to get values from state. +You can access Framework's frontend core via `globalThis.core`, unlocking all sorts of functionality. Notably, you can use `getUserState()` to get values from state. ```js export function alertHueRotationValue() { @@ -105,5 +105,5 @@ export function alertHueRotationValue() { Here be dragons -Effectively using Streamsync's core can be challenging and will likely entail reading its [source code](https://github.com/streamsync-cloud/streamsync/blob/master/ui/src/core/index.ts). Furthermore, it's considered an internal capability rather than a public API, so it may unexpectedly change between releases. +Effectively using Framework's core can be challenging and will likely entail reading its [source code](https://github.com/streamsync-cloud/streamsync/blob/master/ui/src/core/index.ts). Furthermore, it's considered an internal capability rather than a public API, so it may unexpectedly change between releases. \ No newline at end of file diff --git a/docs/framework/introduction.mdx b/docs/framework/introduction.mdx index 130eeeaa4..9ac4635bc 100644 --- a/docs/framework/introduction.mdx +++ b/docs/framework/introduction.mdx @@ -2,11 +2,11 @@ title: "Introduction" --- -## What is Streamsync? +## What is Framework? -Streamsync is an open-source framework for creating data apps. Build user interfaces using a visual editor; write the backend code in Python. +Framework is an open-source framework for creating data apps. Build user interfaces using a visual editor; write the backend code in Python. -![Streamsync Builder screenshot](/framework/public/builder.png) +![Framework Builder screenshot](/framework/public/builder.png) It's an alternative to Plotly Dash, Streamlit and Gradio. Its focused on the creation of web applications for data analytics and machine learning. @@ -21,12 +21,12 @@ Event handlers are defined as plain, easily-testable Python functions. def handle_increment(state): state["counter"] += 1 -ss.init_state({ +wf.init_state({ "counter": 0 }) ``` -The event handler and state are linked to the UI using Streamsync Builder, the framework's visual editor. +The event handler and state are linked to the UI using Framework Builder, the framework's visual editor. ![Counter Increment example](/framework/public/introduction.counter.gif) diff --git a/docs/framework/page-routes.mdx b/docs/framework/page-routes.mdx index 436b5d73c..6de994b24 100644 --- a/docs/framework/page-routes.mdx +++ b/docs/framework/page-routes.mdx @@ -2,7 +2,7 @@ title: "Page routes" --- -Streamsync apps can have multiple pages, with parametrised routes. Pages can be switched from the frontend or the backend. +Framework apps can have multiple pages, with parametrised routes. Pages can be switched from the frontend or the backend. ## Basic navigation @@ -33,7 +33,7 @@ def handle_click(state): You may want to share a URL that links directly to a specific resource within your app. For example, to a specific location or product. -You can do so by specifying parameters in the URL, known as route vars. Streamsync URLs contain the page key, followed by the route vars and their values. For example, `/#detailPage/product_id=32&country=AR`. +You can do so by specifying parameters in the URL, known as route vars. Framework URLs contain the page key, followed by the route vars and their values. For example, `/#detailPage/product_id=32&country=AR`. ### Adding vars to the URL from the backend @@ -50,7 +50,7 @@ def change_route_vars(state): ### Retrieving the values -Streamsync uses the hash portion of the URL to store page and variable data, so even when switching pages or changing variables, the page doesn't reload. To monitor changes to the active URL, set up an event handler for `ss-hashchange` in the _Root_ component. +Framework uses the hash portion of the URL to store page and variable data, so even when switching pages or changing variables, the page doesn't reload. To monitor changes to the active URL, set up an event handler for `wf-hashchange` in the _Root_ component. ```py # The following event handler reads the product_id route var, diff --git a/docs/framework/quickstart-tutorial.mdx b/docs/framework/quickstart-tutorial.mdx index a7bdcc2f2..9d2aebcd7 100644 --- a/docs/framework/quickstart-tutorial.mdx +++ b/docs/framework/quickstart-tutorial.mdx @@ -1,9 +1,9 @@ --- title: "Quickstart tutorial" --- -In this tutorial, we'll guide you through creating a logistic regression visualisation tool using Streamsync. Logistic regression is a fundamental technique in machine learning for binary classification tasks, and visualising its decision boundary can provide valuable insights into the model's behaviour. +In this tutorial, we'll guide you through creating a logistic regression visualisation tool using Framework. Logistic regression is a fundamental technique in machine learning for binary classification tasks, and visualising its decision boundary can provide valuable insights into the model's behaviour. -First, make sure you have Streamsync installed. You can install it via pip: +First, make sure you have Framework installed. You can install it via pip: ```bash pip install "streamsync[ds]" @@ -41,19 +41,19 @@ After that, we can install our requirements. pip install -r requirements.txt ``` -Once this is done, we can finally run the Streamsync editor using the command: +Once this is done, we can finally run the Framework editor using the command: ```bash streamsync edit . ``` -This will run our Streamsync instance. Runtime logs can be observed in the terminal, and the app is available at http://localhost:3006. +This will run our Framework instance. Runtime logs can be observed in the terminal, and the app is available at http://localhost:3006. ![newly created application](./images/quickstart/new_app.png) ## UI Creation -By default, Streamsync creates a simple application with a counter. To keep things easy, let's remove the contents from columns to make space for our new application. If you're unsure where to click to select a specific component on the screen, you can always use the `Component Tree` on the bottom left of the screen. The app should look something like this when you finish. +By default, Framework creates a simple application with a counter. To keep things easy, let's remove the contents from columns to make space for our new application. If you're unsure where to click to select a specific component on the screen, you can always use the `Component Tree` on the bottom left of the screen. The app should look something like this when you finish. ![empty app](./images/quickstart/empty_app.png) @@ -109,12 +109,12 @@ It is time to create the application's initial state. Let's open the code editor Let's remove all code from there and start with: ```python -import streamsync as ss +import writer as wf import plotly.graph_objects as go from sklearn.linear_model import LogisticRegression from sklearn.datasets import make_blobs -initial_state = ss.init_state({ +initial_state = wf.init_state({ "my_app": { "title": "Logistic Regression Visualiser" }, @@ -126,7 +126,7 @@ initial_state = ss.init_state({ "cluster_std": 2, }) ``` -For now, only the Streamsync import is needed, but the rest will be used later on. Notice that after pasting this code into the editor, when we click on `Save and run`, the header of our application will immediately change to "Logistic regression visualiser". This is because the Header has in its text property the value `@{my_app.title}`, which is a template syntax that uses a value from the state. +For now, only the Framework import is needed, but the rest will be used later on. Notice that after pasting this code into the editor, when we click on `Save and run`, the header of our application will immediately change to "Logistic regression visualiser". This is because the Header has in its text property the value `@{my_app.title}`, which is a template syntax that uses a value from the state. The rest of the keys and values from the `initial_state` are names and initial values for components that will be used for communication between the app UI and the backend. Assigning those keys to components is called binding, and it is done by clicking on each component and filling property "State element" in the "Binding" menu. Let's use these bindings for our 3 _Slider Input_ components: @@ -212,7 +212,7 @@ The algorithm will generate one or many lines depending on how many groups we ha def _line(x0, coef, intercept, c): return (-(x0 * coef[c, 0]) - intercept[c]) / coef[c, 1] ``` -This function is a helper function meant to be used on the backend. The underscore at the beginning of its name tells Streamsync that this function is private, and the frontend won't know about its existence. +This function is a helper function meant to be used on the backend. The underscore at the beginning of its name tells Framework that this function is private, and the frontend won't know about its existence. To make the plot more readable, let's quickly define some colours for our plots: @@ -288,16 +288,16 @@ Now, let's create a plot for our logistic regressions. For that, we will use `pl ``` After saving and running the code, we should get something like this: -But as you could notice, when we change our slider values, nothing happens. It's because our function is currently called only once on app initialisation and not after input changes. To change this behaviour, let's set the event handler for `ss-number-change` in all slider inputs to `update`, which is the name of our function in the Python code. Notice that `_line` is not visible there because it's private to the backend. If we would change its name to `line`, then it would be visible on this list. +But as you could notice, when we change our slider values, nothing happens. It's because our function is currently called only once on app initialisation and not after input changes. To change this behaviour, let's set the event handler for `wf-number-change` in all slider inputs to `update`, which is the name of our function in the Python code. Notice that `_line` is not visible there because it's private to the backend. If we would change its name to `line`, then it would be visible on this list. -Set also event handler for dropdown input `ss-option-change` and `ss-click` in the button, also to `update`. +Set also event handler for dropdown input `wf-option-change` and `wf-click` in the button, also to `update`. And done! You can have fun with your new application. Feel free to modify and play with other options. Final code for the application should look something like this: ```python -import streamsync as ss +import writer as wf import plotly.graph_objects as go from sklearn.linear_model import LogisticRegression from sklearn.datasets import make_blobs @@ -398,7 +398,7 @@ def update(state): state['figure'] = fig -initial_state = ss.init_state({ +initial_state = wf.init_state({ "my_app": { "title": "Logistic regression visualizer" }, @@ -422,7 +422,7 @@ When your code has an error, you will be notified with a notification in the app To check some intermediate values in your Python code, you can just use `print()` function. All logs will be available in the terminal. ## Conclusion -Congratulations! You've successfully created a logistic regression visualisation tool using Streamsync. You can further customise and enhance this tool to suit your specific needs. +Congratulations! You've successfully created a logistic regression visualisation tool using Framework. You can further customise and enhance this tool to suit your specific needs. ## Additional Resources - [Scikit-learn Documentation](https://scikit-learn.org/stable/) diff --git a/docs/framework/repeater.mdx b/docs/framework/repeater.mdx index 475d68717..a849914d5 100644 --- a/docs/framework/repeater.mdx +++ b/docs/framework/repeater.mdx @@ -17,7 +17,7 @@ Each iteration is rendered with a different **context**, a dictionary containing Given the state below, the contents of _Repeater_ will be repeated 3 times. For the first iteration, `itemId` will equal `Banana`, and `item` will equal `{"type": "fruit", "colour": "yellow"}`. Components inside _Repeater_ will be able to access this data using references such as `@{itemId}` and `@{item.type}`. ```py -ss.init_state({ +wf.init_state({ "articles": { "Banana": { "type": "fruit", diff --git a/docs/framework/sessions.mdx b/docs/framework/sessions.mdx index 2bd9d5759..d9784a133 100644 --- a/docs/framework/sessions.mdx +++ b/docs/framework/sessions.mdx @@ -2,7 +2,7 @@ title: "Sessions" --- -Sessions are designed for advanced use cases, being most relevant when Streamsync is deployed behind a proxy. +Sessions are designed for advanced use cases, being most relevant when Framework is deployed behind a proxy. ## Session information in event handlers @@ -23,14 +23,14 @@ This enables you to adapt the logic of an event to a number of factors, such as You can use session verifiers to accept or deny a session based on headers or cookies, thus making sure that users without the right privileges don't get access to the initial state or components. -Session verifiers are functions decorated with `ss.session_verifier` and are run every time a user requests a session. A `True` value means that the session must be accepted, a `False` value means that the session must be rejected. +Session verifiers are functions decorated with `wf.session_verifier` and are run every time a user requests a session. A `True` value means that the session must be accepted, a `False` value means that the session must be rejected. ```py -import streamsync as ss +import writer as wf # Users without the header x-success will be denied the session -@ss.session_verifier +@wf.session_verifier def check_headers(headers): if headers.get("x-success") is None: return False diff --git a/docs/framework/state-schema.mdx b/docs/framework/state-schema.mdx index fa022e3a0..aae9be45a 100644 --- a/docs/framework/state-schema.mdx +++ b/docs/framework/state-schema.mdx @@ -2,18 +2,18 @@ title: "State schema" --- -Schema declarations on the [Application state](./application-state) allows Streamsync to handle complex serialisation +Schema declarations on the [Application state](./application-state) allows Framework to handle complex serialisation scenarios, while also allowing your IDE and toolchains to provide autocomplete and type checking. ## Schema declaration ```python -import streamsync as ss +import writer as wf -class AppSchema(ss.StreamsyncState): +class AppSchema(wf.StreamsyncState): counter: int -initial_state = ss.init_state({ +initial_state = wf.init_state({ "counter": 0 }, schema=AppSchema) @@ -33,7 +33,7 @@ def increment(state: AppSchema): Attributes missing from the schema remain accessible by their key. ```python -initial_state = ss.init_state({ +initial_state = wf.init_state({ "counter": 0, "message": None }, schema=AppSchema) @@ -47,14 +47,14 @@ def increment(state: AppSchema): Schema composition allows you to model a complex Application state. ```python -class MyappSchema(ss.State): +class MyappSchema(wf.State): title: str -class AppSchema(ss.StreamsyncState): +class AppSchema(wf.StreamsyncState): my_app: MyappSchema counter: int -initial_state = ss.init_state({ +initial_state = wf.init_state({ "counter": 0, "my_app": { "title": "Nested value" @@ -70,7 +70,7 @@ A schema allows you to specify that an attribute which contains a dictionary must be treated as a dictionary, rather than as a group of state. ```python -class AppSchema(ss.StreamsyncState): +class AppSchema(wf.StreamsyncState): vegas_graph: dict # Without schema, this handler is execute only once @@ -79,7 +79,7 @@ def handle_vega_graph(state: AppSchema): graph["data"]["values"][0]["b"] += 1000 state.vega_graph = graph -initial_state = ss.init_state({ +initial_state = wf.init_state({ "vegas_graph": { "data": { "values": [ @@ -110,15 +110,15 @@ apps/myapp/main.py:7: error: "AppSchema" has no attribute "countr"; maybe "count Here is the code, can you spot the error ? ```python -import streamsync as ss +import writer as wf -class AppSchema(ss.StreamsyncState): +class AppSchema(wf.StreamsyncState): counter: int def increment(state: AppSchema): state.countr += 1 -initial_state = ss.init_state({ +initial_state = wf.init_state({ "counter": 26, }, schema=AppSchema) ``` diff --git a/docs/framework/stylesheets.mdx b/docs/framework/stylesheets.mdx index a26aa3325..3b4b89fba 100644 --- a/docs/framework/stylesheets.mdx +++ b/docs/framework/stylesheets.mdx @@ -6,7 +6,7 @@ The appearance of your application can be fully customised via CSS stylesheets. ## Importing a stylesheet -Stylesheet imports are triggered via Streamsync's `mail`, similarly to other features discussed in [Backend-initiated actions](/backend-initiated-actions). When the import is triggered, the frontend downloads the specified stylesheet and creates a `style` element with its contents. +Stylesheet imports are triggered via Framework's `mail`, similarly to other features discussed in [Backend-initiated actions](/backend-initiated-actions). When the import is triggered, the frontend downloads the specified stylesheet and creates a `style` element with its contents. The `import_stylesheet` method takes the `stylesheet_key` and `path` arguments. The first works as an identifier that will let you override the stylesheet later if needed. The second is the path to the CSS file.The path specified needs to be available to the frontend, so storing it in the `/static` folder of your app is recommended. @@ -20,7 +20,7 @@ def handle_click(state): In many cases, you'll want to import a stylesheet during initialisation time, for all users. This is easily achievable via the initial state, as shown below. ```py -initial_state = ss.init_state({ +initial_state = wf.init_state({ "counter": 1 }) @@ -42,7 +42,7 @@ You can use the property *Custom CSS classes* in Builder's *Component Settings* ## Tips for effective stylesheets -The CSS code for the class used earlier, `bubblegum`, can be found below. Note how the `!important` flag is used when targetting style attributes that are configurable via Builder. If the flag isn't included, these declarations will not work, because built-in Streamsync styling is of higher specificity. +The CSS code for the class used earlier, `bubblegum`, can be found below. Note how the `!important` flag is used when targetting style attributes that are configurable via Builder. If the flag isn't included, these declarations will not work, because built-in Framework styling is of higher specificity. ```css .bubblegum { @@ -60,10 +60,10 @@ The CSS code for the class used earlier, `bubblegum`, can be found below. Note h Component structure may change -When targeting specific HTML elements inside components, take into account that the internal structure of components may change across Streamsync versions. +When targeting specific HTML elements inside components, take into account that the internal structure of components may change across Framework versions. -Alternatively, you can override Streamsync's style variables. This behaves slightly differently though; style variables are inherited by children components. For example, if a *Section* has been assigned the `bubblegum` class, its children will also have a pink background by default. +Alternatively, you can override Framework's style variables. This behaves slightly differently though; style variables are inherited by children components. For example, if a *Section* has been assigned the `bubblegum` class, its children will also have a pink background by default. ```css .bubblegum { @@ -80,7 +80,7 @@ The class can be used in *Component Settings*. If the stylesheet is imported, th ## Targeting component types -Streamsync components have root HTML elements with a class linked to their type. For example, *Dataframe* components use the class *CoreDataframe*. When writing a stylesheet, you can target all *Dataframe* components as shown below. +Framework components have root HTML elements with a class linked to their type. For example, *Dataframe* components use the class *CoreDataframe*. When writing a stylesheet, you can target all *Dataframe* components as shown below. ```css .CoreDataframe { diff --git a/docs/framework/testing.mdx b/docs/framework/testing.mdx index 112a381a7..7fb49a13f 100644 --- a/docs/framework/testing.mdx +++ b/docs/framework/testing.mdx @@ -2,20 +2,20 @@ title: "Testing" --- -Testing a Streamsync application is easy. Given that event handlers are plain Python functions that take arguments such as `state` and `payload`, you can inject your own and test whether the outcome is correct. This section will use `pytest` examples. +Testing a Framework application is easy. Given that event handlers are plain Python functions that take arguments such as `state` and `payload`, you can inject your own and test whether the outcome is correct. This section will use `pytest` examples. ## State ### Accessing the initial state -To get started, import your app's entry point, `main`. This will initialise state and make event handlers available. The initial state is available in the module, at `main.ss.initial_state` provided you imported `streamsync` as `ss`. +To get started, import your app's entry point, `main`. This will initialise state and make event handlers available. The initial state is available in the module, at `main.wf.initial_state` provided you imported `writer` as `wf`. ### Creating states -For testing purposes, you can create your own state using the `StreamsyncState` class in `streamsync.core`. Pass a dictionary when constructing it. +For testing purposes, you can create your own state using the `StreamsyncState` class in `writer.core`. Pass a dictionary when constructing it. ```py -from streamsync.core import StreamsyncState +from writer.core import StreamsyncState artificial_state = StreamsyncState({ "a": 3, @@ -25,7 +25,7 @@ artificial_state = StreamsyncState({ ## Example -The code of a Streamsync application basically consists of two things: +The code of a Framework application basically consists of two things: - Initial state - Event handlers @@ -35,12 +35,12 @@ It's straightforward to test both, as shown below. ### The app ```py -import streamsync as ss +import writer as wf def handle_multiplication(state): state["n"] = state["a"]*state["b"] -ss.init_state({ +wf.init_state({ "counter": 0, "a": 0, "b": 0 @@ -50,14 +50,14 @@ ss.init_state({ ### The tests ```py -from streamsync.core import StreamsyncState +from writer.core import WriterState import main class TestApp: - initial_state = main.ss.initial_state - artificial_state = StreamsyncState({ + initial_state = main.wf.initial_state + artificial_state = WriterState({ "a": 3, "b": 2 })