diff --git a/requirements.txt b/requirements.txt index 52469ec..4a17872 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,2 @@ # Used by streamlit deployment --e . -streamlit>=1.34.0 +-e ."[streamlit]" \ No newline at end of file diff --git a/sksmithy/_static/description.md b/sksmithy/_static/description.md index e5c60c3..646b749 100644 --- a/sksmithy/_static/description.md +++ b/sksmithy/_static/description.md @@ -1,12 +1,27 @@ +# Description + Writing scikit-learn compatible estimators might be harder than expected. -While everyone knows about the `fit` and `predict`, there are other behaviours, methods and attributes that scikit-learn might be expecting from your estimator depending on: +While everyone knows about the `fit` and `predict`, there are other behaviours, methods and attributes that +scikit-learn might be expecting from your estimator depending on: - The type of estimator you're writing. - The signature of the estimator. - The signature of the `.fit(...)` method. -Scikit-learn Smithy to the rescue: this tool aims to help you crafting your own estimator by asking a few questions about it, and then generating the boilerplate code. +Scikit-learn Smithy to the rescue: this tool aims to help you crafting your own estimator by asking a few +questions about it, and then generating the boilerplate code. + +In this way you will be able to fully focus on the core implementation logic, and not on nitty-gritty details +of the scikit-learn API. + +## Sanity check + +Once the core logic is implemented, the estimator should be ready to test against the _somewhat official_ +[`parametrize_with_checks`](https://scikit-learn.org/dev/modules/generated/sklearn.utils.estimator_checks.parametrize_with_checks.html#sklearn.utils.estimator_checks.parametrize_with_checks) +pytest compatible decorator. + +## Official guide -In this way you will be able to fully focus on the core implementation logic, and not on nitty-gritty details of the -scikit-learn API. +Scikit-learn documentation on how to +[develop estimators](https://scikit-learn.org/dev/developers/develop.html#developing-scikit-learn-estimators). diff --git a/sksmithy/_static/tui.tcss b/sksmithy/_static/tui.tcss index 46924ce..f8c1b83 100644 --- a/sksmithy/_static/tui.tcss +++ b/sksmithy/_static/tui.tcss @@ -115,7 +115,3 @@ OptionGroup { height: 1fr; border-right: vkey $background; } - -Message { - margin: 0 1; -} diff --git a/sksmithy/app.py b/sksmithy/app.py index 5d6cf26..ca45d48 100644 --- a/sksmithy/app.py +++ b/sksmithy/app.py @@ -1,5 +1,6 @@ import re import time +from importlib import resources from importlib.metadata import version from result import Err, Ok @@ -32,6 +33,8 @@ else: # pragma: no cover import streamlit as st +SIDEBAR_MSG: str = (resources.files("sksmithy") / "_static" / "description.md").read_text() + st.set_page_config( page_title="Smithy", page_icon="⚒️", @@ -52,35 +55,7 @@ st.markdown("## Forge your own scikit-learn compatible estimator") with st.sidebar: - st.markdown(""" - # Description - - Writing scikit-learn compatible estimators might be harder than expected. - - While everyone knows about the `fit` and `predict`, there are other behaviours, methods and attributes that - scikit-learn might be expecting from your estimator depending on: - - - The type of estimator you're writing. - - The signature of the estimator. - - The signature of the `.fit(...)` method. - - Scikit-learn Smithy to the rescue: this tool aims to help you crafting your own estimator by asking a few - questions about it, and then generating the boilerplate code. - - In this way you will be able to fully focus on the core implementation logic, and not on nitty-gritty details - of the scikit-learn API. - - ## Sanity check - - Once the core logic is implemented, the estimator should be ready to test against the _somewhat official_ - [`parametrize_with_checks`](https://scikit-learn.org/dev/modules/generated/sklearn.utils.estimator_checks.parametrize_with_checks.html#sklearn.utils.estimator_checks.parametrize_with_checks) - pytest compatible decorator. - - ## Official guide - - Scikit-learn documentation on how to - [develop estimators](https://scikit-learn.org/dev/developers/develop.html#developing-scikit-learn-estimators). - """) + st.markdown(SIDEBAR_MSG) sample_weights = False linear = False diff --git a/sksmithy/tui/_components.py b/sksmithy/tui/_components.py index 2f2baf6..7199e3d 100644 --- a/sksmithy/tui/_components.py +++ b/sksmithy/tui/_components.py @@ -1,13 +1,13 @@ import sys -from importlib import metadata, resources +import webbrowser +from importlib import resources from pathlib import Path from result import Err, Ok -from rich.console import RenderableType from textual import on from textual.app import ComposeResult from textual.containers import Container, Grid, Horizontal, ScrollableContainer -from textual.widgets import Button, Collapsible, Input, Select, Static, Switch, TextArea +from textual.widgets import Button, Collapsible, Input, Markdown, Select, Static, Switch, TextArea from sksmithy._models import EstimatorType from sksmithy._parsers import check_duplicates, name_parser, params_parser @@ -336,25 +336,14 @@ class ForgeRow(Grid): """Row grid for forge.""" -class Title(Static): - pass - - class OptionGroup(ScrollableContainer): pass -class Message(Static): - pass - - -class Version(Static): - def render(self: Self) -> RenderableType: - return f"Version: [b]{metadata.version('sklearn-smithy')}" - - class Sidebar(Container): def compose(self: Self) -> ComposeResult: - yield Title("Description") - yield OptionGroup(Message(SIDEBAR_MSG), Version()) - yield Version() + yield OptionGroup(Markdown(SIDEBAR_MSG)) + + def on_markdown_link_clicked(self: Self, event: Markdown.LinkClicked) -> None: + # Relevant discussion: https://github.com/Textualize/textual/discussions/3668 + webbrowser.open_new_tab(event.href) diff --git a/sksmithy/tui/_tui.py b/sksmithy/tui/_tui.py index ca8d0bf..156b694 100644 --- a/sksmithy/tui/_tui.py +++ b/sksmithy/tui/_tui.py @@ -1,5 +1,5 @@ import sys -from importlib import resources +from importlib import metadata, resources from typing import ClassVar from textual.app import App, ComposeResult @@ -29,12 +29,6 @@ from typing_extensions import Self -TEXT = """\ -import pandas as pd -import numpy as np -""" - - class ForgeTUI(App): """Textual app to forge scikit-learn compatible estimators.""" @@ -61,7 +55,7 @@ def on_mount(self: Self) -> None: def compose(self: Self) -> ComposeResult: """Create child widgets for the app.""" yield Container( - Header(), + Header(icon=f"v{metadata.version('sklearn-smithy')}"), ScrollableContainer( Horizontal(Name(), Estimator()), Horizontal(Required(), Optional()),