From 679b30df7e884f5535c2b947151b2913be96b29f Mon Sep 17 00:00:00 2001 From: Johannes Kasimir Date: Fri, 1 Dec 2023 11:24:41 +0100 Subject: [PATCH 01/13] feat: add html repr for pipelines --- src/sciline/display.py | 144 ++++++++++++++++++++++++++++++++++++++++ src/sciline/pipeline.py | 49 ++++++++++++++ src/sciline/utils.py | 18 +++++ tests/pipeline_test.py | 4 ++ 4 files changed, 215 insertions(+) create mode 100644 src/sciline/display.py create mode 100644 src/sciline/utils.py diff --git a/src/sciline/display.py b/src/sciline/display.py new file mode 100644 index 00000000..fc2a3ac8 --- /dev/null +++ b/src/sciline/display.py @@ -0,0 +1,144 @@ +import inspect +from dataclasses import dataclass +from html import escape +from itertools import chain +from typing import Any, Literal, Mapping, Sequence, Tuple, TypeVar + +from .param_table import ParamTable +from .typing import Key +from .utils import qualname + +ProviderKind = Literal['function', 'parameter', 'table'] + + +@dataclass +class ProviderDisplayData: + origin: Key + args: Tuple[Key | TypeVar, ...] + kind: ProviderKind + value: Any + + +def _details(summary: str, body: str) -> str: + return f''' +
+ {summary} + {body} +
+ ''' + + +def _provider_name(p: ProviderDisplayData) -> str: + name = f'{qualname(p.origin)}' + if p.args: + args = ','.join( + ('*' if isinstance(arg, TypeVar) else f'{qualname(arg)}' for arg in p.args) + ) + name += f'[{args}]' + return escape(str(name)) + + +def _provider_source(p: ProviderDisplayData) -> str: + if p.kind != 'function': + return '' + module = getattr(inspect.getmodule(p.value), '__name__', '') + return _details( + escape(p.value.__name__), + escape(f'{module}.{p.value.__name__}'), + ) + + +def _provider_value(p: ProviderDisplayData) -> str: + if p.kind != 'parameter': + return '' + if hasattr(p.value, '_repr_html_'): + html = p.value._repr_html_() + return f'{html}' + return escape(str(p.value)) + + +def provider_table( + providers: Mapping[ProviderKind, Sequence[ProviderDisplayData]] +) -> str: + provider_rows = '\n'.join( + ( + f''' + + {_provider_name(p)} + {_provider_source(p)} + {_provider_value(p)} + ''' + for p in sorted( + chain(providers['function'], providers['parameter']), + key=lambda p: _provider_name(p), + ) + ) + ) + return f''' +
+ + + + + + + + + + {provider_rows} + +
NameSourceValue
+
+ ''' + + +def _parameter_tables(parameter_tables: Sequence[ParamTable]) -> str: + def parameter_table(p: ParamTable) -> str: + name = escape(qualname(p.row_dim)) + html = p._repr_html_() + return f''' +
+
{name}
+ {html} +
+ ''' + + tables = '\n'.join(map(parameter_table, parameter_tables)) + return f''' + +
+

Parameter tables

+
+ {tables} +
+
+ ''' + + +def pipeline_html_repr( + providers: Mapping[ProviderKind, Sequence[ProviderDisplayData]], + param_tables: Sequence[ParamTable], +) -> str: + return f''' + +
+ {provider_table(providers) if len(providers) != 0 else ''} + {_parameter_tables(param_tables) if len(param_tables) != 0 else ''} +
+ '''.strip() diff --git a/src/sciline/pipeline.py b/src/sciline/pipeline.py index 81aa8a28..74d4e1fd 100644 --- a/src/sciline/pipeline.py +++ b/src/sciline/pipeline.py @@ -26,6 +26,7 @@ from sciline.task_graph import TaskGraph +from .display import ProviderDisplayData, ProviderKind, pipeline_html_repr from .domain import Scope, ScopeTwoParams from .handler import ( ErrorHandler, @@ -37,6 +38,7 @@ from .scheduler import Scheduler from .series import Series from .typing import Graph, Item, Key, Label, Provider, get_optional, get_union +from .utils import groupby, qualname T = TypeVar('T') KeyType = TypeVar('KeyType') @@ -138,6 +140,14 @@ def provide_none() -> None: return None +def _kind_of_provider(p: Callable[..., Any]) -> ProviderKind: + if qualname(p) == f'{qualname(Pipeline.__setitem__)}..': + return 'parameter' + if qualname(p) == f'{qualname(Pipeline.set_param_table)}..': + return 'table' + return 'function' + + class ReplicatorBase(Generic[IndexType]): def __init__(self, index_name: type, index: Iterable[IndexType], path: List[Key]): if len(path) == 0: @@ -808,3 +818,42 @@ def copy(self) -> Pipeline: def __copy__(self) -> Pipeline: return self.copy() + + def _repr_html_(self) -> str: + providers_without_parameters = ( + (p, tuple(), v) for p, v in self._providers.items() + ) # type: ignore[var-annotated] + providers_with_parameters = ( + (p, c, v) + for p in self._subproviders + for c, v in self._subproviders[p].items() + ) + providers = groupby( + lambda p: p.kind, + ( + ProviderDisplayData( + origin, + args, + k := _kind_of_provider(value), + value() if k != 'function' else value, + ) + for origin, args, value in chain( + providers_with_parameters, providers_without_parameters + ) + ), + ) + param_tables_by_name = groupby( + lambda p: p.origin.label[0].tp, providers['table'] + ) + param_tables = [] + for table_name, table_cells in param_tables_by_name.items(): + columns = groupby(lambda p: p.origin.tp, table_cells) + index = [p.origin.label[0].index for p in next(iter(columns.values()))] + param_tables.append( + ParamTable( + table_name, + {k: [v.value for v in col] for k, col in columns.items()}, + index=index, + ) + ) + return pipeline_html_repr(providers, param_tables) diff --git a/src/sciline/utils.py b/src/sciline/utils.py new file mode 100644 index 00000000..0bf821d3 --- /dev/null +++ b/src/sciline/utils.py @@ -0,0 +1,18 @@ +from collections import defaultdict +from typing import Any, Callable, DefaultDict, Iterable, TypeVar + +T = TypeVar('T') +G = TypeVar('G') + + +def groupby(f: Callable[[T], G], a: Iterable[T]) -> DefaultDict[G, list[T]]: + g = defaultdict(lambda: []) + for e in a: + g[f(e)].append(e) + return g + + +def qualname(obj: Any) -> Any: + return ( + obj.__qualname__ if hasattr(obj, '__qualname__') else obj.__class__.__qualname__ + ) diff --git a/tests/pipeline_test.py b/tests/pipeline_test.py index 8a46fe18..dfec0d88 100644 --- a/tests/pipeline_test.py +++ b/tests/pipeline_test.py @@ -1197,3 +1197,7 @@ def process( b[RawData[Sample]] = 7 assert a.compute(Result) == 29 assert b.compute(Result) == 53 + +def test_html_repr() -> None: + pipeline = sl.Pipeline([make_int], params={float: 5.0}) + assert isinstance(pipeline._repr_html_(), str) From 3c4e9b7bed0fc570388fb3dc3731623ca75e5974 Mon Sep 17 00:00:00 2001 From: Johannes Kasimir Date: Tue, 19 Dec 2023 16:24:50 +0100 Subject: [PATCH 02/13] remove unnecessary header --- src/sciline/display.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/sciline/display.py b/src/sciline/display.py index fc2a3ac8..b6356f04 100644 --- a/src/sciline/display.py +++ b/src/sciline/display.py @@ -35,7 +35,7 @@ def _provider_name(p: ProviderDisplayData) -> str: ('*' if isinstance(arg, TypeVar) else f'{qualname(arg)}' for arg in p.args) ) name += f'[{args}]' - return escape(str(name)) + return escape(name) def _provider_source(p: ProviderDisplayData) -> str: @@ -94,11 +94,9 @@ def provider_table( def _parameter_tables(parameter_tables: Sequence[ParamTable]) -> str: def parameter_table(p: ParamTable) -> str: - name = escape(qualname(p.row_dim)) html = p._repr_html_() return f'''
-
{name}
{html}
''' From a6f1779c93d97f27a5a8293ee8ba8ef5fe0a212c Mon Sep 17 00:00:00 2001 From: Johannes Kasimir Date: Wed, 20 Dec 2023 14:22:12 +0100 Subject: [PATCH 03/13] fix: remove separate view for parameter tables --- src/sciline/display.py | 87 ++++++++++++----------------------------- src/sciline/pipeline.py | 16 +------- 2 files changed, 26 insertions(+), 77 deletions(-) diff --git a/src/sciline/display.py b/src/sciline/display.py index b6356f04..540d97a2 100644 --- a/src/sciline/display.py +++ b/src/sciline/display.py @@ -2,11 +2,10 @@ from dataclasses import dataclass from html import escape from itertools import chain -from typing import Any, Literal, Mapping, Sequence, Tuple, TypeVar +from typing import Any, Literal, Mapping, Sequence, Tuple, TypeVar, Union -from .param_table import ParamTable from .typing import Key -from .utils import qualname +from .utils import groupby, qualname ProviderKind = Literal['function', 'parameter', 'table'] @@ -28,7 +27,10 @@ def _details(summary: str, body: str) -> str: ''' -def _provider_name(p: ProviderDisplayData) -> str: +def _provider_name(p: Union[ProviderDisplayData, Tuple]) -> str: + if isinstance(p, tuple): + (name, cname), values = p + return escape(f'{qualname(cname)}({qualname(name)})') name = f'{qualname(p.origin)}' if p.args: args = ','.join( @@ -38,8 +40,8 @@ def _provider_name(p: ProviderDisplayData) -> str: return escape(name) -def _provider_source(p: ProviderDisplayData) -> str: - if p.kind != 'function': +def _provider_source(p: Union[ProviderDisplayData, Tuple]) -> str: + if isinstance(p, tuple) or p.kind != 'function': return '' module = getattr(inspect.getmodule(p.value), '__name__', '') return _details( @@ -48,18 +50,25 @@ def _provider_source(p: ProviderDisplayData) -> str: ) -def _provider_value(p: ProviderDisplayData) -> str: +def _provider_value(p: Union[ProviderDisplayData, Tuple]) -> str: + if isinstance(p, tuple): + (name, cname), values = p + return escape(f'length: {len(values)}') if p.kind != 'parameter': return '' if hasattr(p.value, '_repr_html_'): - html = p.value._repr_html_() - return f'{html}' + return _details('', p.value._repr_html_()) return escape(str(p.value)) -def provider_table( +def pipeline_html_repr( providers: Mapping[ProviderKind, Sequence[ProviderDisplayData]] ) -> str: + param_table_columns_by_name_colname = groupby( + lambda p: (p.origin.label[0].tp, p.origin.tp), + providers['table'], + ) + provider_rows = '\n'.join( ( f''' @@ -69,13 +78,17 @@ def provider_table( {_provider_value(p)} ''' for p in sorted( - chain(providers['function'], providers['parameter']), + chain( + providers['function'], + providers['parameter'], + param_table_columns_by_name_colname.items(), + ), key=lambda p: _provider_name(p), ) ) ) return f''' -
+
@@ -89,54 +102,4 @@ def provider_table(
- ''' - - -def _parameter_tables(parameter_tables: Sequence[ParamTable]) -> str: - def parameter_table(p: ParamTable) -> str: - html = p._repr_html_() - return f''' -
- {html} -
- ''' - - tables = '\n'.join(map(parameter_table, parameter_tables)) - return f''' - -
-

Parameter tables

-
- {tables} -
-
- ''' - - -def pipeline_html_repr( - providers: Mapping[ProviderKind, Sequence[ProviderDisplayData]], - param_tables: Sequence[ParamTable], -) -> str: - return f''' - -
- {provider_table(providers) if len(providers) != 0 else ''} - {_parameter_tables(param_tables) if len(param_tables) != 0 else ''} -
'''.strip() diff --git a/src/sciline/pipeline.py b/src/sciline/pipeline.py index 74d4e1fd..ee2f9dc1 100644 --- a/src/sciline/pipeline.py +++ b/src/sciline/pipeline.py @@ -842,18 +842,4 @@ def _repr_html_(self) -> str: ) ), ) - param_tables_by_name = groupby( - lambda p: p.origin.label[0].tp, providers['table'] - ) - param_tables = [] - for table_name, table_cells in param_tables_by_name.items(): - columns = groupby(lambda p: p.origin.tp, table_cells) - index = [p.origin.label[0].index for p in next(iter(columns.values()))] - param_tables.append( - ParamTable( - table_name, - {k: [v.value for v in col] for k, col in columns.items()}, - index=index, - ) - ) - return pipeline_html_repr(providers, param_tables) + return pipeline_html_repr(providers) From 0d8437a75a1c72796814eb55fb14106d63217a06 Mon Sep 17 00:00:00 2001 From: Johannes Kasimir Date: Wed, 20 Dec 2023 14:57:07 +0100 Subject: [PATCH 04/13] fix: some of the type errors --- src/sciline/display.py | 14 ++++++++++---- src/sciline/utils.py | 4 ++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/sciline/display.py b/src/sciline/display.py index 540d97a2..483c149c 100644 --- a/src/sciline/display.py +++ b/src/sciline/display.py @@ -27,7 +27,9 @@ def _details(summary: str, body: str) -> str: ''' -def _provider_name(p: Union[ProviderDisplayData, Tuple]) -> str: +def _provider_name( + p: Union[ProviderDisplayData, Tuple[Tuple[Any, Any], Sequence[ProviderDisplayData]]] +) -> str: if isinstance(p, tuple): (name, cname), values = p return escape(f'{qualname(cname)}({qualname(name)})') @@ -37,10 +39,12 @@ def _provider_name(p: Union[ProviderDisplayData, Tuple]) -> str: ('*' if isinstance(arg, TypeVar) else f'{qualname(arg)}' for arg in p.args) ) name += f'[{args}]' - return escape(name) + return escape(f'{name}') -def _provider_source(p: Union[ProviderDisplayData, Tuple]) -> str: +def _provider_source( + p: Union[ProviderDisplayData, Tuple[Tuple[Any, Any], Sequence[ProviderDisplayData]]] +) -> str: if isinstance(p, tuple) or p.kind != 'function': return '' module = getattr(inspect.getmodule(p.value), '__name__', '') @@ -50,7 +54,9 @@ def _provider_source(p: Union[ProviderDisplayData, Tuple]) -> str: ) -def _provider_value(p: Union[ProviderDisplayData, Tuple]) -> str: +def _provider_value( + p: Union[ProviderDisplayData, Tuple[Tuple[Any, Any], Sequence[ProviderDisplayData]]] +) -> str: if isinstance(p, tuple): (name, cname), values = p return escape(f'length: {len(values)}') diff --git a/src/sciline/utils.py b/src/sciline/utils.py index 0bf821d3..bcd77c5b 100644 --- a/src/sciline/utils.py +++ b/src/sciline/utils.py @@ -12,7 +12,7 @@ def groupby(f: Callable[[T], G], a: Iterable[T]) -> DefaultDict[G, list[T]]: return g -def qualname(obj: Any) -> Any: - return ( +def qualname(obj: Any) -> str: + return str( obj.__qualname__ if hasattr(obj, '__qualname__') else obj.__class__.__qualname__ ) From b946d4bb3fd1db5bf95dd675a0bcd567aba638d5 Mon Sep 17 00:00:00 2001 From: Johannes Kasimir Date: Wed, 20 Dec 2023 15:25:11 +0100 Subject: [PATCH 05/13] fix: change order of source and value --- src/sciline/display.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sciline/display.py b/src/sciline/display.py index 483c149c..89076f1b 100644 --- a/src/sciline/display.py +++ b/src/sciline/display.py @@ -80,8 +80,8 @@ def pipeline_html_repr( f''' {_provider_name(p)} - {_provider_source(p)} {_provider_value(p)} + {_provider_source(p)} ''' for p in sorted( chain( @@ -99,8 +99,8 @@ def pipeline_html_repr( Name - Source Value + Source From 58826512f42e1425d59e3cb20f3f53dfb720e483 Mon Sep 17 00:00:00 2001 From: Johannes Kasimir Date: Wed, 3 Jan 2024 11:19:58 +0100 Subject: [PATCH 06/13] remove nested _repr_html_ of data arrays --- src/sciline/display.py | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/sciline/display.py b/src/sciline/display.py index 89076f1b..15422ace 100644 --- a/src/sciline/display.py +++ b/src/sciline/display.py @@ -45,26 +45,24 @@ def _provider_name( def _provider_source( p: Union[ProviderDisplayData, Tuple[Tuple[Any, Any], Sequence[ProviderDisplayData]]] ) -> str: - if isinstance(p, tuple) or p.kind != 'function': - return '' - module = getattr(inspect.getmodule(p.value), '__name__', '') - return _details( - escape(p.value.__name__), - escape(f'{module}.{p.value.__name__}'), - ) + if isinstance(p, tuple): + (name, cname), values = p + return escape(f'ParamTable({qualname(name)}, length={len(values)})') + if p.kind == 'function': + module = getattr(inspect.getmodule(p.value), '__name__', '') + return _details( + escape(p.value.__name__), + escape(f'{module}.{p.value.__name__}'), + ) + return '' def _provider_value( p: Union[ProviderDisplayData, Tuple[Tuple[Any, Any], Sequence[ProviderDisplayData]]] ) -> str: - if isinstance(p, tuple): - (name, cname), values = p - return escape(f'length: {len(values)}') - if p.kind != 'parameter': - return '' - if hasattr(p.value, '_repr_html_'): - return _details('', p.value._repr_html_()) - return escape(str(p.value)) + if not isinstance(p, tuple) and p.kind == 'parameter': + return escape(str(p.value)) + return '' def pipeline_html_repr( From 789390a422506d16b3bb7d13b35f8b9aa57e3203 Mon Sep 17 00:00:00 2001 From: Johannes Kasimir Date: Wed, 3 Jan 2024 11:27:34 +0100 Subject: [PATCH 07/13] display long parameter values below details tag --- src/sciline/display.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sciline/display.py b/src/sciline/display.py index 15422ace..24c6007d 100644 --- a/src/sciline/display.py +++ b/src/sciline/display.py @@ -61,7 +61,8 @@ def _provider_value( p: Union[ProviderDisplayData, Tuple[Tuple[Any, Any], Sequence[ProviderDisplayData]]] ) -> str: if not isinstance(p, tuple) and p.kind == 'parameter': - return escape(str(p.value)) + html = escape(str(p.value)) + return _details('', html) if len(html.strip()) > 40 else html return '' From 96e296ecd27622f8363f14a74f02ce3b8df5d433 Mon Sep 17 00:00:00 2001 From: Johannes Kasimir Date: Wed, 3 Jan 2024 11:32:30 +0100 Subject: [PATCH 08/13] fix: compatibility --- src/sciline/display.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sciline/display.py b/src/sciline/display.py index 24c6007d..476e6e41 100644 --- a/src/sciline/display.py +++ b/src/sciline/display.py @@ -13,7 +13,7 @@ @dataclass class ProviderDisplayData: origin: Key - args: Tuple[Key | TypeVar, ...] + args: Tuple[Union[Key, TypeVar], ...] kind: ProviderKind value: Any From 828e5e9b44576e270b9345464b17aec352f6a82e Mon Sep 17 00:00:00 2001 From: Johannes Kasimir Date: Thu, 4 Jan 2024 09:43:43 +0100 Subject: [PATCH 09/13] improve variable names --- src/sciline/pipeline.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sciline/pipeline.py b/src/sciline/pipeline.py index ee2f9dc1..738ea2ec 100644 --- a/src/sciline/pipeline.py +++ b/src/sciline/pipeline.py @@ -821,12 +821,12 @@ def __copy__(self) -> Pipeline: def _repr_html_(self) -> str: providers_without_parameters = ( - (p, tuple(), v) for p, v in self._providers.items() + (origin, tuple(), value) for origin, value in self._providers.items() ) # type: ignore[var-annotated] providers_with_parameters = ( - (p, c, v) - for p in self._subproviders - for c, v in self._subproviders[p].items() + (origin, args, value) + for origin in self._subproviders + for args, value in self._subproviders[origin].items() ) providers = groupby( lambda p: p.kind, @@ -834,8 +834,8 @@ def _repr_html_(self) -> str: ProviderDisplayData( origin, args, - k := _kind_of_provider(value), - value() if k != 'function' else value, + kind := _kind_of_provider(value), + value() if kind != 'function' else value, ) for origin, args, value in chain( providers_with_parameters, providers_without_parameters From 609456f7516ee1932745d5a54022a2624e218d6d Mon Sep 17 00:00:00 2001 From: Johannes Kasimir Date: Wed, 10 Jan 2024 11:06:52 +0100 Subject: [PATCH 10/13] fix mypy --- src/sciline/display.py | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/sciline/display.py b/src/sciline/display.py index 476e6e41..ac028151 100644 --- a/src/sciline/display.py +++ b/src/sciline/display.py @@ -2,9 +2,9 @@ from dataclasses import dataclass from html import escape from itertools import chain -from typing import Any, Literal, Mapping, Sequence, Tuple, TypeVar, Union +from typing import Any, Literal, Mapping, Optional, Sequence, Tuple, TypeVar, Union -from .typing import Key +from .typing import Item, Key from .utils import groupby, qualname ProviderKind = Literal['function', 'parameter', 'table'] @@ -27,9 +27,7 @@ def _details(summary: str, body: str) -> str: ''' -def _provider_name( - p: Union[ProviderDisplayData, Tuple[Tuple[Any, Any], Sequence[ProviderDisplayData]]] -) -> str: +def _provider_name(p: Any) -> str: if isinstance(p, tuple): (name, cname), values = p return escape(f'{qualname(cname)}({qualname(name)})') @@ -42,9 +40,7 @@ def _provider_name( return escape(f'{name}') -def _provider_source( - p: Union[ProviderDisplayData, Tuple[Tuple[Any, Any], Sequence[ProviderDisplayData]]] -) -> str: +def _provider_source(p: Any) -> str: if isinstance(p, tuple): (name, cname), values = p return escape(f'ParamTable({qualname(name)}, length={len(values)})') @@ -57,9 +53,7 @@ def _provider_source( return '' -def _provider_value( - p: Union[ProviderDisplayData, Tuple[Tuple[Any, Any], Sequence[ProviderDisplayData]]] -) -> str: +def _provider_value(p: Any) -> str: if not isinstance(p, tuple) and p.kind == 'parameter': html = escape(str(p.value)) return _details('', html) if len(html.strip()) > 40 else html @@ -69,11 +63,15 @@ def _provider_value( def pipeline_html_repr( providers: Mapping[ProviderKind, Sequence[ProviderDisplayData]] ) -> str: + def table_name_and_column_name(p: ProviderDisplayData) -> Optional[Tuple[Any, Any]]: + if isinstance(p.origin, Item): + return (p.origin.label[0].tp, p.origin.tp) + return None + param_table_columns_by_name_colname = groupby( - lambda p: (p.origin.label[0].tp, p.origin.tp), + table_name_and_column_name, providers['table'], ) - provider_rows = '\n'.join( ( f''' @@ -88,7 +86,7 @@ def pipeline_html_repr( providers['parameter'], param_table_columns_by_name_colname.items(), ), - key=lambda p: _provider_name(p), + key=_provider_name, ) ) ) From 73d6e45a76098f23d36d092888d6ded00853698e Mon Sep 17 00:00:00 2001 From: jokasimr Date: Wed, 10 Jan 2024 10:32:32 +0000 Subject: [PATCH 11/13] Apply automatic formatting --- tests/pipeline_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/pipeline_test.py b/tests/pipeline_test.py index dfec0d88..ab6061e6 100644 --- a/tests/pipeline_test.py +++ b/tests/pipeline_test.py @@ -1198,6 +1198,7 @@ def process( assert a.compute(Result) == 29 assert b.compute(Result) == 53 + def test_html_repr() -> None: pipeline = sl.Pipeline([make_int], params={float: 5.0}) assert isinstance(pipeline._repr_html_(), str) From bfad72b986374b9d709eb4480f97614b250674ab Mon Sep 17 00:00:00 2001 From: Johannes Kasimir Date: Wed, 10 Jan 2024 11:45:02 +0100 Subject: [PATCH 12/13] add 'peek' view in detail --- src/sciline/display.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sciline/display.py b/src/sciline/display.py index ac028151..2f9e8498 100644 --- a/src/sciline/display.py +++ b/src/sciline/display.py @@ -55,8 +55,8 @@ def _provider_source(p: Any) -> str: def _provider_value(p: Any) -> str: if not isinstance(p, tuple) and p.kind == 'parameter': - html = escape(str(p.value)) - return _details('', html) if len(html.strip()) > 40 else html + html = escape(str(p.value)).strip() + return _details(f'{html[:30]}...', html) if len(html) > 30 else html return '' From e25cbe882766866cf1e83813c2d47c51f8c51d4b Mon Sep 17 00:00:00 2001 From: Johannes Kasimir Date: Wed, 10 Jan 2024 16:29:02 +0100 Subject: [PATCH 13/13] test: add test with parameter table --- tests/pipeline_with_param_table_test.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/pipeline_with_param_table_test.py b/tests/pipeline_with_param_table_test.py index 385647fc..cd30699f 100644 --- a/tests/pipeline_with_param_table_test.py +++ b/tests/pipeline_with_param_table_test.py @@ -638,3 +638,9 @@ def test_pipeline_set_param_table_on_copy_does_not_affect_original() -> None: assert b.compute(sl.Series[int, float]) == sl.Series(int, {0: 1.0, 1: 2.0, 2: 3.0}) with pytest.raises(sl.UnsatisfiedRequirement): a.compute(sl.Series[int, float]) + + +def test_can_make_html_repr_with_param_table() -> None: + pl = sl.Pipeline() + pl.set_param_table(sl.ParamTable(int, {float: [1.0, 2.0, 3.0]})) + assert pl._repr_html_()