1
1
from __future__ import annotations
2
2
3
3
from collections .abc import Iterable , Iterator , Sequence
4
- from typing import (
5
- Any ,
6
- Callable ,
7
- ClassVar ,
8
- Generic ,
9
- Protocol ,
10
- Tuple ,
11
- TypeVar ,
12
- cast ,
13
- )
4
+ from typing import Any , Callable , ClassVar , Generic , Protocol , TypeVar
14
5
from urllib .parse import unquote , urldefrag , urljoin
15
6
16
7
from attrs import evolve , field
17
- from pyrsistent import PMap as PMapType , plist , pmap , pset
18
- from pyrsistent .typing import PList , PMap , PSet
8
+ from rpds import HashTrieMap , HashTrieSet , List
19
9
20
10
from referencing import exceptions
21
11
from referencing ._attrs import frozen
22
12
from referencing .typing import URI , Anchor as AnchorType , D , Mapping , Retrieve
23
13
24
- EMPTY_RESOURCES : PMap [URI , Resource [Any ]] = pmap ({}, pre_size = 64 )
25
- EMPTY_ANCHORS = cast (PMap [Tuple [URI , str ], AnchorType [Any ]], EMPTY_RESOURCES )
26
- EMPTY_UNCRAWLED : PSet [URI ] = pset (pre_size = 128 )
27
- EMPTY_PREVIOUS_RESOLVERS : PList [URI ] = plist ()
14
+ EMPTY_UNCRAWLED : HashTrieSet [URI ] = HashTrieSet ()
15
+ EMPTY_PREVIOUS_RESOLVERS : List [URI ] = List ()
28
16
29
17
30
18
class _MaybeInSubresource (Protocol [D ]):
@@ -212,14 +200,6 @@ def _fail_to_retrieve(uri: URI):
212
200
raise exceptions .NoSuchResource (ref = uri )
213
201
214
202
215
- def _to_pmap (
216
- value : dict [URI , Resource [D ]]
217
- | PMap [URI , Resource [D ]]
218
- | list [tuple [URI , Resource [D ]]],
219
- ):
220
- return value if isinstance (value , PMapType ) else pmap (value )
221
-
222
-
223
203
@frozen
224
204
class Registry (Mapping [URI , Resource [D ]]):
225
205
r"""
@@ -245,14 +225,12 @@ class Registry(Mapping[URI, Resource[D]]):
245
225
even according to the retrieval logic.
246
226
"""
247
227
248
- _resources : PMap [URI , Resource [D ]] = field (
249
- default = EMPTY_RESOURCES ,
250
- converter = _to_pmap ,
228
+ _resources : HashTrieMap [URI , Resource [D ]] = field ( # type: ignore[reportGeneralTypeIssues] # noqa: E501
229
+ default = HashTrieMap () ,
230
+ converter = HashTrieMap . convert ,
251
231
)
252
- _anchors : PMap [tuple [URI , str ], AnchorType [D ]] = field (
253
- default = EMPTY_ANCHORS ,
254
- )
255
- _uncrawled : PSet [URI ] = field (default = EMPTY_UNCRAWLED )
232
+ _anchors : HashTrieMap [tuple [URI , str ], AnchorType [D ]] = HashTrieMap () # type: ignore[reportGeneralTypeIssues] # noqa: E501
233
+ _uncrawled : HashTrieSet [URI ] = EMPTY_UNCRAWLED
256
234
_retrieve : Retrieve [D ] = field (default = _fail_to_retrieve )
257
235
258
236
def __getitem__ (self , uri : URI ) -> Resource [D ]:
@@ -301,19 +279,15 @@ def __rmatmul__(self, new: Resource[D] | Iterable[Resource[D]]):
301
279
if isinstance (new , Resource ):
302
280
new = (new ,)
303
281
304
- resources = self ._resources . evolver ()
305
- uncrawled = self ._uncrawled . evolver ()
282
+ resources = self ._resources
283
+ uncrawled = self ._uncrawled
306
284
for resource in new :
307
285
id = resource .id ()
308
286
if id is None :
309
287
raise exceptions .NoInternalID (resource = resource )
310
- uncrawled .add (id )
311
- resources .set (id , resource )
312
- return evolve (
313
- self ,
314
- resources = resources .persistent (),
315
- uncrawled = uncrawled .persistent (),
316
- )
288
+ uncrawled = uncrawled .insert (id )
289
+ resources = resources .insert (id , resource )
290
+ return evolve (self , resources = resources , uncrawled = uncrawled )
317
291
318
292
def __repr__ (self ) -> str :
319
293
size = len (self )
@@ -365,7 +339,7 @@ def remove(self, uri: URI):
365
339
self ,
366
340
resources = self ._resources .remove (uri ),
367
341
uncrawled = self ._uncrawled .discard (uri ),
368
- anchors = pmap (
342
+ anchors = HashTrieMap (
369
343
(k , v ) for k , v in self ._anchors .items () if k [0 ] != uri
370
344
),
371
345
)
@@ -394,23 +368,23 @@ def crawl(self) -> Registry[D]:
394
368
"""
395
369
Immediately crawl all added resources, discovering subresources.
396
370
"""
397
- resources = self ._resources . evolver ()
398
- anchors = self ._anchors . evolver ()
371
+ resources = self ._resources
372
+ anchors = self ._anchors
399
373
uncrawled = [(uri , resources [uri ]) for uri in self ._uncrawled ]
400
374
while uncrawled :
401
375
uri , resource = uncrawled .pop ()
402
376
403
377
id = resource .id ()
404
378
if id is not None :
405
379
uri = urljoin (uri , id )
406
- resources [ uri ] = resource
380
+ resources = resources . insert ( uri , resource )
407
381
for each in resource .anchors ():
408
- anchors . set ((uri , each .name ), each )
382
+ anchors = anchors . insert ((uri , each .name ), each )
409
383
uncrawled .extend ((uri , each ) for each in resource .subresources ())
410
384
return evolve (
411
385
self ,
412
- resources = resources . persistent () ,
413
- anchors = anchors . persistent () ,
386
+ resources = resources ,
387
+ anchors = anchors ,
414
388
uncrawled = EMPTY_UNCRAWLED ,
415
389
)
416
390
@@ -427,16 +401,12 @@ def with_resources(
427
401
r"""
428
402
Add the given `Resource`\ s to the registry, without crawling them.
429
403
"""
430
- resources = self ._resources . evolver ()
431
- uncrawled = self ._uncrawled . evolver ()
404
+ resources = self ._resources
405
+ uncrawled = self ._uncrawled
432
406
for uri , resource in pairs :
433
- uncrawled .add (uri )
434
- resources [uri ] = resource
435
- return evolve (
436
- self ,
437
- resources = resources .persistent (),
438
- uncrawled = uncrawled .persistent (),
439
- )
407
+ uncrawled = uncrawled .insert (uri )
408
+ resources = resources .insert (uri , resource )
409
+ return evolve (self , resources = resources , uncrawled = uncrawled )
440
410
441
411
def with_contents (
442
412
self ,
@@ -540,11 +510,7 @@ class Resolver(Generic[D]):
540
510
541
511
_base_uri : str = field (alias = "base_uri" )
542
512
_registry : Registry [D ] = field (alias = "registry" )
543
- _previous : PList [URI ] = field (
544
- default = EMPTY_PREVIOUS_RESOLVERS ,
545
- repr = False ,
546
- alias = "previous" ,
547
- )
513
+ _previous : List [URI ] = field (default = List (), repr = False , alias = "previous" )
548
514
549
515
def lookup (self , ref : URI ) -> Resolved [D ]:
550
516
"""
@@ -614,7 +580,7 @@ def _evolve(self, base_uri: str, **kwargs: Any):
614
580
"""
615
581
previous = self ._previous
616
582
if self ._base_uri and (not previous or base_uri != self ._base_uri ):
617
- previous = previous .cons (self ._base_uri )
583
+ previous = previous .push_front (self ._base_uri )
618
584
return evolve (self , base_uri = base_uri , previous = previous , ** kwargs )
619
585
620
586
0 commit comments