1
1
import collections .abc
2
- from urllib . parse import urldefrag , urljoin
2
+ import typing
3
3
import copy
4
4
import itertools
5
5
import logging
@@ -452,11 +452,19 @@ def __call__(self, *a, **kw):
452
452
)
453
453
454
454
455
+ class ClassBuilderOptions (typing .TypedDict ):
456
+ strict : bool
457
+ any_of : str
458
+
459
+
455
460
class ClassBuilder (object ):
456
- def __init__ (self , resolver : referencing ._core .Resolver ):
461
+ def __init__ (
462
+ self , resolver : referencing ._core .Resolver , options : ClassBuilderOptions
463
+ ):
457
464
self .resolver = resolver
458
465
self .resolved = {}
459
466
self .under_construction = set ()
467
+ self .options = options
460
468
461
469
def expand_references (self , source_uri , iterable ):
462
470
"""Give an iterable of jsonschema descriptors, expands any
@@ -494,7 +502,7 @@ def resolve_type(self, ref, source):
494
502
)
495
503
resolved = self .resolver .lookup (uri )
496
504
if resolved .resolver != self .resolver :
497
- sub_cb = ClassBuilder (resolved .resolver )
505
+ sub_cb = ClassBuilder (resolved .resolver , self . options )
498
506
self .resolved [uri ] = sub_cb .construct (
499
507
uri , resolved .contents , (ProtocolBase ,)
500
508
)
@@ -505,34 +513,38 @@ def resolve_type(self, ref, source):
505
513
506
514
return self .resolved [uri ]
507
515
508
- def construct (self , uri , * args , ** kw ):
516
+ def construct (
517
+ self , uri : str , clsdata : typing .Mapping [str , any ], parent = (ProtocolBase ,)
518
+ ):
509
519
"""Wrapper to debug things"""
510
520
logger .debug (util .lazy_format ("Constructing {0}" , uri ))
511
- if ( "override" not in kw or kw [ "override" ] is False ) and uri in self .resolved :
521
+ if uri in self .resolved :
512
522
logger .debug (util .lazy_format ("Using existing {0}" , uri ))
513
523
assert self .resolved [uri ] is not None
514
524
return self .resolved [uri ]
515
525
else :
516
- ret = self ._construct (uri , * args , ** kw )
526
+ ret = self ._construct (uri , clsdata , parent = parent )
517
527
logger .debug (util .lazy_format ("Constructed {0}" , ret ))
518
528
519
529
return ret
520
530
521
- def _construct (self , uri , clsdata , parent = (ProtocolBase ,), ** kw ):
531
+ def _construct (
532
+ self , uri : str , clsdata : typing .Mapping [str , any ], parent = (ProtocolBase ,)
533
+ ):
522
534
if "anyOf" in clsdata :
523
- if kw .get ("any_of" , None ) is None :
535
+ if self . options .get ("any_of" , None ) is None :
524
536
raise NotImplementedError (
525
537
"anyOf is not supported as bare property (workarounds available by setting any_of flag)"
526
538
)
527
- if kw ["any_of" ] == "use-first" :
539
+ if self . options ["any_of" ] == "use-first" :
528
540
# Patch so the first anyOf becomes a single oneOf
529
541
clsdata ["oneOf" ] = [
530
542
clsdata ["anyOf" ].pop (0 ),
531
543
]
532
544
del clsdata ["anyOf" ]
533
545
else :
534
546
raise NotImplementedError (
535
- f"anyOf workaround is not a recognized type (any_of = { kw ['any_of' ]} )"
547
+ f"anyOf workaround is not a recognized type (any_of = { self . options ['any_of' ]} )"
536
548
)
537
549
538
550
if "oneOf" in clsdata :
@@ -557,7 +569,7 @@ def _construct(self, uri, clsdata, parent=(ProtocolBase,), **kw):
557
569
elif util .safe_issubclass (p , ProtocolBase ):
558
570
parents .append (p )
559
571
560
- self .resolved [uri ] = self ._build_object (uri , clsdata , parents , ** kw )
572
+ self .resolved [uri ] = self ._build_object (uri , clsdata , parents )
561
573
return self .resolved [uri ]
562
574
563
575
elif "$ref" in clsdata :
@@ -611,7 +623,7 @@ def _construct(self, uri, clsdata, parent=(ProtocolBase,), **kw):
611
623
or clsdata .get ("properties" , None ) is not None
612
624
or clsdata .get ("additionalProperties" , False )
613
625
):
614
- self .resolved [uri ] = self ._build_object (uri , clsdata , parent , ** kw )
626
+ self .resolved [uri ] = self ._build_object (uri , clsdata , parent )
615
627
return self .resolved [uri ]
616
628
elif clsdata .get ("type" ) in ("integer" , "number" , "string" , "boolean" , "null" ):
617
629
self .resolved [uri ] = self ._build_literal (uri , clsdata )
@@ -654,7 +666,7 @@ def _build_literal(self, nm, clsdata):
654
666
"default" ,
655
667
"asldkfn24olkjalskdfn e;laishd;1loj;flkansd;iow;naosdinfe;lkamjsdfj" ,
656
668
)
657
- is not "asldkfn24olkjalskdfn e;laishd;1loj;flkansd;iow;naosdinfe;lkamjsdfj"
669
+ != "asldkfn24olkjalskdfn e;laishd;1loj;flkansd;iow;naosdinfe;lkamjsdfj"
658
670
else clsdata .get ("const" )
659
671
),
660
672
}
@@ -663,7 +675,7 @@ def _build_literal(self, nm, clsdata):
663
675
664
676
return cls
665
677
666
- def _build_object (self , nm , clsdata , parents , ** kw ):
678
+ def _build_object (self , nm , clsdata , parents ):
667
679
logger .debug (util .lazy_format ("Building object {0}" , nm ))
668
680
669
681
# To support circular references, we tag objects that we're
@@ -713,7 +725,7 @@ def _build_object(self, nm, clsdata, parents, **kw):
713
725
714
726
if detail .get ("type" , None ) == "object" :
715
727
uri = "{0}/{1}_{2}" .format (nm , prop , "<anonymous>" )
716
- self .resolved [uri ] = self .construct (uri , detail , (ProtocolBase ,), ** kw )
728
+ self .resolved [uri ] = self .construct (uri , detail , (ProtocolBase ,))
717
729
718
730
props [prop ] = make_property (
719
731
prop , {"type" : self .resolved [uri ]}, self .resolved [uri ].__doc__
@@ -741,7 +753,7 @@ def _build_object(self, nm, clsdata, parents, **kw):
741
753
if "$ref" in detail ["items" ]:
742
754
typ = self .resolve_type (detail ["items" ]["$ref" ], nm )
743
755
constraints = copy .copy (detail )
744
- constraints ["strict" ] = kw .get ("strict" )
756
+ constraints ["strict" ] = self . options .get ("strict" )
745
757
propdata = {
746
758
"type" : "array" ,
747
759
"validator" : wrapper_types .ArrayWrapper .create (
@@ -760,10 +772,10 @@ def _build_object(self, nm, clsdata, parents, **kw):
760
772
)
761
773
)
762
774
else :
763
- typ = self .construct (uri , detail ["items" ], ** kw )
775
+ typ = self .construct (uri , detail ["items" ])
764
776
765
777
constraints = copy .copy (detail )
766
- constraints ["strict" ] = kw .get ("strict" )
778
+ constraints ["strict" ] = self . options .get ("strict" )
767
779
propdata = {
768
780
"type" : "array" ,
769
781
"validator" : wrapper_types .ArrayWrapper .create (
@@ -774,7 +786,7 @@ def _build_object(self, nm, clsdata, parents, **kw):
774
786
except NotImplementedError :
775
787
typ = detail ["items" ]
776
788
constraints = copy .copy (detail )
777
- constraints ["strict" ] = kw .get ("strict" )
789
+ constraints ["strict" ] = self . options .get ("strict" )
778
790
propdata = {
779
791
"type" : "array" ,
780
792
"validator" : wrapper_types .ArrayWrapper .create (
@@ -787,15 +799,15 @@ def _build_object(self, nm, clsdata, parents, **kw):
787
799
typs = []
788
800
for i , elem in enumerate (detail ["items" ]):
789
801
uri = "{0}/{1}/<anonymous_{2}>" .format (nm , prop , i )
790
- typ = self .construct (uri , elem , ** kw )
802
+ typ = self .construct (uri , elem )
791
803
typs .append (typ )
792
804
793
805
props [prop ] = make_property (prop , {"type" : typs })
794
806
795
807
else :
796
808
desc = detail ["description" ] if "description" in detail else ""
797
809
uri = "{0}/{1}" .format (nm , prop )
798
- typ = self .construct (uri , detail , ** kw )
810
+ typ = self .construct (uri , detail )
799
811
800
812
props [prop ] = make_property (prop , {"type" : typ }, desc )
801
813
@@ -821,7 +833,7 @@ def _build_object(self, nm, clsdata, parents, **kw):
821
833
822
834
props ["__required__" ] = required
823
835
props ["__has_default__" ] = defaults
824
- if required and kw .get ("strict" ):
836
+ if required and self . options .get ("strict" ):
825
837
props ["__strict__" ] = True
826
838
827
839
props ["__title__" ] = clsdata .get ("title" )
0 commit comments