Skip to content

Commit 7f401c5

Browse files
authored
Merge pull request #13 from Textualize/open-url
Open url
2 parents 433be4d + a5035ac commit 7f401c5

File tree

10 files changed

+334
-258
lines changed

10 files changed

+334
-258
lines changed

.python-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.12.3
1+
3.8.19

examples/dictionary.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from textual.widgets import Input, Markdown
1313

1414

15-
class DictionaryApp(App):
15+
class DictionaryApp(App[None]):
1616
"""Searches a dictionary API as-you-type."""
1717

1818
CSS_PATH = "dictionary.tcss"

examples/open_link.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from textual import on
2+
from textual.app import App, ComposeResult
3+
from textual.widgets import Button
4+
5+
6+
class OpenLink(App[None]):
7+
"""Demonstrates opening a URL in the same tab or a new tab."""
8+
9+
def compose(self) -> ComposeResult:
10+
yield Button("Visit the Textual docs", id="open-link-same-tab")
11+
yield Button("Visit the Textual docs in a new tab", id="open-link-new-tab")
12+
13+
@on(Button.Pressed)
14+
def open_link(self, event: Button.Pressed) -> None:
15+
"""Open the URL in the same tab or a new tab depending on which button was pressed."""
16+
self.open_url(
17+
"https://textual.textualize.io",
18+
new_tab=event.button.id == "open-link-new-tab",
19+
)
20+
21+
22+
app = OpenLink()
23+
if __name__ == "__main__":
24+
app.run()

examples/serve_any.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import sys
2+
from textual_serve.server import Server
3+
4+
if __name__ == "__main__":
5+
server = Server(sys.argv[1])
6+
server.serve(debug=False)

examples/serve_open_link.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from textual_serve.server import Server
2+
3+
server = Server("python open_link.py")
4+
server.serve(debug=False)

pyproject.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ authors = [
66
{ name = "Will McGugan", email = "[email protected]" }
77
]
88
dependencies = [
9-
"textual>=0.66.0",
109
"aiohttp>=3.9.5",
1110
"aiohttp-jinja2>=1.6",
1211
"jinja2>=3.1.4",
12+
"textual>=0.66.0",
1313
]
1414
readme = "README.md"
1515
requires-python = ">= 3.8"
@@ -20,7 +20,9 @@ build-backend = "hatchling.build"
2020

2121
[tool.rye]
2222
managed = true
23-
dev-dependencies = []
23+
dev-dependencies = [
24+
"httpx", # required to run the dictionary example
25+
]
2426

2527
[tool.hatch.metadata]
2628
allow-direct-references = true

requirements-dev.lock

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,28 @@ aiohttp-jinja2==1.6
1616
# via textual-serve
1717
aiosignal==1.3.1
1818
# via aiohttp
19+
anyio==4.4.0
20+
# via httpx
21+
async-timeout==4.0.3
22+
# via aiohttp
1923
attrs==23.2.0
2024
# via aiohttp
25+
certifi==2024.7.4
26+
# via httpcore
27+
# via httpx
28+
exceptiongroup==1.2.2
29+
# via anyio
2130
frozenlist==1.4.1
2231
# via aiohttp
2332
# via aiosignal
33+
h11==0.14.0
34+
# via httpcore
35+
httpcore==1.0.5
36+
# via httpx
37+
httpx==0.27.0
2438
idna==3.7
39+
# via anyio
40+
# via httpx
2541
# via yarl
2642
jinja2==3.1.4
2743
# via aiohttp-jinja2
@@ -45,9 +61,14 @@ pygments==2.18.0
4561
# via rich
4662
rich==13.7.1
4763
# via textual
48-
textual==0.66.0
64+
sniffio==1.3.1
65+
# via anyio
66+
# via httpx
67+
textual==0.74.0
4968
# via textual-serve
5069
typing-extensions==4.12.2
70+
# via anyio
71+
# via rich
5172
# via textual
5273
uc-micro-py==1.0.3
5374
# via linkify-it-py

requirements.lock

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ aiohttp-jinja2==1.6
1616
# via textual-serve
1717
aiosignal==1.3.1
1818
# via aiohttp
19+
async-timeout==4.0.3
20+
# via aiohttp
1921
attrs==23.2.0
2022
# via aiohttp
2123
frozenlist==1.4.1
@@ -45,9 +47,10 @@ pygments==2.18.0
4547
# via rich
4648
rich==13.7.1
4749
# via textual
48-
textual==0.66.0
50+
textual==0.74.0
4951
# via textual-serve
5052
typing-extensions==4.12.2
53+
# via rich
5154
# via textual
5255
uc-micro-py==1.0.3
5356
# via linkify-it-py

src/textual_serve/app_service.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ def __init__(
2323
self,
2424
command: str,
2525
*,
26-
write_bytes: Callable[[bytes], Awaitable],
27-
write_str: Callable[[str], Awaitable],
28-
close: Callable[[], Awaitable],
26+
write_bytes: Callable[[bytes], Awaitable[None]],
27+
write_str: Callable[[str], Awaitable[None]],
28+
close: Callable[[], Awaitable[None]],
2929
debug: bool = False,
3030
) -> None:
3131
self.command = command
@@ -35,7 +35,7 @@ def __init__(
3535
self.debug = debug
3636

3737
self._process: Process | None = None
38-
self._task: asyncio.Task | None = None
38+
self._task: asyncio.Task[None] | None = None
3939
self._stdin: asyncio.StreamWriter | None = None
4040
self._exit_event = asyncio.Event()
4141

@@ -268,7 +268,23 @@ async def on_meta(self, data: bytes) -> None:
268268
Args:
269269
data: Encoded meta data.
270270
"""
271-
meta_data = json.loads(data)
271+
meta_data: dict[str, object] = json.loads(data)
272+
meta_type = meta_data["type"]
272273

273-
if meta_data["type"] == "exit":
274+
if meta_type == "exit":
274275
await self.remote_close()
276+
elif meta_type == "open_url":
277+
payload = json.dumps(
278+
[
279+
"open_url",
280+
{
281+
"url": meta_data["url"],
282+
"new_tab": meta_data["new_tab"],
283+
},
284+
]
285+
)
286+
await self.remote_write_str(payload)
287+
else:
288+
log.warning(
289+
f"Unknown meta type: {meta_type!r}. You may need to update `textual-serve`."
290+
)

0 commit comments

Comments
 (0)