diff --git a/Makefile b/Makefile index 3898e94b709..e60eef2bde0 100644 --- a/Makefile +++ b/Makefile @@ -72,11 +72,12 @@ py-test: cd marimo && typos && cd - && hatch run +py=3.12 test-optional:test .PHONY: py-snapshots -# update html snapshots +# update snapshots py-snapshots: hatch run +py=3.12 test:test \ tests/_server/templates/test_templates.py \ - tests/_server/api/endpoints/test_export.py + tests/_server/api/endpoints/test_export.py \ + tests/test_api.py .PHONY: install-all # install everything; takes a long time due to editable install diff --git a/marimo/__init__.py b/marimo/__init__.py index 9d87b0b70c9..e63d7e6b105 100644 --- a/marimo/__init__.py +++ b/marimo/__init__.py @@ -14,8 +14,6 @@ 5. fun """ -from __future__ import annotations - __all__ = [ # Core API "App", @@ -90,7 +88,7 @@ import marimo._islands as islands from marimo._ast.app import App from marimo._ast.cell import Cell -from marimo._islands.island_generator import MarimoIslandGenerator +from marimo._islands._island_generator import MarimoIslandGenerator from marimo._output.doc import doc from marimo._output.formatting import as_html, iframe, plain from marimo._output.hypertext import Html diff --git a/marimo/_ai/__init__.py b/marimo/_ai/__init__.py index 4334a8d3567..88844f85f06 100644 --- a/marimo/_ai/__init__.py +++ b/marimo/_ai/__init__.py @@ -1,8 +1,6 @@ # Copyright 2024 Marimo. All rights reserved. """AI utilities.""" -from __future__ import annotations - __all__ = [ "ChatMessage", "ChatModelConfig", @@ -10,8 +8,8 @@ "llm", ] -from marimo._ai import llm -from marimo._ai.types import ( +import marimo._ai.llm as llm +from marimo._ai._types import ( ChatAttachment, ChatMessage, ChatModelConfig, diff --git a/marimo/_ai/convert.py b/marimo/_ai/_convert.py similarity index 99% rename from marimo/_ai/convert.py rename to marimo/_ai/_convert.py index d23f014f3e7..0ed2211d01a 100644 --- a/marimo/_ai/convert.py +++ b/marimo/_ai/_convert.py @@ -4,7 +4,7 @@ import base64 from typing import Any, Dict, List, TypedDict -from marimo._ai.types import ChatMessage +from marimo._ai._types import ChatMessage def convert_to_openai_messages( diff --git a/marimo/_ai/types.py b/marimo/_ai/_types.py similarity index 100% rename from marimo/_ai/types.py rename to marimo/_ai/_types.py diff --git a/marimo/_ai/llm/__init__.py b/marimo/_ai/llm/__init__.py new file mode 100644 index 00000000000..a42bdf1fe3f --- /dev/null +++ b/marimo/_ai/llm/__init__.py @@ -0,0 +1,3 @@ +from marimo._ai.llm._impl import anthropic, google, groq, openai + +__all__ = ["openai", "anthropic", "google", "groq"] diff --git a/marimo/_ai/llm.py b/marimo/_ai/llm/_impl.py similarity index 99% rename from marimo/_ai/llm.py rename to marimo/_ai/llm/_impl.py index 5371676d02e..a3b4eeb5c0f 100644 --- a/marimo/_ai/llm.py +++ b/marimo/_ai/llm/_impl.py @@ -4,13 +4,13 @@ import os from typing import Callable, List, Optional, cast -from marimo._ai.convert import ( +from marimo._ai._convert import ( convert_to_anthropic_messages, convert_to_google_messages, convert_to_groq_messages, convert_to_openai_messages, ) -from marimo._ai.types import ( +from marimo._ai._types import ( ChatMessage, ChatModel, ChatModelConfig, diff --git a/marimo/_islands/__init__.py b/marimo/_islands/__init__.py index 92fba771d57..93169d35985 100644 --- a/marimo/_islands/__init__.py +++ b/marimo/_islands/__init__.py @@ -1,12 +1,10 @@ # Copyright 2024 Marimo. All rights reserved. -from __future__ import annotations - __all__ = [ "MarimoIslandGenerator", "MarimoIslandStub", ] -from marimo._islands.island_generator import ( +from marimo._islands._island_generator import ( MarimoIslandGenerator, MarimoIslandStub, ) diff --git a/marimo/_islands/island_generator.py b/marimo/_islands/_island_generator.py similarity index 100% rename from marimo/_islands/island_generator.py rename to marimo/_islands/_island_generator.py diff --git a/marimo/_plugins/ui/__init__.py b/marimo/_plugins/ui/__init__.py index 1ab60c9ceff..5c62eec343a 100644 --- a/marimo/_plugins/ui/__init__.py +++ b/marimo/_plugins/ui/__init__.py @@ -4,8 +4,6 @@ This module contains a library of interactive UI elements. """ -from __future__ import annotations - __all__ = [ "altair_chart", "anywidget", diff --git a/marimo/_plugins/ui/_impl/chat/chat.py b/marimo/_plugins/ui/_impl/chat/chat.py index a988ad5159b..4169cd979c5 100644 --- a/marimo/_plugins/ui/_impl/chat/chat.py +++ b/marimo/_plugins/ui/_impl/chat/chat.py @@ -5,7 +5,7 @@ from dataclasses import dataclass from typing import Any, Callable, Dict, Final, List, Optional, Union, cast -from marimo._ai.types import ( +from marimo._ai._types import ( ChatMessage, ChatModelConfig, ChatModelConfigDict, diff --git a/marimo/_plugins/ui/_impl/chat/utils.py b/marimo/_plugins/ui/_impl/chat/utils.py index 984f21346ca..a0e3a844a51 100644 --- a/marimo/_plugins/ui/_impl/chat/utils.py +++ b/marimo/_plugins/ui/_impl/chat/utils.py @@ -3,7 +3,7 @@ from typing import List, Optional -from marimo._ai.types import ( +from marimo._ai._types import ( ChatAttachment, ChatMessage, ChatMessageDict, diff --git a/marimo/_server/api/endpoints/ai.py b/marimo/_server/api/endpoints/ai.py index 7bfea9eba25..c2708df7134 100644 --- a/marimo/_server/api/endpoints/ai.py +++ b/marimo/_server/api/endpoints/ai.py @@ -8,12 +8,12 @@ from starlette.responses import StreamingResponse from marimo import _loggers -from marimo._ai.convert import ( +from marimo._ai._convert import ( convert_to_anthropic_messages, convert_to_google_messages, convert_to_openai_messages, ) -from marimo._ai.types import ChatMessage +from marimo._ai._types import ChatMessage from marimo._config.config import MarimoConfig from marimo._server.ai.prompts import Prompter from marimo._server.api.deps import AppState diff --git a/marimo/_server/export/__init__.py b/marimo/_server/export/__init__.py index 63c79c81934..c4010e86222 100644 --- a/marimo/_server/export/__init__.py +++ b/marimo/_server/export/__init__.py @@ -184,7 +184,7 @@ async def run_app_then_export_as_reactive_html( ) -> ExportResult: import os - from marimo._islands.island_generator import MarimoIslandGenerator + from marimo._islands._island_generator import MarimoIslandGenerator generator = MarimoIslandGenerator.from_file( path.absolute_name, display_code=include_code diff --git a/marimo/_server/models/completion.py b/marimo/_server/models/completion.py index fff3eb4a327..1ee2b6fc95c 100644 --- a/marimo/_server/models/completion.py +++ b/marimo/_server/models/completion.py @@ -4,7 +4,7 @@ from dataclasses import dataclass, field from typing import Any, List, Literal, Optional -from marimo._ai.types import ChatMessage +from marimo._ai._types import ChatMessage @dataclass diff --git a/pyproject.toml b/pyproject.toml index bb4600f1756..883ead46270 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -319,6 +319,7 @@ ignore = [ "PT011", # `pytest.raises(ValueError)` is too broad, set the `match` parameter or use a more specific exception "E501", # Line too long, we still trim "D415", # First line should end with a period, question mark, or exclamation point + "FA102", # Use `from __future__ import annotations` ] extend-select = [ # pyflakes diff --git a/tests/_ai/test_chat_convert.py b/tests/_ai/test_chat_convert.py index 4c4bd040685..769868df7a9 100644 --- a/tests/_ai/test_chat_convert.py +++ b/tests/_ai/test_chat_convert.py @@ -5,13 +5,13 @@ import pytest -from marimo._ai.convert import ( +from marimo._ai._convert import ( convert_to_anthropic_messages, convert_to_google_messages, convert_to_groq_messages, convert_to_openai_messages, ) -from marimo._ai.types import ( +from marimo._ai._types import ( ChatAttachment, ChatMessage, ) diff --git a/tests/_ai/test_chat_model.py b/tests/_ai/test_chat_model.py index 4e5179c7b4e..14a262cfc3b 100644 --- a/tests/_ai/test_chat_model.py +++ b/tests/_ai/test_chat_model.py @@ -1,7 +1,7 @@ from __future__ import annotations -from marimo._ai.llm import simple -from marimo._ai.types import ChatMessage, ChatModelConfig +from marimo._ai._types import ChatMessage, ChatModelConfig +from marimo._ai.llm._impl import simple def test_simple_model(): diff --git a/tests/_islands/test_island_generator.py b/tests/_islands/test_island_generator.py index 28f37febfb0..c873889f31a 100644 --- a/tests/_islands/test_island_generator.py +++ b/tests/_islands/test_island_generator.py @@ -6,7 +6,7 @@ from marimo import __version__ from marimo._ast.app import _AppConfig -from marimo._islands.island_generator import ( +from marimo._islands._island_generator import ( MarimoIslandGenerator, ) from tests.mocks import snapshotter diff --git a/tests/_plugins/ui/_impl/chat/test_chat.py b/tests/_plugins/ui/_impl/chat/test_chat.py index 16a946ab9e9..26b4c980fd6 100644 --- a/tests/_plugins/ui/_impl/chat/test_chat.py +++ b/tests/_plugins/ui/_impl/chat/test_chat.py @@ -6,7 +6,7 @@ import pytest -from marimo._ai.types import ( +from marimo._ai._types import ( ChatMessage, ChatModelConfig, ChatModelConfigDict, diff --git a/tests/snapshots/api.txt b/tests/snapshots/api.txt new file mode 100644 index 00000000000..31b5951d442 --- /dev/null +++ b/tests/snapshots/api.txt @@ -0,0 +1,114 @@ +App +Cell +Html +MarimoIslandGenerator +MarimoStopError +Thread +accordion +ai + ChatAttachment + ChatMessage + ChatModelConfig + llm + anthropic + google + groq + openai +app_meta +as_html +audio +cache +callout +capture_stderr +capture_stdout +carousel +center +cli_args +create_asgi_app +defs +doc +download +hstack +icon +iframe +image +islands + MarimoIslandGenerator + MarimoIslandStub +latex +lazy +left +lru_cache +md +mermaid +mpl + interactive +nav_menu +notebook_dir +notebook_location +output + append + clear + replace + replace_at_index +pdf +persistent_cache +plain +plain_text +query_params +redirect_stderr +redirect_stdout +refs +right +routes +running_in_notebook +show_code +sidebar +sql +stat +state +status + progress_bar + spinner + toast +stop +style +tabs +tree +ui + altair_chart + anywidget + array + batch + button + chat + checkbox + code_editor + data_explorer + dataframe + date + date_range + datetime + dictionary + dropdown + experimental_data_editor + file + file_browser + form + microphone + multiselect + number + panel + plotly + radio + range_slider + refresh + run_button + slider + switch + table + tabs + text + text_area +video +vstack \ No newline at end of file diff --git a/tests/test_api.py b/tests/test_api.py new file mode 100644 index 00000000000..d47d1d344f5 --- /dev/null +++ b/tests/test_api.py @@ -0,0 +1,57 @@ +from __future__ import annotations + +import inspect +from typing import Any, Optional, Set + +from tests.mocks import snapshotter + +snapshot = snapshotter(__file__) + + +def _explore_module( + module: Any, indent: int = 0, visited: Optional[Set[int]] = None +) -> list[str]: + """ + Recursively explore a module and print all public exported items. + + Args: + module: The module or object to explore + indent: Current indentation level (for pretty printing) + visited: Set[int] = set() + """ + if visited is None: + visited = set() + + # Skip if we've already visited this object + if id(module) in visited: + return [] + + visited.add(id(module)) + + results: list[str] = [] + # Get all attributes of the module + for name, obj in inspect.getmembers(module): + # Skip private/special attributes (starting with _) + if name.startswith("_"): + continue + + # Create indentation string + indent_str = " " * indent + + # Print the current item + results.append(f"{indent_str}{name}") + + # Recursively explore if it's a module, class, or other container type + if inspect.ismodule(obj) and obj.__name__.startswith(module.__name__): + # Only recurse into submodules of the original module + results.extend(_explore_module(obj, indent + 1, visited)) + + return results + + +def test_api(): + import marimo as mo + + results = _explore_module(mo) + assert len(results) > 0 + snapshot("api.txt", "\n".join(results))