Document preserves.schema
This commit is contained in:
parent
108119a351
commit
316c2dd407
|
@ -0,0 +1,16 @@
|
|||
A Preserves schema connects Preserves `Value`s to host-language data
|
||||
structures. Each definition within a schema can be processed by a
|
||||
compiler to produce
|
||||
|
||||
- a simple host-language *type definition*;
|
||||
|
||||
- a partial *parsing* function from `Value`s to instances of the
|
||||
produced type; and
|
||||
|
||||
- a total *serialization* function from instances of the type to
|
||||
`Value`s.
|
||||
|
||||
Every parsed `Value` retains enough information to always be able to
|
||||
be serialized again, and every instance of a host-language data
|
||||
structure contains, by construction, enough information to be
|
||||
successfully serialized.
|
|
@ -1,3 +1,7 @@
|
|||
# Preserves Schema
|
||||
|
||||
{% include "what-is-preserves-schema.md" %}
|
||||
|
||||
## Schema support in Python
|
||||
|
||||
::: preserves.schema
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
´³bundle·µ³tcp„´³schema·³version‘³definitions·³TcpLocal´³rec´³lit³ tcp-local„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³
SignedInteger„„„„„³ TcpRemote´³rec´³lit³
|
||||
tcp-remote„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³
SignedInteger„„„„„³TcpPeerInfo´³rec´³lit³tcp-peer„´³tupleµ´³named³handle´³embedded³any„„´³named³local´³refµ„³TcpLocal„„´³named³remote´³refµ„³ TcpRemote„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³http„´³schema·³version‘³definitions·³Chunk´³orµµ±string´³atom³String„„µ±bytes´³atom³
|
||||
ByteString„„„„³Headers´³dictof´³atom³Symbol„´³atom³String„„³MimeType´³atom³Symbol„³
|
||||
QueryValue´³orµµ±string´³atom³String„„µ±file´³rec´³lit³file„´³tupleµ´³named³filename´³atom³String„„´³named³headers´³refµ„³Headers„„´³named³body´³atom³
|
||||
ByteString„„„„„„„„³HostPattern´³orµµ±host´³atom³String„„µ±any´³lit€„„„„³HttpBinding´³rec´³lit³ http-bind„´³tupleµ´³named³host´³refµ„³HostPattern„„´³named³port´³atom³
SignedInteger„„´³named³method´³refµ„³
MethodPattern„„´³named³path´³refµ„³PathPattern„„´³named³handler´³embedded´³refµ„³HttpRequest„„„„„„³HttpContext´³rec´³lit³request„´³tupleµ´³named³req´³refµ„³HttpRequest„„´³named³res´³embedded´³refµ„³HttpResponse„„„„„„³HttpRequest´³rec´³lit³http-request„´³tupleµ´³named³sequenceNumber´³atom³
SignedInteger„„´³named³host´³atom³String„„´³named³port´³atom³
SignedInteger„„´³named³method´³atom³Symbol„„´³named³path´³seqof´³atom³String„„„´³named³headers´³refµ„³Headers„„´³named³query´³dictof´³atom³Symbol„´³seqof´³refµ„³
|
||||
QueryValue„„„„´³named³body´³refµ„³RequestBody„„„„„³HttpService´³rec´³lit³http-service„´³tupleµ´³named³host´³refµ„³HostPattern„„´³named³port´³atom³
SignedInteger„„´³named³method´³refµ„³
MethodPattern„„´³named³path´³refµ„³PathPattern„„„„„³PathPattern´³seqof´³refµ„³PathPatternElement„„³RequestBody´³orµµ±present´³atom³
|
||||
ByteString„„µ±absent´³lit€„„„„³HttpListener´³rec´³lit³
http-listener„´³tupleµ´³named³port´³atom³
SignedInteger„„„„„³HttpResponse´³orµµ±status´³rec´³lit³status„´³tupleµ´³named³code´³atom³
SignedInteger„„´³named³message´³atom³String„„„„„„µ±header´³rec´³lit³header„´³tupleµ´³named³name´³atom³Symbol„„´³named³value´³atom³String„„„„„„µ±chunk´³rec´³lit³chunk„´³tupleµ´³named³chunk´³refµ„³Chunk„„„„„„µ±done´³rec´³lit³done„´³tupleµ´³named³chunk´³refµ„³Chunk„„„„„„„„³
MethodPattern´³orµµ±any´³lit€„„µ±specific´³atom³Symbol„„„„³PathPatternElement´³orµµ±label´³atom³String„„µ±wildcard´³lit³_„„µ±rest´³lit³...„„„„„³embeddedType€„„µ³noise„´³schema·³version‘³definitions·³Packet´³orµµ±complete´³atom³
|
||||
ByteString„„µ±
|
||||
fragmented´³seqof´³atom³
|
||||
ByteString„„„„„³ NoiseSpec´³andµ´³dict·³key´³named³key´³atom³
|
||||
ByteString„„³service´³named³service´³refµ„³ServiceSelector„„„„´³named³protocol´³refµ„³
NoiseProtocol„„´³named³
preSharedKeys´³refµ„³NoisePreSharedKeys„„„„³
NoiseProtocol´³orµµ±present´³dict·³protocol´³named³protocol´³atom³String„„„„„µ±invalid´³dict·³protocol´³named³protocol³any„„„„µ±absent´³dict·„„„„„³
NoiseStepType´³lit³noise„³SecretKeyField´³orµµ±present´³dict·³ secretKey´³named³ secretKey´³atom³
|
||||
ByteString„„„„„µ±invalid´³dict·³ secretKey´³named³ secretKey³any„„„„µ±absent´³dict·„„„„„³DefaultProtocol´³lit±!Noise_NK_25519_ChaChaPoly_BLAKE2s„³NoiseStepDetail´³refµ„³ServiceSelector„³ServiceSelector³any³NoiseServiceSpec´³andµ´³named³base´³refµ„³ NoiseSpec„„´³named³ secretKey´³refµ„³SecretKeyField„„„„³NoisePreSharedKeys´³orµµ±present´³dict·³
preSharedKeys´³named³
preSharedKeys´³seqof´³atom³
|
||||
ByteString„„„„„„µ±invalid´³dict·³
preSharedKeys´³named³
preSharedKeys³any„„„„µ±absent´³dict·„„„„„³NoisePathStepDetail´³refµ„³ NoiseSpec„³NoiseDescriptionDetail´³refµ„³NoiseServiceSpec„„³embeddedType€„„µ³timer„´³schema·³version‘³definitions·³SetTimer´³rec´³lit³ set-timer„´³tupleµ´³named³label³any„´³named³seconds´³atom³Double„„´³named³kind´³refµ„³ TimerKind„„„„„³ LaterThan´³rec´³lit³
|
||||
later-than„´³tupleµ´³named³seconds´³atom³Double„„„„„³ TimerKind´³orµµ±relative´³lit³relative„„µ±absolute´³lit³absolute„„µ±clear´³lit³clear„„„„³TimerExpired´³rec´³lit³
timer-expired„´³tupleµ´³named³label³any„´³named³seconds´³atom³Double„„„„„„³embeddedType€„„µ³trace„´³schema·³version‘³definitions·³Oid³any³Name´³orµµ± anonymous´³rec´³lit³ anonymous„´³tupleµ„„„„µ±named´³rec´³lit³named„´³tupleµ´³named³name³any„„„„„„„³Target´³rec´³lit³entity„´³tupleµ´³named³actor´³refµ„³ActorId„„´³named³facet´³refµ„³FacetId„„´³named³oid´³refµ„³Oid„„„„„³TaskId³any³TurnId³any³ActorId³any³FacetId³any³ TurnCause´³orµµ±turn´³rec´³lit³ caused-by„´³tupleµ´³named³id´³refµ„³TurnId„„„„„„µ±cleanup´³rec´³lit³cleanup„´³tupleµ„„„„µ±linkedTaskRelease´³rec´³lit³linked-task-release„´³tupleµ´³named³id´³refµ„³TaskId„„´³named³reason´³refµ„³LinkedTaskReleaseReason„„„„„„µ±periodicActivation´³rec´³lit³periodic-activation„´³tupleµ´³named³period´³atom³Double„„„„„„µ±delay´³rec´³lit³delay„´³tupleµ´³named³causingTurn´³refµ„³TurnId„„´³named³amount´³atom³Double„„„„„„µ±external´³rec´³lit³external„´³tupleµ´³named³description³any„„„„„„„³ TurnEvent´³orµµ±assert´³rec´³lit³assert„´³tupleµ´³named³ assertion´³refµ„³AssertionDescription„„´³named³handle´³refµ³protocol„³Handle„„„„„„µ±retract´³rec´³lit³retract„´³tupleµ´³named³handle´³refµ³protocol„³Handle„„„„„„µ±message´³rec´³lit³message„´³tupleµ´³named³body´³refµ„³AssertionDescription„„„„„„µ±sync´³rec´³lit³sync„´³tupleµ´³named³peer´³refµ„³Target„„„„„„µ± breakLink´³rec´³lit³
|
||||
break-link„´³tupleµ´³named³source´³refµ„³ActorId„„´³named³handle´³refµ³protocol„³Handle„„„„„„„„³
|
||||
ExitStatus´³orµµ±ok´³lit³ok„„µ±Error´³refµ³protocol„³Error„„„„³
|
||||
TraceEntry´³rec´³lit³trace„´³tupleµ´³named³ timestamp´³atom³Double„„´³named³actor´³refµ„³ActorId„„´³named³item´³refµ„³ActorActivation„„„„„³ActorActivation´³orµµ±start´³rec´³lit³start„´³tupleµ´³named³ actorName´³refµ„³Name„„„„„„µ±turn´³refµ„³TurnDescription„„µ±stop´³rec´³lit³stop„´³tupleµ´³named³status´³refµ„³
|
||||
ExitStatus„„„„„„„„³FacetStopReason´³orµµ±explicitAction´³lit³explicit-action„„µ±inert´³lit³inert„„µ±parentStopping´³lit³parent-stopping„„µ±
actorStopping´³lit³actor-stopping„„„„³TurnDescription´³rec´³lit³turn„´³tupleµ´³named³id´³refµ„³TurnId„„´³named³cause´³refµ„³ TurnCause„„´³named³actions´³seqof´³refµ„³ActionDescription„„„„„„³ActionDescription´³orµµ±dequeue´³rec´³lit³dequeue„´³tupleµ´³named³event´³refµ„³TargetedTurnEvent„„„„„„µ±enqueue´³rec´³lit³enqueue„´³tupleµ´³named³event´³refµ„³TargetedTurnEvent„„„„„„µ±dequeueInternal´³rec´³lit³dequeue-internal„´³tupleµ´³named³event´³refµ„³TargetedTurnEvent„„„„„„µ±enqueueInternal´³rec´³lit³enqueue-internal„´³tupleµ´³named³event´³refµ„³TargetedTurnEvent„„„„„„µ±spawn´³rec´³lit³spawn„´³tupleµ´³named³link´³atom³Boolean„„´³named³id´³refµ„³ActorId„„„„„„µ±link´³rec´³lit³link„´³tupleµ´³named³parentActor´³refµ„³ActorId„„´³named³
childToParent´³refµ³protocol„³Handle„„´³named³
|
||||
childActor´³refµ„³ActorId„„´³named³
parentToChild´³refµ³protocol„³Handle„„„„„„µ±
|
||||
facetStart´³rec´³lit³facet-start„´³tupleµ´³named³path´³seqof´³refµ„³FacetId„„„„„„„µ± facetStop´³rec´³lit³
|
||||
facet-stop„´³tupleµ´³named³path´³seqof´³refµ„³FacetId„„„´³named³reason´³refµ„³FacetStopReason„„„„„„µ±linkedTaskStart´³rec´³lit³linked-task-start„´³tupleµ´³named³taskName´³refµ„³Name„„´³named³id´³refµ„³TaskId„„„„„„„„³TargetedTurnEvent´³rec´³lit³event„´³tupleµ´³named³target´³refµ„³Target„„´³named³detail´³refµ„³ TurnEvent„„„„„³AssertionDescription´³orµµ±value´³rec´³lit³value„´³tupleµ´³named³value³any„„„„„µ±opaque´³rec´³lit³opaque„´³tupleµ´³named³description³any„„„„„„„³LinkedTaskReleaseReason´³orµµ± cancelled´³lit³ cancelled„„µ±normal´³lit³normal„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³stream„´³schema·³version‘³definitions·³Mode´³orµµ±bytes´³lit³bytes„„µ±lines´³refµ„³LineMode„„µ±packet´³rec´³lit³packet„´³tupleµ´³named³size´³atom³
SignedInteger„„„„„„µ±object´³rec´³lit³object„´³tupleµ´³named³description³any„„„„„„„³Sink´³orµµ±source´³rec´³lit³source„´³tupleµ´³named³
|
||||
controller´³embedded´³refµ„³Source„„„„„„„µ±StreamError´³refµ„³StreamError„„µ±data´³rec´³lit³data„´³tupleµ´³named³payload³any„´³named³mode´³refµ„³Mode„„„„„„µ±eof´³rec´³lit³eof„´³tupleµ„„„„„„³Source´³orµµ±sink´³rec´³lit³sink„´³tupleµ´³named³
|
||||
controller´³embedded´³refµ„³Sink„„„„„„„µ±StreamError´³refµ„³StreamError„„µ±credit´³rec´³lit³credit„´³tupleµ´³named³amount´³refµ„³CreditAmount„„´³named³mode´³refµ„³Mode„„„„„„„„³LineMode´³orµµ±lf´³lit³lf„„µ±crlf´³lit³crlf„„„„³StreamError´³rec´³lit³error„´³tupleµ´³named³message´³atom³String„„„„„³CreditAmount´³orµµ±count´³atom³
SignedInteger„„µ± unbounded´³lit³ unbounded„„„„³StreamConnection´³rec´³lit³stream-connection„´³tupleµ´³named³source´³embedded´³refµ„³Source„„„´³named³sink´³embedded´³refµ„³Sink„„„´³named³spec³any„„„„³StreamListenerError´³rec´³lit³stream-listener-error„´³tupleµ´³named³spec³any„´³named³message´³atom³String„„„„„³StreamListenerReady´³rec´³lit³stream-listener-ready„´³tupleµ´³named³spec³any„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³sturdy„´³schema·³version‘³definitions·³Lit´³rec´³lit³lit„´³tupleµ´³named³value³any„„„„³Oid´³atom³
SignedInteger„³Alts´³rec´³lit³or„´³tupleµ´³named³alternatives´³seqof´³refµ„³Rewrite„„„„„„³PAnd´³rec´³lit³and„´³tupleµ´³named³patterns´³seqof´³refµ„³Pattern„„„„„„³PNot´³rec´³lit³not„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„³TRef´³rec´³lit³ref„´³tupleµ´³named³binding´³atom³
SignedInteger„„„„„³PAtom´³orµµ±Boolean´³lit³Boolean„„µ±Float´³lit³Float„„µ±Double´³lit³Double„„µ±
SignedInteger´³lit³
SignedInteger„„µ±String´³lit³String„„µ±
|
||||
ByteString´³lit³
|
||||
ByteString„„µ±Symbol´³lit³Symbol„„„„³PBind´³rec´³lit³bind„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„³Caveat´³orµµ±Rewrite´³refµ„³Rewrite„„µ±Alts´³refµ„³Alts„„µ±Reject´³refµ„³Reject„„µ±unknown³any„„„³Reject´³rec´³lit³reject„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„³Pattern´³orµµ±PDiscard´³refµ„³PDiscard„„µ±PAtom´³refµ„³PAtom„„µ± PEmbedded´³refµ„³ PEmbedded„„µ±PBind´³refµ„³PBind„„µ±PAnd´³refµ„³PAnd„„µ±PNot´³refµ„³PNot„„µ±Lit´³refµ„³Lit„„µ± PCompound´³refµ„³ PCompound„„„„³Rewrite´³rec´³lit³rewrite„´³tupleµ´³named³pattern´³refµ„³Pattern„„´³named³template´³refµ„³Template„„„„„³WireRef´³orµµ±mine´³tupleµ´³lit<69>„´³named³oid´³refµ„³Oid„„„„„µ±yours´³tuplePrefixµ´³lit‘„´³named³oid´³refµ„³Oid„„„´³named³attenuation´³seqof´³refµ„³Caveat„„„„„„„³PDiscard´³rec´³lit³_„´³tupleµ„„„³Template´³orµµ±
|
||||
TAttenuate´³refµ„³
|
||||
TAttenuate„„µ±TRef´³refµ„³TRef„„µ±Lit´³refµ„³Lit„„µ± TCompound´³refµ„³ TCompound„„„„³ PCompound´³orµµ±rec´³rec´³lit³rec„´³tupleµ´³named³label³any„´³named³fields´³seqof´³refµ„³Pattern„„„„„„„µ±arr´³rec´³lit³arr„´³tupleµ´³named³items´³seqof´³refµ„³Pattern„„„„„„„µ±dict´³rec´³lit³dict„´³tupleµ´³named³entries´³dictof³any´³refµ„³Pattern„„„„„„„„„³ PEmbedded´³lit³Embedded„³ SturdyRef´³rec´³lit³ref„´³tupleµ´³named³
|
||||
parameters´³refµ„³
|
||||
Parameters„„„„„³ TCompound´³orµµ±rec´³rec´³lit³rec„´³tupleµ´³named³label³any„´³named³fields´³seqof´³refµ„³Template„„„„„„„µ±arr´³rec´³lit³arr„´³tupleµ´³named³items´³seqof´³refµ„³Template„„„„„„„µ±dict´³rec´³lit³dict„´³tupleµ´³named³entries´³dictof³any´³refµ„³Template„„„„„„„„„³
|
||||
Parameters´³andµ´³dict·³oid´³named³oid³any„³sig´³named³sig´³atom³
|
||||
ByteString„„„„´³named³caveats´³refµ„³CaveatsField„„„„³
|
||||
TAttenuate´³rec´³lit³ attenuate„´³tupleµ´³named³template´³refµ„³Template„„´³named³attenuation´³seqof´³refµ„³Caveat„„„„„„³CaveatsField´³orµµ±present´³dict·³caveats´³named³caveats´³seqof´³refµ„³Caveat„„„„„„µ±invalid´³dict·³caveats´³named³caveats³any„„„„µ±absent´³dict·„„„„„³SturdyStepType´³lit³ref„³SturdyStepDetail´³refµ„³
|
||||
Parameters„³SturdyPathStepDetail´³refµ„³
|
||||
Parameters„³SturdyDescriptionDetail´³dict·³key´³named³key´³atom³
|
||||
ByteString„„³oid´³named³oid³any„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³worker„´³schema·³version‘³definitions·³Instance´³rec´³lit³Instance„´³tupleµ´³named³name´³atom³String„„´³named³argument³any„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³service„´³schema·³version‘³definitions·³State´³orµµ±started´³lit³started„„µ±ready´³lit³ready„„µ±failed´³lit³failed„„µ±complete´³lit³complete„„µ±userDefined³any„„„³
|
||||
RunService´³rec´³lit³run-service„´³tupleµ´³named³serviceName³any„„„„³ServiceState´³rec´³lit³
service-state„´³tupleµ´³named³serviceName³any„´³named³state´³refµ„³State„„„„„³
ServiceObject´³rec´³lit³service-object„´³tupleµ´³named³serviceName³any„´³named³object³any„„„„³RequireService´³rec´³lit³require-service„´³tupleµ´³named³serviceName³any„„„„³RestartService´³rec´³lit³restart-service„´³tupleµ´³named³serviceName³any„„„„³ServiceDependency´³rec´³lit³
|
||||
depends-on„´³tupleµ´³named³depender³any„´³named³dependee´³refµ„³ServiceState„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³protocol„´³schema·³version‘³definitions·³Oid´³atom³
SignedInteger„³Sync´³rec´³lit³sync„´³tupleµ´³named³peer´³embedded´³lit<69>„„„„„„³Turn´³seqof´³refµ„³ TurnEvent„„³Error´³rec´³lit³error„´³tupleµ´³named³message´³atom³String„„´³named³detail³any„„„„³Event´³orµµ±Assert´³refµ„³Assert„„µ±Retract´³refµ„³Retract„„µ±Message´³refµ„³Message„„µ±Sync´³refµ„³Sync„„„„³Assert´³rec´³lit³assert„´³tupleµ´³named³ assertion´³refµ„³ Assertion„„´³named³handle´³refµ„³Handle„„„„„³Handle´³atom³
SignedInteger„³Packet´³orµµ±Turn´³refµ„³Turn„„µ±Error´³refµ„³Error„„µ± Extension´³refµ„³ Extension„„„„³Message´³rec´³lit³message„´³tupleµ´³named³body´³refµ„³ Assertion„„„„„³Retract´³rec´³lit³retract„´³tupleµ´³named³handle´³refµ„³Handle„„„„„³ Assertion³any³ Extension´³rec´³named³label³any„´³named³fields´³seqof³any„„„³ TurnEvent´³tupleµ´³named³oid´³refµ„³Oid„„´³named³event´³refµ„³Event„„„„„³embeddedType€„„µ³ dataspace„´³schema·³version‘³definitions·³Observe´³rec´³lit³Observe„´³tupleµ´³named³pattern´³refµ³dataspacePatterns„³Pattern„„´³named³observer´³embedded³any„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³
|
||||
gatekeeper„´³schema·³version‘³definitions·³Bind´³rec´³lit³bind„´³tupleµ´³named³description´³refµ„³Description„„´³named³target´³embedded³any„„´³named³observer´³refµ„³BindObserver„„„„„³Step´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³Bound´³orµµ±bound´³rec´³lit³bound„´³tupleµ´³named³pathStep´³refµ„³PathStep„„„„„„µ±Rejected´³refµ„³Rejected„„„„³Route´³rec´³lit³route„´³tuplePrefixµ´³named³
|
||||
transports´³seqof³any„„„´³named³ pathSteps´³seqof´³refµ„³PathStep„„„„„³Resolve´³rec´³lit³resolve„´³tupleµ´³named³step´³refµ„³Step„„´³named³observer´³embedded´³refµ„³Resolved„„„„„„³PathStep´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³Rejected´³rec´³lit³rejected„´³tupleµ´³named³detail³any„„„„³Resolved´³orµµ±accepted´³rec´³lit³accepted„´³tupleµ´³named³responderSession´³embedded³any„„„„„„µ±Rejected´³refµ„³Rejected„„„„³Description´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³ResolvePath´³rec´³lit³resolve-path„´³tupleµ´³named³route´³refµ„³Route„„´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³resolved´³refµ„³Resolved„„„„„³BindObserver´³orµµ±present´³embedded´³refµ„³Bound„„„µ±absent´³lit€„„„„³ForceDisconnect´³rec´³lit³force-disconnect„´³tupleµ„„„³ResolvedPathStep´³rec´³lit³ path-step„´³tupleµ´³named³origin´³embedded´³refµ„³Resolve„„„´³named³pathStep´³refµ„³PathStep„„´³named³resolved´³refµ„³Resolved„„„„„³TransportControl´³refµ„³ForceDisconnect„³TransportConnection´³rec´³lit³connect-transport„´³tupleµ´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³resolved´³refµ„³Resolved„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³transportAddress„´³schema·³version‘³definitions·³Tcp´³rec´³lit³tcp„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³
SignedInteger„„„„„³Unix´³rec´³lit³unix„´³tupleµ´³named³path´³atom³String„„„„„³Stdio´³rec´³lit³stdio„´³tupleµ„„„³ WebSocket´³rec´³lit³ws„´³tupleµ´³named³url´³atom³String„„„„„„³embeddedType€„„µ³dataspacePatterns„´³schema·³version‘³definitions·³DLit´³rec´³lit³lit„´³tupleµ´³named³value´³refµ„³AnyAtom„„„„„³DBind´³rec´³lit³bind„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„³AnyAtom´³orµµ±bool´³atom³Boolean„„µ±float´³atom³Float„„µ±double´³atom³Double„„µ±int´³atom³
SignedInteger„„µ±string´³atom³String„„µ±bytes´³atom³
|
||||
ByteString„„µ±symbol´³atom³Symbol„„µ±embedded´³embedded³any„„„„³Pattern´³orµµ±DDiscard´³refµ„³DDiscard„„µ±DBind´³refµ„³DBind„„µ±DLit´³refµ„³DLit„„µ± DCompound´³refµ„³ DCompound„„„„³DDiscard´³rec´³lit³_„´³tupleµ„„„³ DCompound´³orµµ±rec´³rec´³lit³rec„´³tupleµ´³named³label³any„´³named³fields´³seqof´³refµ„³Pattern„„„„„„„µ±arr´³rec´³lit³arr„´³tupleµ´³named³items´³seqof´³refµ„³Pattern„„„„„„„µ±dict´³rec´³lit³dict„´³tupleµ´³named³entries´³dictof³any´³refµ„³Pattern„„„„„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„„„
|
|
@ -1,7 +1,266 @@
|
|||
"""This is an implementation of [Preserves Schema](https://preserves.dev/preserves-schema.html)
|
||||
for Python 3.
|
||||
"""The [preserves.schema][] module implements [Preserves
|
||||
Schema](https://preserves.dev/preserves-schema.html) for Python.
|
||||
|
||||
A Schema source file (like [this one](https://preserves.dev/schema/schema.prs)) is first
|
||||
compiled using [`preserves-schemac`](https://preserves.dev/doc/preserves-schemac.html) to
|
||||
produce a binary-syntax *schema bundle* containing schema module definitons (like [this
|
||||
one](https://preserves.dev/preserves-schema.html#appendix-metaschema-instance)). Python code
|
||||
then loads the bundle, exposing its contents as [Namespace][preserves.schema.Namespace]s
|
||||
ultimately containing [SchemaObject][preserves.schema.SchemaObject]s.
|
||||
|
||||
## Examples
|
||||
|
||||
### Setup: Loading a schema bundle
|
||||
|
||||
For our running example, we will use schemas associated with the [Syndicated Actor
|
||||
Model](https://git.syndicate-lang.org/syndicate-lang/syndicate-protocols). (The schema bundle
|
||||
is a copy of [this
|
||||
file](https://git.syndicate-lang.org/syndicate-lang/syndicate-protocols/src/branch/main/schema-bundle.bin)
|
||||
from the `syndicate-protocols` repository.)
|
||||
|
||||
To load a schema bundle, use [load_schema_file][preserves.schema.load_schema_file] (or,
|
||||
alternatively, use [Compiler][preserves.schema.Compiler] directly):
|
||||
|
||||
```python
|
||||
>>> bundle = load_schema_file('docs/syndicate-protocols-schema-bundle.bin')
|
||||
>>> type(bundle)
|
||||
<class 'preserves.schema.Namespace'>
|
||||
|
||||
```
|
||||
|
||||
The top-level entries in the loaded bundle are schema modules. Let's examine the `stream`
|
||||
schema module, whose [source
|
||||
code](https://git.syndicate-lang.org/syndicate-lang/syndicate-protocols/src/commit/d8a139b23a40bad6698f9f4240f9e8426b4a123f/schemas/stream.prs)
|
||||
indicates that it should contain definitions for `Mode`, `Source`, `Sink`, etc.:
|
||||
|
||||
```python
|
||||
>>> bundle.stream # doctest: +ELLIPSIS
|
||||
{'Mode': <class 'stream.Mode'>, 'Sink': <class 'stream.Sink'>, ...}
|
||||
|
||||
```
|
||||
|
||||
### Example 1: stream.StreamListenerError, a product type
|
||||
|
||||
Drilling down further, let's consider the [definition of
|
||||
StreamListenerError](https://git.syndicate-lang.org/syndicate-lang/syndicate-protocols/src/commit/d8a139b23a40bad6698f9f4240f9e8426b4a123f/schemas/stream.prs#L9), which appears in the source as
|
||||
|
||||
```
|
||||
StreamListenerError = <stream-listener-error @spec any @message string> .
|
||||
```
|
||||
|
||||
This reads, in the [Preserves Schema
|
||||
language](https://preserves.dev/preserves-schema.html#the-preserves-schema-language), as the
|
||||
definition of a simple product type (record, class, object) with two named fields `spec` and
|
||||
`message`. Parsing a value into a `StreamListenerError` will only succeed if it's a record, if
|
||||
the label matches, the second field (`message`) is a string, and it has exactly two fields.
|
||||
|
||||
```python
|
||||
>>> bundle.stream.StreamListenerError
|
||||
<class 'stream.StreamListenerError'>
|
||||
|
||||
```
|
||||
|
||||
The `StreamListenerError` class includes a [decode][preserves.schema.SchemaObject.decode]
|
||||
method that analyzes an input value:
|
||||
|
||||
```python
|
||||
>>> bundle.stream.StreamListenerError.decode(
|
||||
... parse('<stream-listener-error <xyz> "an error">'))
|
||||
StreamListenerError {'spec': #xyz(), 'message': 'an error'}
|
||||
|
||||
```
|
||||
|
||||
If invalid input is supplied, [decode][preserves.schema.SchemaObject.decode] will raise
|
||||
[SchemaDecodeFailed][preserves.schema.SchemaDecodeFailed], which includes helpful information
|
||||
for diagnosing the problem (as we will see below, this is especially useful for parsers for sum
|
||||
types):
|
||||
|
||||
```python
|
||||
>>> bundle.stream.StreamListenerError.decode(
|
||||
... parse('<i-am-invalid>'))
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
preserves.schema.SchemaDecodeFailed: Could not decode i-am-invalid using <class 'stream.StreamListenerError'>
|
||||
Most likely reason: in stream.StreamListenerError: <lit stream-listener-error> didn't match i-am-invalid
|
||||
Full explanation:
|
||||
in stream.StreamListenerError: <lit stream-listener-error> didn't match i-am-invalid
|
||||
|
||||
```
|
||||
|
||||
Alternatively, the [try_decode][preserves.schema.SchemaObject.try_decode] method catches
|
||||
[SchemaDecodeFailed][preserves.schema.SchemaDecodeFailed], transforming it into `None`:
|
||||
|
||||
```python
|
||||
>>> bundle.stream.StreamListenerError.try_decode(
|
||||
... parse('<stream-listener-error <xyz> "an error">'))
|
||||
StreamListenerError {'spec': #xyz(), 'message': 'an error'}
|
||||
>>> bundle.stream.StreamListenerError.try_decode(
|
||||
... parse('<i-am-invalid>'))
|
||||
|
||||
```
|
||||
|
||||
The class can also be instantiated directly:
|
||||
|
||||
```python
|
||||
>>> err = bundle.stream.StreamListenerError(Record(Symbol('xyz'), []), 'an error')
|
||||
>>> err
|
||||
StreamListenerError {'spec': #xyz(), 'message': 'an error'}
|
||||
|
||||
```
|
||||
|
||||
The fields and contents of instances can be queried:
|
||||
|
||||
```python
|
||||
>>> err.spec
|
||||
#xyz()
|
||||
>>> err.message
|
||||
'an error'
|
||||
|
||||
```
|
||||
|
||||
And finally, instances can of course be serialized and encoded:
|
||||
|
||||
```python
|
||||
>>> print(stringify(err))
|
||||
<stream-listener-error <xyz> "an error">
|
||||
>>> canonicalize(err)
|
||||
b'\\xb4\\xb3\\x15stream-listener-error\\xb4\\xb3\\x03xyz\\x84\\xb1\\x08an error\\x84'
|
||||
|
||||
```
|
||||
|
||||
### Example 2: stream.Mode, a sum type
|
||||
|
||||
Now let's consider the [definition of
|
||||
Mode](https://git.syndicate-lang.org/syndicate-lang/syndicate-protocols/src/commit/d8a139b23a40bad6698f9f4240f9e8426b4a123f/schemas/stream.prs#L37),
|
||||
which appears in the source as
|
||||
|
||||
```
|
||||
Mode = =bytes / @lines LineMode / <packet @size int> / <object @description any> .
|
||||
```
|
||||
|
||||
This reads, in the [Preserves Schema
|
||||
language](https://preserves.dev/preserves-schema.html#the-preserves-schema-language), as an
|
||||
alternation (disjoint union, variant, sum type) of four possible kinds of value: the symbol
|
||||
`bytes`; a `LineMode` value; a record with `packet` as its label and an integer as its only
|
||||
field; or a record with `object` as its label and any kind of value as its only field. In
|
||||
Python, this becomes:
|
||||
|
||||
```python
|
||||
>>> bundle.stream.Mode.bytes
|
||||
<class 'stream.Mode.bytes'>
|
||||
>>> bundle.stream.Mode.lines
|
||||
<class 'stream.Mode.lines'>
|
||||
>>> bundle.stream.Mode.packet
|
||||
<class 'stream.Mode.packet'>
|
||||
>>> bundle.stream.Mode.object
|
||||
<class 'stream.Mode.object'>
|
||||
|
||||
```
|
||||
|
||||
As before, `Mode` includes a [decode][preserves.schema.SchemaObject.decode] method that analyzes
|
||||
an input value:
|
||||
|
||||
```python
|
||||
>>> bundle.stream.Mode.decode(parse('bytes'))
|
||||
Mode.bytes()
|
||||
>>> bundle.stream.Mode.decode(parse('lf'))
|
||||
Mode.lines(LineMode.lf())
|
||||
>>> bundle.stream.Mode.decode(parse('<packet 123>'))
|
||||
Mode.packet {'size': 123}
|
||||
>>> bundle.stream.Mode.decode(parse('<object "?">'))
|
||||
Mode.object {'description': '?'}
|
||||
|
||||
```
|
||||
|
||||
Invalid input causes [SchemaDecodeFailed][preserves.schema.SchemaDecodeFailed] to be raised:
|
||||
|
||||
```python
|
||||
>>> bundle.stream.Mode.decode(parse('<i-am-not-a-valid-mode>'))
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
preserves.schema.SchemaDecodeFailed: Could not decode <i-am-not-a-valid-mode> using <class 'stream.Mode'>
|
||||
Most likely reason: in stream.LineMode.crlf: <lit crlf> didn't match <i-am-not-a-valid-mode>
|
||||
Full explanation:
|
||||
in stream.Mode: matching <i-am-not-a-valid-mode>
|
||||
in stream.Mode.bytes: <lit bytes> didn't match <i-am-not-a-valid-mode>
|
||||
in stream.Mode.lines: <ref [] LineMode> didn't match <i-am-not-a-valid-mode>
|
||||
in stream.LineMode: matching <i-am-not-a-valid-mode>
|
||||
in stream.LineMode.lf: <lit lf> didn't match <i-am-not-a-valid-mode>
|
||||
in stream.LineMode.crlf: <lit crlf> didn't match <i-am-not-a-valid-mode>
|
||||
in stream.Mode.packet: <lit packet> didn't match i-am-not-a-valid-mode
|
||||
in stream.Mode.object: <lit object> didn't match i-am-not-a-valid-mode
|
||||
|
||||
```
|
||||
|
||||
The "full explanation" includes details on which parses were attempted, and why they failed.
|
||||
|
||||
Again, the [try_decode][preserves.schema.SchemaObject.try_decode] method catches
|
||||
[SchemaDecodeFailed][preserves.schema.SchemaDecodeFailed], transforming it into `None`:
|
||||
|
||||
```python
|
||||
>>> bundle.stream.Mode.try_decode(parse('bytes'))
|
||||
Mode.bytes()
|
||||
>>> bundle.stream.Mode.try_decode(parse('<i-am-not-a-valid-mode>'))
|
||||
|
||||
```
|
||||
|
||||
Direct instantiation is done with the variant classes, not with `Mode` itself:
|
||||
|
||||
```python
|
||||
>>> bundle.stream.Mode.bytes()
|
||||
Mode.bytes()
|
||||
>>> bundle.stream.Mode.lines(bundle.stream.LineMode.lf())
|
||||
Mode.lines(LineMode.lf())
|
||||
>>> bundle.stream.Mode.packet(123)
|
||||
Mode.packet {'size': 123}
|
||||
>>> bundle.stream.Mode.object('?')
|
||||
Mode.object {'description': '?'}
|
||||
|
||||
```
|
||||
|
||||
Fields and contents can be queried as usual:
|
||||
|
||||
```python
|
||||
>>> bundle.stream.Mode.lines(bundle.stream.LineMode.lf()).value
|
||||
LineMode.lf()
|
||||
>>> bundle.stream.Mode.packet(123).size
|
||||
123
|
||||
>>> bundle.stream.Mode.object('?').description
|
||||
'?'
|
||||
|
||||
```
|
||||
|
||||
And serialization and encoding are also as expected:
|
||||
|
||||
```python
|
||||
>>> print(stringify(bundle.stream.Mode.bytes()))
|
||||
bytes
|
||||
>>> print(stringify(bundle.stream.Mode.lines(bundle.stream.LineMode.lf())))
|
||||
lf
|
||||
>>> print(stringify(bundle.stream.Mode.packet(123)))
|
||||
<packet 123>
|
||||
>>> print(stringify(bundle.stream.Mode.object('?')))
|
||||
<object "?">
|
||||
>>> canonicalize(bundle.stream.Mode.object('?'))
|
||||
b'\\xb4\\xb3\\x06object\\xb1\\x01?\\x84'
|
||||
|
||||
```
|
||||
|
||||
Finally, the [VARIANT][preserves.schema.SchemaObject.VARIANT] attribute of instances
|
||||
allows code to dispatch on what kind of data it is handling at a given moment:
|
||||
|
||||
```python
|
||||
>>> bundle.stream.Mode.bytes().VARIANT
|
||||
#bytes
|
||||
>>> bundle.stream.Mode.lines(bundle.stream.LineMode.lf()).VARIANT
|
||||
#lines
|
||||
>>> bundle.stream.Mode.packet(123).VARIANT
|
||||
#packet
|
||||
>>> bundle.stream.Mode.object('?').VARIANT
|
||||
#object
|
||||
|
||||
```
|
||||
|
||||
TODO
|
||||
"""
|
||||
|
||||
from . import *
|
||||
|
@ -40,7 +299,15 @@ def sequenceish(x):
|
|||
return isinstance(x, tuple) or isinstance(x, list)
|
||||
|
||||
class SchemaDecodeFailed(ValueError):
|
||||
"""TODO"""
|
||||
"""Raised when [decode][preserves.schema.SchemaObject.decode] cannot find a way to parse a
|
||||
given input.
|
||||
|
||||
Attributes:
|
||||
cls (class): the SchemaObject subclass attempting the parse
|
||||
pattern (Value): the failing pattern, a `Value` conforming to schema `meta.Pattern`
|
||||
value (Value): the unparseable value
|
||||
failures (list[SchemaDecodeFailed]): descriptions of failed paths attempted during the match this failure describes
|
||||
"""
|
||||
def __init__(self, cls, p, v, failures=None):
|
||||
super().__init__()
|
||||
self.cls = cls
|
||||
|
@ -84,22 +351,108 @@ class ExplanationBuilder:
|
|||
return '\n' + ' ' * self.indentLevel + self._node(failure) + ''.join(nested)
|
||||
|
||||
class SchemaObject:
|
||||
"""TODO"""
|
||||
"""Base class for classes representing grammatical productions in a schema: instances of
|
||||
[SchemaObject][preserves.schema.SchemaObject] represent schema *definitions*. This is an
|
||||
abstract class, as are its subclasses [Enumeration][preserves.schema.Enumeration] and
|
||||
[Definition][preserves.schema.Definition]. It is subclasses of *those* subclasses,
|
||||
automatically produced during schema loading, that are actually instantiated.
|
||||
|
||||
```python
|
||||
>>> bundle = load_schema_file('docs/syndicate-protocols-schema-bundle.bin')
|
||||
|
||||
>>> bundle.stream.Mode.mro()[1:-1]
|
||||
[<class 'preserves.schema.Enumeration'>, <class 'preserves.schema.SchemaObject'>]
|
||||
|
||||
>>> bundle.stream.Mode.packet.mro()[1:-1]
|
||||
[<class 'stream.Mode._ALL'>, <class 'preserves.schema.Definition'>, <class 'preserves.schema.SchemaObject'>]
|
||||
|
||||
>>> bundle.stream.StreamListenerError.mro()[1:-1]
|
||||
[<class 'preserves.schema.Definition'>, <class 'preserves.schema.SchemaObject'>]
|
||||
|
||||
```
|
||||
|
||||
Illustrating the class attributes on [SchemaObject][preserves.schema.SchemaObject]
|
||||
subclasses:
|
||||
|
||||
```python
|
||||
>>> bundle.stream.Mode.ROOTNS is bundle
|
||||
True
|
||||
|
||||
>>> print(stringify(bundle.stream.Mode.SCHEMA, indent=2))
|
||||
<or [
|
||||
[
|
||||
"bytes"
|
||||
<lit bytes>
|
||||
]
|
||||
[
|
||||
"lines"
|
||||
<ref [] LineMode>
|
||||
]
|
||||
[
|
||||
"packet"
|
||||
<rec <lit packet> <tuple [<named size <atom SignedInteger>>]>>
|
||||
]
|
||||
[
|
||||
"object"
|
||||
<rec <lit object> <tuple [<named description any>]>>
|
||||
]
|
||||
]>
|
||||
|
||||
>>> bundle.stream.Mode.MODULE_PATH
|
||||
(#stream,)
|
||||
|
||||
>>> bundle.stream.Mode.NAME
|
||||
#Mode
|
||||
|
||||
>>> bundle.stream.Mode.VARIANT is None
|
||||
True
|
||||
>>> bundle.stream.Mode.packet.VARIANT
|
||||
#packet
|
||||
|
||||
```
|
||||
|
||||
"""
|
||||
|
||||
ROOTNS = None
|
||||
"""A [Namespace][preserves.schema.Namespace] that is the top-level environment for all
|
||||
bundles included in the [Compiler][preserves.schema.Compiler] run that produced this
|
||||
[SchemaObject][preserves.schema.SchemaObject].
|
||||
|
||||
"""
|
||||
|
||||
SCHEMA = None
|
||||
"""A `Value` conforming to schema `meta.Definition` (and thus often to `meta.Pattern`
|
||||
etc.), interpreted by the [SchemaObject][preserves.schema.SchemaObject] machinery to drive
|
||||
parsing, unparsing and so forth."""
|
||||
|
||||
MODULE_PATH = None
|
||||
"""A sequence (tuple) of [Symbol][preserves.values.Symbol]s naming the path from the root
|
||||
to the schema module containing this definition."""
|
||||
|
||||
NAME = None
|
||||
"""A [Symbol][preserves.values.Symbol] naming this definition within its module."""
|
||||
|
||||
VARIANT = None
|
||||
"""`None` for [Definition][preserves.schema.Definition]s (such as
|
||||
`bundle.stream.StreamListenerError` above) and for overall
|
||||
[Enumeration][preserves.schema.Enumeration]s (such as `bundle.stream.Mode`), or a
|
||||
[Symbol][preserves.values.Symbol] for variant definitions *contained within* an enumeration
|
||||
(such as `bundle.stream.Mode.packet`).
|
||||
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def decode(cls, v):
|
||||
"""TODO"""
|
||||
"""Parses `v` using the [SCHEMA][preserves.schema.SchemaObject.SCHEMA], returning a
|
||||
(sub)instance of [SchemaObject][preserves.schema.SchemaObject] or raising
|
||||
[SchemaDecodeFailed][preserves.schema.SchemaDecodeFailed]."""
|
||||
raise NotImplementedError('Subclass responsibility')
|
||||
|
||||
@classmethod
|
||||
def try_decode(cls, v):
|
||||
"""TODO"""
|
||||
"""Parses `v` using the [SCHEMA][preserves.schema.SchemaObject.SCHEMA], returning a
|
||||
(sub)instance of [SchemaObject][preserves.schema.SchemaObject] or `None` if parsing
|
||||
failed."""
|
||||
try:
|
||||
return cls.decode(v)
|
||||
except SchemaDecodeFailed:
|
||||
|
@ -183,7 +536,8 @@ class SchemaObject:
|
|||
raise ValueError(f'Bad schema {p}')
|
||||
|
||||
def __preserve__(self):
|
||||
"""TODO"""
|
||||
"""Called by [preserves.values.preserve][]: *unparses* the information represented by
|
||||
this instance, using its schema definition, to produce a Preserves `Value`."""
|
||||
raise NotImplementedError('Subclass responsibility')
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -200,9 +554,29 @@ class SchemaObject:
|
|||
raise NotImplementedError('Subclass responsibility')
|
||||
|
||||
class Enumeration(SchemaObject):
|
||||
"""TODO"""
|
||||
"""Subclasses of [Enumeration][preserves.schema.Enumeration] represent a group of variant
|
||||
options within a sum type.
|
||||
|
||||
```python
|
||||
>>> bundle = load_schema_file('docs/syndicate-protocols-schema-bundle.bin')
|
||||
|
||||
>>> import pprint
|
||||
>>> pprint.pprint(bundle.stream.Mode.VARIANTS)
|
||||
[(#bytes, <class 'stream.Mode.bytes'>),
|
||||
(#lines, <class 'stream.Mode.lines'>),
|
||||
(#packet, <class 'stream.Mode.packet'>),
|
||||
(#object, <class 'stream.Mode.object'>)]
|
||||
|
||||
>>> bundle.stream.Mode.VARIANTS[0][1] is bundle.stream.Mode.bytes
|
||||
True
|
||||
|
||||
```
|
||||
|
||||
"""
|
||||
|
||||
VARIANTS = None
|
||||
"""List of `(Symbol, SchemaObject class)` tuples representing the possible options within
|
||||
this sum type."""
|
||||
|
||||
def __init__(self):
|
||||
raise TypeError('Cannot create instance of Enumeration')
|
||||
|
@ -237,6 +611,7 @@ class Enumeration(SchemaObject):
|
|||
raise TypeError('Cannot encode instance of Enumeration')
|
||||
|
||||
def safeattrname(k):
|
||||
"""Escapes Python keywords by prepending `_`; passes all other strings through."""
|
||||
return k + '_' if keyword.iskeyword(k) else k
|
||||
|
||||
def safesetattr(o, k, v):
|
||||
|
@ -249,13 +624,61 @@ def safehasattr(o, k):
|
|||
return hasattr(o, safeattrname(k))
|
||||
|
||||
class Definition(SchemaObject):
|
||||
"""TODO"""
|
||||
"""Subclasses of [Definition][preserves.schema.Definition] are used to represent both
|
||||
standalone non-alternation definitions as well as alternatives within an
|
||||
[Enumeration][preserves.schema.Enumeration].
|
||||
|
||||
```python
|
||||
>>> bundle = load_schema_file('docs/syndicate-protocols-schema-bundle.bin')
|
||||
|
||||
>>> bundle.stream.StreamListenerError.FIELD_NAMES
|
||||
['spec', 'message']
|
||||
>>> bundle.stream.StreamListenerError.SAFE_FIELD_NAMES
|
||||
['spec', 'message']
|
||||
>>> bundle.stream.StreamListenerError.ENUMERATION is None
|
||||
True
|
||||
|
||||
>>> bundle.stream.Mode.object.FIELD_NAMES
|
||||
['description']
|
||||
>>> bundle.stream.Mode.object.SAFE_FIELD_NAMES
|
||||
['description']
|
||||
>>> bundle.stream.Mode.object.ENUMERATION is bundle.stream.Mode
|
||||
True
|
||||
|
||||
>>> bundle.stream.CreditAmount.count.FIELD_NAMES
|
||||
[]
|
||||
>>> bundle.stream.CreditAmount.count.SAFE_FIELD_NAMES
|
||||
[]
|
||||
>>> bundle.stream.CreditAmount.count.ENUMERATION is bundle.stream.CreditAmount
|
||||
True
|
||||
|
||||
>>> bundle.stream.CreditAmount.decode(parse('123'))
|
||||
CreditAmount.count(123)
|
||||
>>> bundle.stream.CreditAmount.count(123)
|
||||
CreditAmount.count(123)
|
||||
>>> bundle.stream.CreditAmount.count(123).value
|
||||
123
|
||||
|
||||
```
|
||||
|
||||
"""
|
||||
|
||||
EMPTY = False
|
||||
SIMPLE = False
|
||||
|
||||
FIELD_NAMES = []
|
||||
"""List of strings: names of the fields contained within this definition, if it has named
|
||||
fields at all; otherwise, an empty list, and the definition is a simple wrapper for another
|
||||
value, in which case that value is accessed via the `value` attribute."""
|
||||
|
||||
SAFE_FIELD_NAMES = []
|
||||
"""The list produced by mapping [safeattrname][preserves.schema.safeattrname] over
|
||||
[FIELD_NAMES][preserves.schema.Definition.FIELD_NAMES]."""
|
||||
|
||||
ENUMERATION = None
|
||||
"""`None` for standalone top-level definitions with a module; otherwise, an
|
||||
[Enumeration][preserves.schema.Enumeration] subclass representing a top-level alternation
|
||||
definition."""
|
||||
|
||||
def _constructor_name(self):
|
||||
if self.VARIANT is None:
|
||||
|
@ -357,7 +780,6 @@ class escape:
|
|||
return self.escaped
|
||||
|
||||
def encode(p, v):
|
||||
"""TODO"""
|
||||
if hasattr(v, '__escape_schema__'):
|
||||
return preserve(v.__escape_schema__())
|
||||
if p == ANY:
|
||||
|
@ -444,7 +866,13 @@ def definition_not_found(module_path, name):
|
|||
raise KeyError('Definition not found: ' + module_path_str(module_path + (name,)))
|
||||
|
||||
class Namespace:
|
||||
"""TODO"""
|
||||
"""A [Namespace][preserves.schema.Namespace] is a dictionary-like object representing a
|
||||
schema module that knows its location in a schema module hierarchy and whose attributes
|
||||
correspond to definitions and submodules within the schema module.
|
||||
|
||||
Attributes:
|
||||
_prefix (tuple[Symbol]): path to this module/Namespace from the root Namespace
|
||||
"""
|
||||
def __init__(self, prefix):
|
||||
self._prefix = prefix
|
||||
|
||||
|
@ -467,22 +895,50 @@ class Namespace:
|
|||
return repr(self._items())
|
||||
|
||||
class Compiler:
|
||||
"""TODO"""
|
||||
"""Instances of [Compiler][preserves.schema.Compiler] populate an initially-empty
|
||||
[Namespace][preserves.schema.Namespace] by loading and compiling schema bundle files.
|
||||
|
||||
```python
|
||||
>>> c = Compiler()
|
||||
>>> c.load('docs/syndicate-protocols-schema-bundle.bin')
|
||||
>>> type(c.root)
|
||||
<class 'preserves.schema.Namespace'>
|
||||
|
||||
```
|
||||
|
||||
Attributes:
|
||||
root (Namespace): the root namespace into which top-level schema modules are installed.
|
||||
"""
|
||||
def __init__(self):
|
||||
self.root = Namespace(())
|
||||
|
||||
def load_filelike(self, module_path, f):
|
||||
def load_filelike(self, f, module_name=None):
|
||||
"""Reads a `meta.Bundle` or `meta.Schema` from the filelike object `f`, compiling and
|
||||
installing it in `self.root`. If `f` contains a bundle, `module_name` is not used,
|
||||
since the schema modules in the bundle know their own names; if `f` contains a plain
|
||||
schema module, however, `module_name` is used directly if it is a string, and if it is
|
||||
`None`, a suitable module name is computed from the `name` attribute of `f`, if it is
|
||||
present. If `name` is absent in that case, `ValueError` is raised.
|
||||
|
||||
"""
|
||||
x = Decoder(f.read()).next()
|
||||
if x.key == SCHEMA:
|
||||
self.load_schema((Symbol(module_path),), x)
|
||||
if module_name is None:
|
||||
if hasattr(f, 'name'):
|
||||
module_name = pathlib.Path(f.name).stem
|
||||
else:
|
||||
raise ValueError('Cannot load schema module from filelike object without a module_name')
|
||||
self.load_schema((Symbol(module_name),), x)
|
||||
elif x.key == BUNDLE:
|
||||
for (p, s) in x[0].items():
|
||||
self.load_schema(p, s)
|
||||
|
||||
def load(self, filename):
|
||||
"""Opens the file at `filename`, passing the resulting file object to
|
||||
[load_filelike][preserves.schema.Compiler.load_filelike]."""
|
||||
filename = pathlib.Path(filename)
|
||||
with open(filename, 'rb') as f:
|
||||
self.load_filelike(filename.stem, f)
|
||||
self.load_filelike(f, filename.stem)
|
||||
|
||||
def load_schema(self, module_path, schema):
|
||||
if schema[0][VERSION] != 1:
|
||||
|
@ -502,14 +958,50 @@ class Compiler:
|
|||
ns[n] = c
|
||||
|
||||
def load_schema_file(filename):
|
||||
"""TODO"""
|
||||
"""Simple entry point to the compiler: creates a [Compiler][preserves.schema.Compiler],
|
||||
calls [load][preserves.schema.Compiler.load] on it, and returns its `root`
|
||||
[Namespace][preserves.schema.Namespace].
|
||||
|
||||
```python
|
||||
>>> bundle = load_schema_file('docs/syndicate-protocols-schema-bundle.bin')
|
||||
>>> type(bundle)
|
||||
<class 'preserves.schema.Namespace'>
|
||||
|
||||
```
|
||||
"""
|
||||
c = Compiler()
|
||||
c.load(filename)
|
||||
return c.root
|
||||
|
||||
# a decorator
|
||||
def extend(cls):
|
||||
"""TODO"""
|
||||
"""A decorator for function definitions. Useful for adding *behaviour* to the classes
|
||||
resulting from loading a schema module:
|
||||
|
||||
```python
|
||||
>>> bundle = load_schema_file('docs/syndicate-protocols-schema-bundle.bin')
|
||||
|
||||
>>> @extend(bundle.stream.LineMode.lf)
|
||||
... def what_am_i(self):
|
||||
... return 'I am a LINEFEED linemode'
|
||||
|
||||
>>> @extend(bundle.stream.LineMode.crlf)
|
||||
... def what_am_i(self):
|
||||
... return 'I am a CARRIAGE-RETURN-PLUS-LINEFEED linemode'
|
||||
|
||||
>>> bundle.stream.LineMode.lf()
|
||||
LineMode.lf()
|
||||
>>> bundle.stream.LineMode.lf().what_am_i()
|
||||
'I am a LINEFEED linemode'
|
||||
|
||||
>>> bundle.stream.LineMode.crlf()
|
||||
LineMode.crlf()
|
||||
>>> bundle.stream.LineMode.crlf().what_am_i()
|
||||
'I am a CARRIAGE-RETURN-PLUS-LINEFEED linemode'
|
||||
|
||||
```
|
||||
|
||||
"""
|
||||
@wraps(cls)
|
||||
def extender(f):
|
||||
setattr(cls, f.__name__, f)
|
||||
|
@ -518,7 +1010,8 @@ def extend(cls):
|
|||
|
||||
__metaschema_filename = pathlib.Path(__file__).parent / 'schema.prb'
|
||||
meta = load_schema_file(__metaschema_filename).schema
|
||||
"""TODO"""
|
||||
"""Schema module [Namespace][preserves.schema.Namespace] corresponding to [Preserves Schema's
|
||||
metaschema](https://preserves.dev/preserves-schema.html#appendix-metaschema)."""
|
||||
|
||||
if __name__ == '__main__':
|
||||
with open(__metaschema_filename, 'rb') as f:
|
||||
|
|
|
@ -195,7 +195,9 @@ class Symbol(object):
|
|||
```
|
||||
|
||||
Attributes:
|
||||
name (str): the symbol's text label
|
||||
name (str | Symbol):
|
||||
The symbol's text label. If an existing [Symbol][preserves.values.Symbol] is passed
|
||||
in, the existing Symbol's `name` is used as the `name` for the new Symbol.
|
||||
"""
|
||||
def __init__(self, name):
|
||||
self.name = name.name if isinstance(name, Symbol) else name
|
||||
|
|
|
@ -13,22 +13,7 @@ This document proposes a Schema language for the
|
|||
|
||||
## Introduction
|
||||
|
||||
A Preserves schema connects Preserves `Value`s to host-language data
|
||||
structures. Each definition within a schema can be processed by a
|
||||
compiler to produce
|
||||
|
||||
- a simple host-language *type definition*;
|
||||
|
||||
- a partial *parsing* function from `Value`s to instances of the
|
||||
produced type; and
|
||||
|
||||
- a total *serialization* function from instances of the type to
|
||||
`Value`s.
|
||||
|
||||
Every parsed `Value` retains enough information to always be able to
|
||||
be serialized again, and every instance of a host-language data
|
||||
structure contains, by construction, enough information to be
|
||||
successfully serialized.
|
||||
{% include what-is-preserves-schema.md %}
|
||||
|
||||
**Portability.** Preserves Schema is broadly portable. Any host-language
|
||||
type system that can represent [algebraic
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -904,9 +904,9 @@ about annotations</a>.</p>
|
|||
|
||||
<details class="quote">
|
||||
<summary>Source code in <code>preserves/values.py</code></summary>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">573</span>
|
||||
<span class="normal">574</span>
|
||||
<span class="normal">575</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">):</span>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">575</span>
|
||||
<span class="normal">576</span>
|
||||
<span class="normal">577</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">annotations</span> <span class="o">=</span> <span class="p">[]</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">item</span> <span class="o">=</span> <span class="n">item</span>
|
||||
</code></pre></div></td></tr></table></div>
|
||||
|
@ -940,9 +940,9 @@ about annotations</a>.</p>
|
|||
|
||||
<details class="quote">
|
||||
<summary>Source code in <code>preserves/values.py</code></summary>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">596</span>
|
||||
<span class="normal">597</span>
|
||||
<span class="normal">598</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="nf">peel</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">598</span>
|
||||
<span class="normal">599</span>
|
||||
<span class="normal">600</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="nf">peel</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
||||
<span class="w"> </span><span class="sd">"""Calls [strip_annotations][preserves.values.strip_annotations] on `self` with `depth=1`."""</span>
|
||||
<span class="k">return</span> <span class="n">strip_annotations</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
||||
</code></pre></div></td></tr></table></div>
|
||||
|
@ -967,9 +967,9 @@ about annotations</a>.</p>
|
|||
|
||||
<details class="quote">
|
||||
<summary>Source code in <code>preserves/values.py</code></summary>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">592</span>
|
||||
<span class="normal">593</span>
|
||||
<span class="normal">594</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="nf">strip</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">depth</span><span class="o">=</span><span class="n">inf</span><span class="p">):</span>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">594</span>
|
||||
<span class="normal">595</span>
|
||||
<span class="normal">596</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="nf">strip</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">depth</span><span class="o">=</span><span class="n">inf</span><span class="p">):</span>
|
||||
<span class="w"> </span><span class="sd">"""Calls [strip_annotations][preserves.values.strip_annotations] on `self` and `depth`."""</span>
|
||||
<span class="k">return</span> <span class="n">strip_annotations</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">depth</span><span class="p">)</span>
|
||||
</code></pre></div></td></tr></table></div>
|
||||
|
@ -1040,8 +1040,8 @@ Preserves <code>Value</code>, could be <code>None</code>, could be anything!</p>
|
|||
|
||||
<details class="quote">
|
||||
<summary>Source code in <code>preserves/values.py</code></summary>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">718</span>
|
||||
<span class="normal">719</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">embeddedValue</span><span class="p">):</span>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">720</span>
|
||||
<span class="normal">721</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">embeddedValue</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">embeddedValue</span> <span class="o">=</span> <span class="n">embeddedValue</span>
|
||||
</code></pre></div></td></tr></table></div>
|
||||
</details>
|
||||
|
@ -1397,10 +1397,10 @@ other dictionaries.</p>
|
|||
|
||||
<details class="quote">
|
||||
<summary>Source code in <code>preserves/values.py</code></summary>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">459</span>
|
||||
<span class="normal">460</span>
|
||||
<span class="normal">461</span>
|
||||
<span class="normal">462</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">461</span>
|
||||
<span class="normal">462</span>
|
||||
<span class="normal">463</span>
|
||||
<span class="normal">464</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
||||
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s1">'__hash'</span><span class="p">):</span> <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s1">'Immutable'</span><span class="p">)</span>
|
||||
<span class="nb">super</span><span class="p">(</span><span class="n">ImmutableDict</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">__hash</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
|
@ -1449,9 +1449,7 @@ key-value pairs.</p>
|
|||
|
||||
<details class="quote">
|
||||
<summary>Source code in <code>preserves/values.py</code></summary>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">480</span>
|
||||
<span class="normal">481</span>
|
||||
<span class="normal">482</span>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">482</span>
|
||||
<span class="normal">483</span>
|
||||
<span class="normal">484</span>
|
||||
<span class="normal">485</span>
|
||||
|
@ -1481,7 +1479,9 @@ key-value pairs.</p>
|
|||
<span class="normal">509</span>
|
||||
<span class="normal">510</span>
|
||||
<span class="normal">511</span>
|
||||
<span class="normal">512</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="nd">@staticmethod</span>
|
||||
<span class="normal">512</span>
|
||||
<span class="normal">513</span>
|
||||
<span class="normal">514</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="nd">@staticmethod</span>
|
||||
<span class="k">def</span> <span class="nf">from_kvs</span><span class="p">(</span><span class="n">kvs</span><span class="p">):</span>
|
||||
<span class="w"> </span><span class="sd">"""Constructs an [ImmutableDict][preserves.values.ImmutableDict] from a sequence of</span>
|
||||
<span class="sd"> alternating keys and values; compare to the</span>
|
||||
|
@ -1622,10 +1622,10 @@ key-value pairs.</p>
|
|||
|
||||
<details class="quote">
|
||||
<summary>Source code in <code>preserves/values.py</code></summary>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">271</span>
|
||||
<span class="normal">272</span>
|
||||
<span class="normal">273</span>
|
||||
<span class="normal">274</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">fields</span><span class="p">):</span>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">273</span>
|
||||
<span class="normal">274</span>
|
||||
<span class="normal">275</span>
|
||||
<span class="normal">276</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">fields</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">fields</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">fields</span><span class="p">)</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">__hash</span> <span class="o">=</span> <span class="kc">None</span>
|
||||
|
@ -1739,9 +1739,7 @@ argument.</p>
|
|||
|
||||
<details class="quote">
|
||||
<summary>Source code in <code>preserves/values.py</code></summary>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">319</span>
|
||||
<span class="normal">320</span>
|
||||
<span class="normal">321</span>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">321</span>
|
||||
<span class="normal">322</span>
|
||||
<span class="normal">323</span>
|
||||
<span class="normal">324</span>
|
||||
|
@ -1818,7 +1816,9 @@ argument.</p>
|
|||
<span class="normal">395</span>
|
||||
<span class="normal">396</span>
|
||||
<span class="normal">397</span>
|
||||
<span class="normal">398</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="nd">@staticmethod</span>
|
||||
<span class="normal">398</span>
|
||||
<span class="normal">399</span>
|
||||
<span class="normal">400</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="nd">@staticmethod</span>
|
||||
<span class="k">def</span> <span class="nf">makeBasicConstructor</span><span class="p">(</span><span class="n">label</span><span class="p">,</span> <span class="n">fieldNames</span><span class="p">):</span>
|
||||
<span class="w"> </span><span class="sd">"""Constructs and returns a "constructor" for `Record`s having a certain `label` and</span>
|
||||
<span class="sd"> number of fields.</span>
|
||||
|
@ -1928,15 +1928,15 @@ argument.</p>
|
|||
</details>
|
||||
<details class="quote">
|
||||
<summary>Source code in <code>preserves/values.py</code></summary>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">309</span>
|
||||
<span class="normal">310</span>
|
||||
<span class="normal">311</span>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">311</span>
|
||||
<span class="normal">312</span>
|
||||
<span class="normal">313</span>
|
||||
<span class="normal">314</span>
|
||||
<span class="normal">315</span>
|
||||
<span class="normal">316</span>
|
||||
<span class="normal">317</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="nd">@staticmethod</span>
|
||||
<span class="normal">317</span>
|
||||
<span class="normal">318</span>
|
||||
<span class="normal">319</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="nd">@staticmethod</span>
|
||||
<span class="k">def</span> <span class="nf">makeConstructor</span><span class="p">(</span><span class="n">labelSymbolText</span><span class="p">,</span> <span class="n">fieldNames</span><span class="p">):</span>
|
||||
<span class="w"> </span><span class="sd">"""</span>
|
||||
<span class="sd"> Equivalent to `Record.makeBasicConstructor(Symbol(labelSymbolText), fieldNames)`.</span>
|
||||
|
@ -2010,9 +2010,9 @@ count).</p>
|
|||
|
||||
<details class="quote">
|
||||
<summary>Source code in <code>preserves/values.py</code></summary>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">414</span>
|
||||
<span class="normal">415</span>
|
||||
<span class="normal">416</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">arity</span><span class="p">):</span>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">416</span>
|
||||
<span class="normal">417</span>
|
||||
<span class="normal">418</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">arity</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">arity</span> <span class="o">=</span> <span class="n">arity</span>
|
||||
</code></pre></div></td></tr></table></div>
|
||||
|
@ -2082,9 +2082,10 @@ count).</p>
|
|||
<tr>
|
||||
<td><code>name</code></td>
|
||||
<td>
|
||||
<code>str</code>
|
||||
<code>str | <a class="autorefs autorefs-internal" title="preserves.values.Symbol" href="#preserves.values.Symbol">Symbol</a></code>
|
||||
</td>
|
||||
<td><p>the symbol's text label</p></td>
|
||||
<td><p>The symbol's text label. If an existing <a class="autorefs autorefs-internal" href="#preserves.values.Symbol">Symbol</a> is passed
|
||||
in, the existing Symbol's <code>name</code> is used as the <code>name</code> for the new Symbol.</p></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -2092,8 +2093,8 @@ count).</p>
|
|||
|
||||
<details class="quote">
|
||||
<summary>Source code in <code>preserves/values.py</code></summary>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">200</span>
|
||||
<span class="normal">201</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">202</span>
|
||||
<span class="normal">203</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
|
||||
<span class="bp">self</span><span class="o">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span><span class="o">.</span><span class="n">name</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">Symbol</span><span class="p">)</span> <span class="k">else</span> <span class="n">name</span>
|
||||
</code></pre></div></td></tr></table></div>
|
||||
</details>
|
||||
|
@ -2142,9 +2143,7 @@ wrapped, and appends each of the <code>anns</code> to the <a class="autorefs aut
|
|||
|
||||
<details class="quote">
|
||||
<summary>Source code in <code>preserves/values.py</code></summary>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">662</span>
|
||||
<span class="normal">663</span>
|
||||
<span class="normal">664</span>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">664</span>
|
||||
<span class="normal">665</span>
|
||||
<span class="normal">666</span>
|
||||
<span class="normal">667</span>
|
||||
|
@ -2159,7 +2158,9 @@ wrapped, and appends each of the <code>anns</code> to the <a class="autorefs aut
|
|||
<span class="normal">676</span>
|
||||
<span class="normal">677</span>
|
||||
<span class="normal">678</span>
|
||||
<span class="normal">679</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="nf">annotate</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="o">*</span><span class="n">anns</span><span class="p">):</span>
|
||||
<span class="normal">679</span>
|
||||
<span class="normal">680</span>
|
||||
<span class="normal">681</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="nf">annotate</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="o">*</span><span class="n">anns</span><span class="p">):</span>
|
||||
<span class="w"> </span><span class="sd">"""Wraps `v` in an [Annotated][preserves.values.Annotated] object, if it isn't already</span>
|
||||
<span class="sd"> wrapped, and appends each of the `anns` to the [Annotated][preserves.values.Annotated]'s</span>
|
||||
<span class="sd"> `annotations` sequence. NOTE: Does not recursively ensure that any parts of the argument</span>
|
||||
|
@ -2245,9 +2246,7 @@ sense the inverse of <a class="autorefs autorefs-internal" href="#preserves.valu
|
|||
|
||||
<details class="quote">
|
||||
<summary>Source code in <code>preserves/values.py</code></summary>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">514</span>
|
||||
<span class="normal">515</span>
|
||||
<span class="normal">516</span>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">516</span>
|
||||
<span class="normal">517</span>
|
||||
<span class="normal">518</span>
|
||||
<span class="normal">519</span>
|
||||
|
@ -2257,7 +2256,9 @@ sense the inverse of <a class="autorefs autorefs-internal" href="#preserves.valu
|
|||
<span class="normal">523</span>
|
||||
<span class="normal">524</span>
|
||||
<span class="normal">525</span>
|
||||
<span class="normal">526</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="nf">dict_kvs</span><span class="p">(</span><span class="n">d</span><span class="p">):</span>
|
||||
<span class="normal">526</span>
|
||||
<span class="normal">527</span>
|
||||
<span class="normal">528</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="nf">dict_kvs</span><span class="p">(</span><span class="n">d</span><span class="p">):</span>
|
||||
<span class="w"> </span><span class="sd">"""Generator function yielding a sequence of alternating keys and values from `d`. In some</span>
|
||||
<span class="sd"> sense the inverse of [ImmutableDict.from_kvs][preserves.values.ImmutableDict.from_kvs].</span>
|
||||
|
||||
|
@ -2292,9 +2293,9 @@ sense the inverse of <a class="autorefs autorefs-internal" href="#preserves.valu
|
|||
|
||||
<details class="quote">
|
||||
<summary>Source code in <code>preserves/values.py</code></summary>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">612</span>
|
||||
<span class="normal">613</span>
|
||||
<span class="normal">614</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="nf">is_annotated</span><span class="p">(</span><span class="n">v</span><span class="p">):</span>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">614</span>
|
||||
<span class="normal">615</span>
|
||||
<span class="normal">616</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="nf">is_annotated</span><span class="p">(</span><span class="n">v</span><span class="p">):</span>
|
||||
<span class="w"> </span><span class="sd">"""`True` iff `v` is an instance of [Annotated][preserves.values.Annotated]."""</span>
|
||||
<span class="k">return</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">Annotated</span><span class="p">)</span>
|
||||
</code></pre></div></td></tr></table></div>
|
||||
|
@ -2386,9 +2387,7 @@ into the structure of <code>v.item</code>.</p>
|
|||
|
||||
<details class="quote">
|
||||
<summary>Source code in <code>preserves/values.py</code></summary>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">616</span>
|
||||
<span class="normal">617</span>
|
||||
<span class="normal">618</span>
|
||||
<div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal">618</span>
|
||||
<span class="normal">619</span>
|
||||
<span class="normal">620</span>
|
||||
<span class="normal">621</span>
|
||||
|
@ -2430,7 +2429,9 @@ into the structure of <code>v.item</code>.</p>
|
|||
<span class="normal">657</span>
|
||||
<span class="normal">658</span>
|
||||
<span class="normal">659</span>
|
||||
<span class="normal">660</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="nf">strip_annotations</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">depth</span><span class="o">=</span><span class="n">inf</span><span class="p">):</span>
|
||||
<span class="normal">660</span>
|
||||
<span class="normal">661</span>
|
||||
<span class="normal">662</span></pre></div></td><td class="code"><div><pre><span></span><code><span class="k">def</span> <span class="nf">strip_annotations</span><span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">depth</span><span class="o">=</span><span class="n">inf</span><span class="p">):</span>
|
||||
<span class="w"> </span><span class="sd">"""Exposes `depth` layers of raw structure of</span>
|
||||
<span class="sd"> potentially-[Annotated][preserves.values.Annotated] `Value`s. If `depth==0` or `v` is not</span>
|
||||
<span class="sd"> [Annotated][preserves.values.Annotated], just returns `v`. Otherwise, descends recursively</span>
|
||||
|
|
Loading…
Reference in New Issue