Skip to content

Commit

Permalink
fix(Node): Expand the Node union type to include all entity types
Browse files Browse the repository at this point in the history
  • Loading branch information
nokome committed Jun 4, 2021
1 parent de9ffd0 commit b658222
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 23 deletions.
4 changes: 2 additions & 2 deletions python/stencila/schema/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from .types import Node, Entity


def decode(serialized: str) -> typing.Union[dict, Node]:
def decode(serialized: str) -> Node:
"""Decode JSON as a `Node`"""
node = json.loads(serialized)
return dict_decode(node) if isinstance(node, dict) else node
Expand All @@ -24,7 +24,7 @@ def encode(node: Node) -> str:
return json.dumps(node, default=object_encode, indent=2)


def dict_decode(node_dict: dict) -> typing.Union[dict, Entity]:
def dict_decode(node_dict: dict) -> Node:
"""Convert a dictionary to an `Entity` node (if it has a `type` item)."""
if "type" not in node_dict:
return node_dict
Expand Down
4 changes: 2 additions & 2 deletions python/stencila/schema/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -4412,9 +4412,9 @@ class CitationIntentEnumeration(Enum):


"""
Union type for all valid nodes.
Union type for all schema nodes, including primitives and entities
"""
Node = Union["Entity", None, bool, int, float, str, Dict[str, Any], Array[Any]]
Node = Union["ArrayValidator", "Article", "AudioObject", "BooleanValidator", "Brand", "CitationIntentEnumeration", "Cite", "CiteGroup", "Claim", "Code", "CodeBlock", "CodeChunk", "CodeError", "CodeExpression", "CodeFragment", "Collection", "Comment", "ConstantValidator", "ContactPoint", "CreativeWork", "Datatable", "DatatableColumn", "Date", "DefinedTerm", "Delete", "Emphasis", "EnumValidator", "Enumeration", "Figure", "Function", "Grant", "Heading", "ImageObject", "Include", "IntegerValidator", "Link", "List", "ListItem", "Mark", "Math", "MathBlock", "MathFragment", "MediaObject", "MonetaryGrant", "NontextualAnnotation", "Note", "NumberValidator", "Organization", "Paragraph", "Parameter", "Periodical", "Person", "PostalAddress", "Product", "PropertyValue", "PublicationIssue", "PublicationVolume", "Quote", "QuoteBlock", "Review", "SoftwareApplication", "SoftwareEnvironment", "SoftwareSession", "SoftwareSourceCode", "StringValidator", "Strong", "Subscript", "Superscript", "Table", "TableCell", "TableRow", "ThematicBreak", "Thing", "TupleValidator", "Validator", "Variable", "VideoObject", "VolumeMount", None, bool, int, float, str, Dict[str, Any], Array[Any]]


