|
21 | 21 | "metadata": {}, |
22 | 22 | "outputs": [], |
23 | 23 | "source": [ |
24 | | - "\"\"\"Minimal imports.\"\"\"\n", |
| 24 | + "\"\"\"Minimal imports to get started.\"\"\"\n", |
25 | 25 | "\n", |
26 | | - "from typing import NewType\n", |
27 | | - "from upath import UPath\n", |
| 26 | + "from fsspec import AbstractFileSystem\n", |
28 | 27 | "from pydantic import BaseModel, ConfigDict\n", |
29 | 28 | "from pydantic_cereal import Cereal\n", |
30 | 29 | "\n", |
|
35 | 34 | "cell_type": "markdown", |
36 | 35 | "metadata": {}, |
37 | 36 | "source": [ |
38 | | - "We have a custom type `MyType`, in this case it's just an alias for `str`:" |
| 37 | + "We have a custom type `MyType`, in this case it's just an wrapper for a `str`:" |
39 | 38 | ] |
40 | 39 | }, |
41 | 40 | { |
|
44 | 43 | "metadata": {}, |
45 | 44 | "outputs": [], |
46 | 45 | "source": [ |
47 | | - "MyType = NewType(\"MyType\", str) # actually `str`, but type checker has special semantics " |
| 46 | + "class MyType(object):\n", |
| 47 | + " \"\"\"My custom type, which isn't a Pydantic model.\"\"\"\n", |
| 48 | + "\n", |
| 49 | + " def __init__(self, value: str):\n", |
| 50 | + " \"\"\"Initialize the object.\"\"\"\n", |
| 51 | + " self.value = str(value)\n", |
| 52 | + "\n", |
| 53 | + " def __repr__(self) -> str:\n", |
| 54 | + " \"\"\"Represent the string.\"\"\"\n", |
| 55 | + " return f\"MyType({self.value})\"\n", |
| 56 | + "\n", |
| 57 | + " def __str__(self) -> str:\n", |
| 58 | + " \"\"\"Return the internal string.\"\"\"\n", |
| 59 | + " return str(self.value)" |
48 | 60 | ] |
49 | 61 | }, |
50 | 62 | { |
51 | 63 | "cell_type": "markdown", |
52 | 64 | "metadata": {}, |
53 | 65 | "source": [ |
54 | 66 | "We must add reader and writer classes for it. \n", |
55 | | - "These must accept [`fsspec`](https://filesystem-spec.readthedocs.io/en/latest/) URIs as inputs.\n", |
| 67 | + "These must accept [`fsspec`](https://filesystem-spec.readthedocs.io/en/latest/) file system\n", |
| 68 | + "and path (within that filesystem) as inputs.\n", |
56 | 69 | "We can register these with our `cereal` object by creating a wrapped (`Annotated`) type." |
57 | 70 | ] |
58 | 71 | }, |
|
62 | 75 | "metadata": {}, |
63 | 76 | "outputs": [], |
64 | 77 | "source": [ |
65 | | - "def my_reader(uri: str) -> MyType:\n", |
66 | | - " \"\"\"Read the object from an fsspec URI.\"\"\"\n", |
67 | | - " return MyType(UPath(uri).read_text())\n", |
| 78 | + "def my_reader(fs: AbstractFileSystem, path: str) -> MyType:\n", |
| 79 | + " \"\"\"Read a MyType from an fsspec URI.\"\"\"\n", |
| 80 | + " res = fs.read_text(path)\n", |
| 81 | + " if isinstance(res, bytes):\n", |
| 82 | + " res = res.decode(\"utf8\")\n", |
| 83 | + " else:\n", |
| 84 | + " res = str(res)\n", |
| 85 | + " return MyType(value=res)\n", |
| 86 | + "\n", |
| 87 | + "\n", |
| 88 | + "def my_writer(obj: MyType, fs: AbstractFileSystem, path: str) -> None:\n", |
| 89 | + " \"\"\"Write a MyType object to an fsspec URI.\"\"\"\n", |
| 90 | + " fs.write_text(path, obj.value)\n", |
68 | 91 | "\n", |
69 | | - "def my_writer(obj: MyType, uri: str) -> None:\n", |
70 | | - " \"\"\"Write the object to an fsspec URI.\"\"\"\n", |
71 | | - " UPath(uri).write_text(obj)\n", |
72 | 92 | "\n", |
73 | 93 | "MyWrappedType = cereal.wrap_type(MyType, reader=my_reader, writer=my_writer)" |
74 | 94 | ] |
|
145 | 165 | { |
146 | 166 | "data": { |
147 | 167 | "text/plain": [ |
148 | | - "MemoryPath('memory://example_model/')" |
| 168 | + "'/example_model'" |
149 | 169 | ] |
150 | 170 | }, |
151 | 171 | "execution_count": 7, |
|
172 | 192 | { |
173 | 193 | "data": { |
174 | 194 | "text/plain": [ |
175 | | - "'my_field'" |
| 195 | + "MyType(my_field)" |
176 | 196 | ] |
177 | 197 | }, |
178 | 198 | "execution_count": 8, |
|
201 | 221 | { |
202 | 222 | "data": { |
203 | 223 | "text/plain": [ |
204 | | - "'my_field'" |
| 224 | + "MyType(my_field)" |
205 | 225 | ] |
206 | 226 | }, |
207 | 227 | "execution_count": 9, |
|
224 | 244 | "cell_type": "code", |
225 | 245 | "execution_count": 10, |
226 | 246 | "metadata": {}, |
| 247 | + "outputs": [], |
| 248 | + "source": [ |
| 249 | + "from fsspec.implementations.memory import MemoryFileSystem # noqa" |
| 250 | + ] |
| 251 | + }, |
| 252 | + { |
| 253 | + "cell_type": "code", |
| 254 | + "execution_count": 11, |
| 255 | + "metadata": {}, |
| 256 | + "outputs": [], |
| 257 | + "source": [ |
| 258 | + "fs = MemoryFileSystem()" |
| 259 | + ] |
| 260 | + }, |
| 261 | + { |
| 262 | + "cell_type": "code", |
| 263 | + "execution_count": 12, |
| 264 | + "metadata": {}, |
227 | 265 | "outputs": [ |
228 | 266 | { |
229 | 267 | "data": { |
230 | 268 | "text/plain": [ |
231 | | - "[MemoryPath('memory://example_model/51c07fc879fa403993ba780d9ff29b52'),\n", |
232 | | - " MemoryPath('memory://example_model/model.json'),\n", |
233 | | - " MemoryPath('memory://example_model/model.schema.json')]" |
| 269 | + "['/example_model/9048f517f71f434aad4a5481f3b2b3d4',\n", |
| 270 | + " '/example_model/model.json',\n", |
| 271 | + " '/example_model/model.schema.json']" |
234 | 272 | ] |
235 | 273 | }, |
236 | | - "execution_count": 10, |
| 274 | + "execution_count": 12, |
237 | 275 | "metadata": {}, |
238 | 276 | "output_type": "execute_result" |
239 | 277 | } |
240 | 278 | ], |
241 | 279 | "source": [ |
242 | | - "list(UPath(\"memory://example_model\").glob(\"*\"))" |
| 280 | + "fs.glob(\"example_model/*\")" |
243 | 281 | ] |
244 | 282 | }, |
245 | 283 | { |
|
0 commit comments