pystreamlet 0.1.0__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pystreamlet
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: A fluent, lazy stream-processing library for Python, modeled after Java's Streams API
5
5
  Keywords: stream,streams,lazy,itertools,functional,pipeline,async
6
6
  Author: 0xthreadsafe
@@ -29,7 +29,7 @@ Description-Content-Type: text/markdown
29
29
  A fluent, **lazy** stream-processing library for Python, modeled after Java's Streams API.
30
30
 
31
31
  ```python
32
- from streamlet import Stream
32
+ from pystreamlet import Stream
33
33
 
34
34
  (
35
35
  Stream.from_iterable(range(100))
@@ -47,13 +47,11 @@ The goal is to make `itertools`' power reachable through clean, chainable syntax
47
47
  pip install pystreamlet # or: uv add pystreamlet
48
48
  ```
49
49
 
50
- You install `pystreamlet` but import `streamlet`, as above — PyPI reserves names confusable with
51
- `streamlit`. Requires **Python 3.11+**, has no dependencies, and ships type information
52
- (`py.typed`).
50
+ Requires **Python 3.11+**, has no dependencies, and ships type information (`py.typed`).
53
51
 
54
- > **Status: 0.1.0, awaiting its first upload.** Everything below works and is tested; until the
55
- > release lands on PyPI, install from source (see [Development](#development)). Before 1.0.0 the
56
- > API may still change — see [versioning](#versioning).
52
+ > **Status: 0.2.0, on PyPI.** Everything below works and is tested. Before 1.0.0 the API may
53
+ > still change — see [versioning](#versioning). Coming from 0.1.0? The import moved from
54
+ > `streamlet` to `pystreamlet`, matching the install name; nothing else changed.
57
55
 
58
56
  ## Why
59
57
 
@@ -65,7 +63,7 @@ from itertools import count, islice
65
63
 
66
64
  list(islice((n**2 for n in count() if n % 2 == 0), 5))
67
65
 
68
- # streamlet: read left to right, in the order it happens
66
+ # pystreamlet: read left to right, in the order it happens
69
67
  (
70
68
  Stream.iterate(0, lambda n: n + 1)
71
69
  .filter(lambda n: n % 2 == 0)
@@ -261,7 +259,7 @@ something you opened would break the whoever-opens-closes convention.
261
259
  ```python
262
260
  import asyncio
263
261
 
264
- from streamlet import AsyncStream
262
+ from pystreamlet import AsyncStream
265
263
 
266
264
 
267
265
  async def fetch(url: str) -> str: ...
@@ -380,7 +378,7 @@ through trusted publishing, so no token lives in this repository.
380
378
  - [x] `Stream.from_file` — context-managed resource streams
381
379
  - [x] `AsyncStream` — bounded concurrent `map`
382
380
  - [x] Docstrings, README examples
383
- - [ ] PyPI release
381
+ - [x] PyPI release
384
382
 
385
383
  ## License
386
384
 
@@ -3,7 +3,7 @@
3
3
  A fluent, **lazy** stream-processing library for Python, modeled after Java's Streams API.
4
4
 
5
5
  ```python
6
- from streamlet import Stream
6
+ from pystreamlet import Stream
7
7
 
8
8
  (
9
9
  Stream.from_iterable(range(100))
@@ -21,13 +21,11 @@ The goal is to make `itertools`' power reachable through clean, chainable syntax
21
21
  pip install pystreamlet # or: uv add pystreamlet
22
22
  ```
23
23
 
24
- You install `pystreamlet` but import `streamlet`, as above — PyPI reserves names confusable with
25
- `streamlit`. Requires **Python 3.11+**, has no dependencies, and ships type information
26
- (`py.typed`).
24
+ Requires **Python 3.11+**, has no dependencies, and ships type information (`py.typed`).
27
25
 
28
- > **Status: 0.1.0, awaiting its first upload.** Everything below works and is tested; until the
29
- > release lands on PyPI, install from source (see [Development](#development)). Before 1.0.0 the
30
- > API may still change — see [versioning](#versioning).
26
+ > **Status: 0.2.0, on PyPI.** Everything below works and is tested. Before 1.0.0 the API may
27
+ > still change — see [versioning](#versioning). Coming from 0.1.0? The import moved from
28
+ > `streamlet` to `pystreamlet`, matching the install name; nothing else changed.
31
29
 
32
30
  ## Why
33
31
 
@@ -39,7 +37,7 @@ from itertools import count, islice
39
37
 
40
38
  list(islice((n**2 for n in count() if n % 2 == 0), 5))
41
39
 
42
- # streamlet: read left to right, in the order it happens
40
+ # pystreamlet: read left to right, in the order it happens
43
41
  (
44
42
  Stream.iterate(0, lambda n: n + 1)
45
43
  .filter(lambda n: n % 2 == 0)
@@ -235,7 +233,7 @@ something you opened would break the whoever-opens-closes convention.
235
233
  ```python
236
234
  import asyncio
237
235
 
238
- from streamlet import AsyncStream
236
+ from pystreamlet import AsyncStream
239
237
 
240
238
 
241
239
  async def fetch(url: str) -> str: ...
@@ -354,7 +352,7 @@ through trusted publishing, so no token lives in this repository.
354
352
  - [x] `Stream.from_file` — context-managed resource streams
355
353
  - [x] `AsyncStream` — bounded concurrent `map`
356
354
  - [x] Docstrings, README examples
357
- - [ ] PyPI release
355
+ - [x] PyPI release
358
356
 
359
357
  ## License
360
358
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pystreamlet"
3
- version = "0.1.0"
3
+ version = "0.2.0"
4
4
  description = "A fluent, lazy stream-processing library for Python, modeled after Java's Streams API"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -40,14 +40,21 @@ Changelog = "https://github.com/0xthreadsafe/streamlet/blob/main/CHANGELOG.md"
40
40
  Issues = "https://github.com/0xthreadsafe/streamlet/issues"
41
41
 
42
42
  [project.scripts]
43
- streamlet = "streamlet:main"
43
+ pystreamlet = "pystreamlet:main"
44
44
 
45
45
  [build-system]
46
46
  requires = ["uv_build>=0.10.4,<0.11.0"]
47
47
  build-backend = "uv_build"
48
48
 
49
- [tool.uv.build-backend]
50
- module-name = "streamlet"
49
+ [dependency-groups]
50
+ dev = [
51
+ "mypy>=2.3.1",
52
+ "pytest>=9.1.1",
53
+ "ruff>=0.16.6",
54
+ "hypothesis>=6.0",
55
+ "pytest-asyncio>=0.24",
56
+ "pre-commit>=4.0",
57
+ ]
51
58
 
52
59
  [tool.ruff]
53
60
  target-version = "py311"
@@ -105,13 +112,3 @@ show_error_codes = true
105
112
  [tool.pytest.ini_options]
106
113
  asyncio_mode = "auto"
107
114
  asyncio_default_fixture_loop_scope = "function"
108
-
109
- [dependency-groups]
110
- dev = [
111
- "mypy>=2.3.1",
112
- "pytest>=9.1.1",
113
- "ruff>=0.16.6",
114
- "hypothesis>=6.0",
115
- "pytest-asyncio>=0.24",
116
- "pre-commit>=4.0",
117
- ]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pystreamlet"
3
- version = "0.1.0"
3
+ version = "0.2.0"
4
4
  description = "A fluent, lazy stream-processing library for Python, modeled after Java's Streams API"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -31,17 +31,12 @@ Changelog = "https://github.com/0xthreadsafe/streamlet/blob/main/CHANGELOG.md"
31
31
  Issues = "https://github.com/0xthreadsafe/streamlet/issues"
32
32
 
33
33
  [project.scripts]
34
- streamlet = "streamlet:main"
34
+ pystreamlet = "pystreamlet:main"
35
35
 
36
36
  [build-system]
37
37
  requires = ["uv_build>=0.10.4,<0.11.0"]
38
38
  build-backend = "uv_build"
39
39
 
40
- # The distribution is pystreamlet but the module stays streamlet, so the
41
- # backend has to be told rather than inferring the path from the name.
42
- [tool.uv.build-backend]
43
- module-name = "streamlet"
44
-
45
40
  [dependency-groups]
46
41
  dev = [
47
42
  "mypy>=2.3.1",
@@ -0,0 +1,30 @@
1
+ """Streamlet — a fluent, lazy stream-processing library for Python.
2
+
3
+ Start from :class:`~pystreamlet.stream.Stream` for synchronous pipelines and
4
+ :class:`~pystreamlet.async_stream.AsyncStream` for async ones::
5
+
6
+ from pystreamlet import Stream
7
+
8
+ Stream.from_iterable(range(100)).filter(lambda n: n % 2 == 0).take(5).to_list()
9
+
10
+ :class:`~pystreamlet.file_stream.ResourceStream` (and its ``FileStream``
11
+ specialisation) covers sources that hold a resource open.
12
+ """
13
+
14
+ from pystreamlet.async_stream import AsyncStream
15
+ from pystreamlet.file_stream import ClosableIterable, FileStream, ResourceStream
16
+ from pystreamlet.stream import Stream, StreamConsumedError
17
+
18
+ __all__ = [
19
+ "AsyncStream",
20
+ "ClosableIterable",
21
+ "FileStream",
22
+ "ResourceStream",
23
+ "Stream",
24
+ "StreamConsumedError",
25
+ ]
26
+
27
+
28
+ def main() -> None:
29
+ """Entry point for the ``streamlet`` console script."""
30
+ print("Hello from pystreamlet!")
@@ -1,6 +1,6 @@
1
1
  """Lazy asynchronous streams.
2
2
 
3
- ``AsyncStream`` mirrors :class:`~streamlet.stream.Stream`, but pulls from an
3
+ ``AsyncStream`` mirrors :class:`~pystreamlet.stream.Stream`, but pulls from an
4
4
  async source and is driven with ``async for`` / ``await``. Every operation
5
5
  that takes a function accepts either a plain function or a coroutine
6
6
  function, so ``map(str)`` and ``map(fetch)`` both work.
@@ -22,7 +22,7 @@ from collections.abc import (
22
22
  from contextlib import asynccontextmanager
23
23
  from typing import Any, Generic, TypeVar, cast, overload
24
24
 
25
- from streamlet.stream import StreamConsumedError
25
+ from pystreamlet.stream import StreamConsumedError
26
26
 
27
27
  T = TypeVar("T")
28
28
  R = TypeVar("R")
@@ -91,7 +91,7 @@ class AsyncStream(Generic[T]):
91
91
 
92
92
  total = await AsyncStream.from_iterable(urls).map(fetch).count()
93
93
 
94
- Like :class:`~streamlet.stream.Stream`, a stream is consumed once;
94
+ Like :class:`~pystreamlet.stream.Stream`, a stream is consumed once;
95
95
  iterating a second time raises :class:`StreamConsumedError`.
96
96
 
97
97
  Cleanup runs eagerly: each stage closes the one behind it, so a bounded
@@ -8,7 +8,7 @@ from pathlib import Path
8
8
  from types import TracebackType
9
9
  from typing import IO, Protocol, Self, TypeVar, runtime_checkable
10
10
 
11
- from streamlet.stream import Stream
11
+ from pystreamlet.stream import Stream
12
12
 
13
13
  T = TypeVar("T")
14
14
  T_co = TypeVar("T_co", covariant=True)
@@ -16,7 +16,7 @@ from os import PathLike
16
16
  from typing import TYPE_CHECKING, Any, Generic, TypeVar, overload
17
17
 
18
18
  if TYPE_CHECKING:
19
- from streamlet.file_stream import ClosableIterable, FileStream, ResourceStream
19
+ from pystreamlet.file_stream import ClosableIterable, FileStream, ResourceStream
20
20
 
21
21
  T = TypeVar("T")
22
22
  R = TypeVar("R")
@@ -95,7 +95,7 @@ class Stream(Generic[T]):
95
95
  ) -> FileStream:
96
96
  """Stream the lines of a file, closing the handle when done.
97
97
 
98
- Returns a :class:`~streamlet.file_stream.FileStream`, which closes the
98
+ Returns a :class:`~pystreamlet.file_stream.FileStream`, which closes the
99
99
  handle on every exit path and is also a context manager::
100
100
 
101
101
  with Stream.from_file("app.log") as lines:
@@ -103,7 +103,7 @@ class Stream(Generic[T]):
103
103
 
104
104
  Lines keep their trailing newline, matching ``open()``.
105
105
  """
106
- from streamlet.file_stream import open_file_stream
106
+ from pystreamlet.file_stream import open_file_stream
107
107
 
108
108
  return open_file_stream(path, encoding=encoding, errors=errors, newline=newline)
109
109
 
@@ -136,7 +136,7 @@ class Stream(Generic[T]):
136
136
  TypeError: if the handle has no ``close()`` method.
137
137
 
138
138
  """
139
- from streamlet.file_stream import resource_stream
139
+ from pystreamlet.file_stream import resource_stream
140
140
 
141
141
  return resource_stream(handle, close=close)
142
142
 
@@ -1,30 +0,0 @@
1
- """Streamlet — a fluent, lazy stream-processing library for Python.
2
-
3
- Start from :class:`~streamlet.stream.Stream` for synchronous pipelines and
4
- :class:`~streamlet.async_stream.AsyncStream` for async ones::
5
-
6
- from streamlet import Stream
7
-
8
- Stream.from_iterable(range(100)).filter(lambda n: n % 2 == 0).take(5).to_list()
9
-
10
- :class:`~streamlet.file_stream.ResourceStream` (and its ``FileStream``
11
- specialisation) covers sources that hold a resource open.
12
- """
13
-
14
- from streamlet.async_stream import AsyncStream
15
- from streamlet.file_stream import ClosableIterable, FileStream, ResourceStream
16
- from streamlet.stream import Stream, StreamConsumedError
17
-
18
- __all__ = [
19
- "AsyncStream",
20
- "ClosableIterable",
21
- "FileStream",
22
- "ResourceStream",
23
- "Stream",
24
- "StreamConsumedError",
25
- ]
26
-
27
-
28
- def main() -> None:
29
- """Entry point for the ``streamlet`` console script."""
30
- print("Hello from streamlet!")
File without changes