"""
Expand Down
4 changes: 2 additions & 2 deletions r/R/types.R
Original file line number Diff line number Diff line change
Expand Up @@ -4508,11 +4508,11 @@ MathTypes <- Union(Math, MathBlock, MathFragment)
MediaObjectTypes <- Union(MediaObject, AudioObject, ImageObject, VideoObject)


#' Union type for all valid nodes.
#' Union type for all schema nodes, including primitives and entities
#'
#' @return A `list` of class `Union` describing valid subtypes of this type
#' @export
Node <- Union(Entity, "NULL", "logical", "numeric", "character", "list", Array(Any()))
Node <- Union(ArrayValidator, Article, AudioObject, BooleanValidator, Brand, CitationIntentEnumeration, Cite, CiteGroup, Claim, Code, CodeBlock, CodeChunk, CodeError, CodeExpression, CodeFragment, Collection, Comment, ConstantValidator, ContactPoint, CreativeWork, Datatable, DatatableColumn, Date, DefinedTerm, Delete, Emphasis, EnumValidator, Enumeration, Figure, Function, Grant, Heading, ImageObject, Include, IntegerValidator, Link, List, ListItem, Mark, Math, MathBlock, MathFragment, MediaObject, MonetaryGrant, NontextualAnnotation, Note, NumberValidator, Organization, Paragraph, Parameter, Periodical, Person, PostalAddress, Product, PropertyValue, PublicationIssue, PublicationVolume, Quote, QuoteBlock, Review, SoftwareApplication, SoftwareEnvironment, SoftwareSession, SoftwareSourceCode, StringValidator, Strong, Subscript, Superscript, Table, TableCell, TableRow, ThematicBreak, Thing, TupleValidator, Validator, Variable, VideoObject, VolumeMount, "NULL", "logical", "numeric", "character", "list", Array(Any()))


#' All type schemas that are derived from Thing
Expand Down
99 changes: 91 additions & 8 deletions rust/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,8 @@ pub struct CodeExpression {
pub meta: Option<Object>,

/// The value of the expression when it was last evaluated.
pub output: Option<Node>,
#[serde(skip)]
pub output: Option<Arc<Node>>,

/// The programming language of the code.
pub programming_language: Option<String>,
Expand Down Expand Up @@ -1593,7 +1594,8 @@ pub struct ConstantValidator {
pub meta: Option<Object>,

/// The value that the node must have.
pub value: Option<Node>,
#[serde(skip)]
pub value: Option<Arc<Node>>,
}
impl_type!(ConstantValidator);

Expand Down Expand Up @@ -2125,7 +2127,8 @@ pub struct ListItem {
pub is_checked: Option<Bool>,

/// The item represented by this list item.
pub item: Option<Node>,
#[serde(skip)]
pub item: Option<Arc<Node>>,

/// Metadata associated with this item.
pub meta: Option<Object>,
Expand Down Expand Up @@ -2462,7 +2465,8 @@ pub struct Variable {
pub validator: Option<ValidatorTypes>,

/// The value of the variable.
pub value: Option<Node>,
#[serde(skip)]
pub value: Option<Arc<Node>>,
}
impl_type!(Variable);

Expand All @@ -2480,7 +2484,8 @@ pub struct Parameter {
pub name: String,

/// The default value of the parameter.
pub default: Option<Node>,
#[serde(skip)]
pub default: Option<Arc<Node>>,

/// The identifier for this item.
pub id: Option<String>,
Expand All @@ -2504,7 +2509,8 @@ pub struct Parameter {
pub validator: Option<ValidatorTypes>,

/// The value of the variable.
pub value: Option<Node>,
#[serde(skip)]
pub value: Option<Arc<Node>>,
}
impl_type!(Parameter);

Expand Down Expand Up @@ -4969,11 +4975,88 @@ pub enum MediaObjectTypes {
VideoObject(VideoObject),
}

/// Union type for all valid nodes.
/// Union type for all schema nodes, including primitives and entities
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Node {
Entity(Entity),
ArrayValidator(ArrayValidator),
Article(Article),
AudioObject(AudioObject),
BooleanValidator(BooleanValidator),
Brand(Brand),
CitationIntentEnumeration(CitationIntentEnumeration),
Cite(Cite),
CiteGroup(CiteGroup),
Claim(Claim),
Code(Code),
CodeBlock(CodeBlock),
CodeChunk(CodeChunk),
CodeError(CodeError),
CodeExpression(CodeExpression),
CodeFragment(CodeFragment),
Collection(Collection),
Comment(Comment),
ConstantValidator(ConstantValidator),
ContactPoint(ContactPoint),
CreativeWork(CreativeWork),
Datatable(Datatable),
DatatableColumn(DatatableColumn),
Date(Date),
DefinedTerm(DefinedTerm),
Delete(Delete),
Emphasis(Emphasis),
EnumValidator(EnumValidator),
Enumeration(Enumeration),
Figure(Figure),
Function(Function),
Grant(Grant),
Heading(Heading),
ImageObject(ImageObject),
Include(Include),
IntegerValidator(IntegerValidator),
Link(Link),
List(List),
ListItem(ListItem),
Mark(Mark),
Math(Math),
MathBlock(MathBlock),
MathFragment(MathFragment),
MediaObject(MediaObject),
MonetaryGrant(MonetaryGrant),
NontextualAnnotation(NontextualAnnotation),
Note(Note),
NumberValidator(NumberValidator),
Organization(Organization),
Paragraph(Paragraph),
Parameter(Parameter),
Periodical(Periodical),
Person(Person),
PostalAddress(PostalAddress),
Product(Product),
PropertyValue(PropertyValue),
PublicationIssue(PublicationIssue),
PublicationVolume(PublicationVolume),
Quote(Quote),
QuoteBlock(QuoteBlock),
Review(Review),
SoftwareApplication(SoftwareApplication),
SoftwareEnvironment(SoftwareEnvironment),
SoftwareSession(SoftwareSession),
SoftwareSourceCode(SoftwareSourceCode),
StringValidator(StringValidator),
Strong(Strong),
Subscript(Subscript),
Superscript(Superscript),
Table(Table),
TableCell(TableCell),
TableRow(TableRow),
ThematicBreak(ThematicBreak),
Thing(Thing),
TupleValidator(TupleValidator),
Validator(Validator),
Variable(Variable),
VideoObject(VideoObject),
VolumeMount(VolumeMount),
Null,
Bool(Bool),
Integer(Integer),
Expand Down
5 changes: 1 addition & 4 deletions schema/InlineContent.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,8 @@ category: text
status: stable
description: Union type for valid inline content.
$comment: |
Note that this definition currently does not include
`array` and `object` nodes (which are included in `Node`).
This seems incongruent, and may be changed in the future.
The order of these types is important because it determines the
order of attempted coercion (particularly important for primitive types).
order of attempted coercion (this is particularly important for primitive types).
anyOf:
# Entity types in alphabetical order
- $ref: AudioObject
Expand Down
10 changes: 5 additions & 5 deletions schema/Node.schema.yaml
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
title: Node
category: other
status: unstable
description: Union type for all valid nodes.
description: Union type for all schema nodes, including primitives and entities
$comment: |
The entity types in this union are automatically inserted during the build.
The order of these types is important because it determines the
order of attempted coercion (ie. parsing and reshaping to arrays)
order of attempted coercion (ie. parsing and reshaping to arrays).
Array should come last to avoid single items (e.g. a single string)
being coerced into an array.
anyOf:
- $ref: Entity
- type: 'null'
- type: boolean
- type: integer
- type: number
- type: string
- type: object
# Array should come last to avoid single items (e.g. a single string)
# being coerced into an array.
- type: array
6 changes: 6 additions & 0 deletions ts/bindings/rust.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,15 @@ const pointerProperties = [
'Organization.parentOrganization',
'ImageObject.publisher', // recursive because publisher has `logo`
'ImageObject.thumbnail',
'ListItem.item',
'Comment.parentItem',
'ArrayValidator.contains',
'ArrayValidator.itemsValidator',
'ConstantValidator.value',
'CodeExpression.output',
'Parameter.default',
'Parameter.value',
'Variable.value',
]

/**
Expand Down
17 changes: 17 additions & 0 deletions ts/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ export async function build(cleanup = true): Promise<void> {
// Process each of the schemas
schemata.forEach((schema) => processSchema(schemas, schema))

// Update the `Node` union schema`
updateNodeSchema(schemas)

// Generate additional schemas
addTypesSchemas(schemas)

Expand Down Expand Up @@ -440,6 +443,20 @@ const parentSchema = (
return parent
}

/**
* Add all entity types to the `Node` union schema.
*/
const updateNodeSchema = (schemas: Map<string, JsonSchema>): void => {
const entitySchema = schemas.get('Entity') as JsonSchema
const entityRefs = (entitySchema.descendants ?? []).map((descendant) => ({
$ref: `${descendant}.schema.json`,
}))

const nodeSchema = schemas.get('Node') as JsonSchema
nodeSchema.anyOf = [...(entityRefs ?? []), ...(nodeSchema.anyOf ?? [])]
schemas.set('Node', nodeSchema)
}

/**
* Add `*Types` schemas to the map of schemas which
* are the union (`anyOf`) of any descendant types
Expand Down

0 comments on commit b658222

Please sign in to comment.