1
1
from __future__ import annotations
2
2
3
- from dataclasses import dataclass
4
3
from typing import (
5
4
Protocol ,
6
5
Dict ,
10
9
Union ,
11
10
Callable ,
12
11
MutableMapping ,
13
- TypeAlias ,
14
12
)
15
13
import uuid
16
14
19
17
import numpy as np
20
18
import pandas as pd
21
19
20
+ from .description import Desc , desc_like
21
+
22
22
from typing import TYPE_CHECKING
23
23
24
24
if TYPE_CHECKING :
@@ -33,123 +33,6 @@ def __sub__(self, other) -> "_MatplotlibTransform":
33
33
...
34
34
35
35
36
- ShapeSpec : TypeAlias = Tuple [Union [str , int ], ...]
37
-
38
-
39
- @dataclass (frozen = True )
40
- class Desc :
41
- # TODO: sort out how to actually spell this. We need to know:
42
- # - what the number of dimensions is (1d vs 2d vs ...)
43
- # - is this a fixed size dimension (e.g. 2 for xextent)
44
- # - is this a variable size depending on the query (e.g. N)
45
- # - what is the relative size to the other variable values (N vs N+1)
46
- # We are probably going to have to implement a DSL for this (😞)
47
- shape : ShapeSpec
48
- dtype : np .dtype
49
- coordinates : str = "naive"
50
-
51
- @staticmethod
52
- def validate_shapes (
53
- specification : dict [str , ShapeSpec | "Desc" ],
54
- actual : dict [str , ShapeSpec | "Desc" ],
55
- * ,
56
- broadcast : bool = False ,
57
- ) -> None :
58
- """Validate specified shape relationships against a provided set of shapes.
59
-
60
- Shapes provided are tuples of int | str. If a specification calls for an int,
61
- the exact size is expected.
62
- If it is a str, it must be a single capital letter optionally followed by ``+``
63
- or ``-`` an integer value.
64
- The same letter used in the specification must represent the same value in all
65
- appearances. The value may, however, be a variable (with an offset) in the
66
- actual shapes (which does not need to have the same letter).
67
-
68
- Shapes may be provided as raw tuples or as ``Desc`` objects.
69
-
70
- Parameters
71
- ----------
72
- specification: dict[str, ShapeSpec | "Desc"]
73
- The desired shape relationships
74
- actual: dict[str, ShapeSpec | "Desc"]
75
- The shapes to test for compliance
76
-
77
- Keyword Parameters
78
- ------------------
79
- broadcast: bool
80
- Whether to allow broadcasted shapes to pass (i.e. actual shapes with a ``1``
81
- will not cause exceptions regardless of what the specified shape value is)
82
-
83
- Raises
84
- ------
85
- KeyError:
86
- If a required field from the specification is missing in the provided actual
87
- values.
88
- ValueError:
89
- If shapes are incompatible in any other way
90
- """
91
- specvars : dict [str , int | tuple [str , int ]] = {}
92
- for fieldname in specification :
93
- spec = specification [fieldname ]
94
- if fieldname not in actual :
95
- raise KeyError (
96
- f"Actual is missing { fieldname !r} , required by specification."
97
- )
98
- desc = actual [fieldname ]
99
- if isinstance (spec , Desc ):
100
- spec = spec .shape
101
- if isinstance (desc , Desc ):
102
- desc = desc .shape
103
- if not broadcast :
104
- if len (spec ) != len (desc ):
105
- raise ValueError (
106
- f"{ fieldname !r} shape { desc } incompatible with specification "
107
- f"{ spec } ."
108
- )
109
- elif len (desc ) > len (spec ):
110
- raise ValueError (
111
- f"{ fieldname !r} shape { desc } incompatible with specification "
112
- f"{ spec } ."
113
- )
114
- for speccomp , desccomp in zip (spec [::- 1 ], desc [::- 1 ]):
115
- if broadcast and desccomp == 1 :
116
- continue
117
- if isinstance (speccomp , str ):
118
- specv , specoff = speccomp [0 ], int (speccomp [1 :] or 0 )
119
-
120
- if isinstance (desccomp , str ):
121
- descv , descoff = desccomp [0 ], int (desccomp [1 :] or 0 )
122
- entry = (descv , descoff - specoff )
123
- else :
124
- entry = desccomp - specoff
125
-
126
- if specv in specvars and entry != specvars [specv ]:
127
- raise ValueError (f"Found two incompatible values for { specv !r} " )
128
-
129
- specvars [specv ] = entry
130
- elif speccomp != desccomp :
131
- raise ValueError (
132
- f"{ fieldname !r} shape { desc } incompatible with specification "
133
- f"{ spec } "
134
- )
135
- return None
136
-
137
- @staticmethod
138
- def compatible (a : dict [str , Desc ], b : dict [str , Desc ]) -> bool :
139
- """Determine if ``a`` is a valid input for ``b``.
140
-
141
- Note: ``a`` _may_ have additional keys.
142
- """
143
- try :
144
- Desc .validate_shapes (b , a )
145
- except (KeyError , ValueError ):
146
- return False
147
- for k , v in b .items ():
148
- if a [k ].coordinates != v .coordinates :
149
- return False
150
- return True
151
-
152
-
153
36
class DataContainer (Protocol ):
154
37
def query (
155
38
self ,
@@ -184,6 +67,7 @@ def query(
184
67
This is a key that clients can use to cache down-stream
185
68
computations on this data.
186
69
"""
70
+ ...
187
71
188
72
def describe (self ) -> Dict [str , Desc ]:
189
73
"""
@@ -193,6 +77,7 @@ def describe(self) -> Dict[str, Desc]:
193
77
-------
194
78
Dict[str, Desc]
195
79
"""
80
+ ...
196
81
197
82
198
83
class NoNewKeys (ValueError ):
@@ -312,73 +197,16 @@ def query(
312
197
# if hash_key in self._cache:
313
198
# return self._cache[hash_key], hash_key
314
199
200
+ desc = Desc (("N" ,), np .dtype ("f8" ))
201
+ xy = {"x" : desc , "y" : desc }
315
202
data_lim = graph .evaluator (
316
- {
317
- "x" : Desc (
318
- ("N" ,),
319
- np .dtype (
320
- "f8" ,
321
- ),
322
- coordinates = "data" ,
323
- ),
324
- "y" : Desc (
325
- ("N" ,),
326
- np .dtype (
327
- "f8" ,
328
- ),
329
- coordinates = "data" ,
330
- ),
331
- },
332
- {
333
- "x" : Desc (
334
- ("N" ,),
335
- np .dtype (
336
- "f8" ,
337
- ),
338
- coordinates = parent_coordinates ,
339
- ),
340
- "y" : Desc (
341
- ("N" ,),
342
- np .dtype (
343
- "f8" ,
344
- ),
345
- coordinates = parent_coordinates ,
346
- ),
347
- },
203
+ desc_like (xy , coordinates = "data" ),
204
+ desc_like (xy , coordinates = parent_coordinates ),
348
205
).inverse
206
+
349
207
screen_size = graph .evaluator (
350
- {
351
- "x" : Desc (
352
- ("N" ,),
353
- np .dtype (
354
- "f8" ,
355
- ),
356
- coordinates = parent_coordinates ,
357
- ),
358
- "y" : Desc (
359
- ("N" ,),
360
- np .dtype (
361
- "f8" ,
362
- ),
363
- coordinates = parent_coordinates ,
364
- ),
365
- },
366
- {
367
- "x" : Desc (
368
- ("N" ,),
369
- np .dtype (
370
- "f8" ,
371
- ),
372
- coordinates = "display" ,
373
- ),
374
- "y" : Desc (
375
- ("N" ,),
376
- np .dtype (
377
- "f8" ,
378
- ),
379
- coordinates = "display" ,
380
- ),
381
- },
208
+ desc_like (xy , coordinates = parent_coordinates ),
209
+ desc_like (xy , coordinates = "display" ),
382
210
)
383
211
384
212
screen_dims = screen_size .evaluate ({"x" : [0 , 1 ], "y" : [0 , 1 ]})
@@ -429,39 +257,11 @@ def query(
429
257
) -> Tuple [Dict [str , Any ], Union [str , int ]]:
430
258
dmin , dmax = self ._full_range
431
259
260
+ desc = Desc (("N" ,), np .dtype ("f8" ))
261
+ xy = {"x" : desc , "y" : desc }
432
262
data_lim = graph .evaluator (
433
- {
434
- "x" : Desc (
435
- ("N" ,),
436
- np .dtype (
437
- "f8" ,
438
- ),
439
- coordinates = "data" ,
440
- ),
441
- "y" : Desc (
442
- ("N" ,),
443
- np .dtype (
444
- "f8" ,
445
- ),
446
- coordinates = "data" ,
447
- ),
448
- },
449
- {
450
- "x" : Desc (
451
- ("N" ,),
452
- np .dtype (
453
- "f8" ,
454
- ),
455
- coordinates = parent_coordinates ,
456
- ),
457
- "y" : Desc (
458
- ("N" ,),
459
- np .dtype (
460
- "f8" ,
461
- ),
462
- coordinates = parent_coordinates ,
463
- ),
464
- },
263
+ desc_like (xy , coordinates = "data" ),
264
+ desc_like (xy , coordinates = parent_coordinates ),
465
265
).inverse
466
266
467
267
pts = data_lim .evaluate ({"x" : (0 , 1 ), "y" : (0 , 1 )})
@@ -493,7 +293,7 @@ def describe(self) -> Dict[str, Desc]:
493
293
494
294
495
295
class SeriesContainer :
496
- _data : pd .DataFrame
296
+ _data : pd .Series
497
297
_index_name : str
498
298
_hash_key : str
499
299
@@ -615,7 +415,7 @@ def query(
615
415
parent_coordinates : str = "axes" ,
616
416
) -> Tuple [Dict [str , Any ], Union [str , int ]]:
617
417
def hit_some_database ():
618
- {}, "1"
418
+ return {}, "1"
619
419
620
420
data , etag = hit_some_database ()
621
421
return data , etag
0 commit comments