pycapnp icon indicating copy to clipboard operation
pycapnp copied to clipboard

Support for annotations

Open kfir-drivenets opened this issue 9 years ago • 2 comments

cap'n proto defines annotations (https://capnproto.org/language.html). Annotations allows powerful features to be added.

Consider the following example

@0x934efea7f017fff0;

struct Range {
    min @0 :UInt32;
    max @1 :UInt32;
}

annotation checkRange(field) :Range;

struct Example {
    val @0 :UInt32 $checkRange(min = 1, max = 5);
}

In the given example annotation was added for validation on a field value. It would be create to do something like the following

import capnp
import example_capnp

range = example_capnp.Example.fields['val'].annotations['checkRange']
a = 5
if a > range.min and a < range.max:
  ....

Basically this will allow users of the library to pass arbitrary information from the capnp file to the python parser. This has great potential for this like generating CLI form capnp file, custom validators and a lot more.

kfir-drivenets avatar Sep 07 '16 06:09 kfir-drivenets

This will be extremely helpful. I could help with that but I am in need of some guidance.

doron-cohen avatar Jan 15 '17 20:01 doron-cohen

Currently, this is possible to achieve, but it's really gruesome. Using example from @kfir-drivenets :

import capnpy
example_capnp = capnp.load("example_capnp")

val_field = example_capnp.Example.schema.fields['val']
val_ann = val_field.proto.annotations[0]
val_range = val_ann.value.struct.as_struct(example_capnp.Range)

This works if we know that there is only one annotation on the field val and that it is always of the type example_capnp.Range. However if that wasn't known:

  • val_ann.name doesn't exist. But, it is possible to match the annotation id val_ann.id in the list example_capnp.schema.node.nestedNodes and get the name from there
  • to change the val_ann.value to a struct we need to know which struct should capnp treat it as. If we already know its name we can do val_ann_type = example_capnp.schema.get_nested(NAME).node.annotation.type. From here for safety, we can do val_ann_type.which(). If it's a struct, we get its id by val_ann_type.struct.typeId and match that again in example_capnp.schema.node.nestedNodes to get the name of the struct.

As you can see, it is possible to achieve, even without hard-coding names or relying in a specific order of annotations. Hopefully this will help contributors to add a nicer way, e.g. as suggested above.

Faboor avatar Aug 09 '17 18:08 Faboor