Skip to content
This repository was archived by the owner on Jun 23, 2018. It is now read-only.

Latest commit

 

History

History
108 lines (80 loc) · 4.21 KB

File metadata and controls

108 lines (80 loc) · 4.21 KB

Mapping NStack types to Python types

The table below show you what python types to expect and to return when dealing with types defined in the NStack IDL:

NStack Type Python Type
Integer int
Double double.Double
Boolean bool
Text str
Tuple tuple
Struct collections.namedtuple *
Array list
Sum see section below
[Byte] bytes
x optional None or x

*you can return a normal tuple (see Structs section below)

Sum Types

Python doesn't have support for Sum types (aka tagged/disjoint unions) but we still support them via inheritance.

Here's some example definitions of types in the nstack IDL:

type URL = Text;
type Referrer = URL;
type Target = URL;
type Event = PageImpression URL | Click (Referrer, Target);

You can imagine that we create classes for Event and its constructors something like the following:

class Event(object):
  ...
  class PageImpression(Event):
    ...
  class Click(Event):
    ...

As the sum is defined as a type alias (this is the only way to define sums in the IDL) then the types will be available as members of the nstack package module, and we can construct new values (to return them from an nstack service method) like this:

import nstack
ex_impression = nstack.Event.PageImpression("http://www.nstack.com/")
ex_click = nstack.Event.Click(("http://www.nstack.com/", "http://demo.nstack.com/"))

And we can see the class inheritance by asking python about the instances' types:

>> isinstance(ex_impression, nstack.Event)
True
>> isinstance(ex_impression, nstack.Event.PageImpression)
True
>> isinstance(ex_impression, nstack.Event.Click)
False

You will usually need to handle each branch of the sum type differently. Case analysis can be achieved using python's isinstance function as above...

if isinstance(v, nstack.Event.PageImpression):
  ... # do something with a page impression
elif isinstance(v, nstack.Event.Click):
  ... # do something with a click

The classes have some other useful properties/methods as shown below:

>> ex_impression.value
"http://www.nstack.com/"
>> ex_click.value
("http://www.nstack.com/", "http://demo.nstack.com/")
>> ex_impression.getPageImpression()
"http://www.nstack.com/"
>> ex_impression.getClick()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: Not a Click
>> ex_impression.match(lambda i: "got a page impression",
                       lambda i: "got a click")
"got a page impression"

Structs

We an modify the Click branch from the sample above to be a struct/record instead:

type URL = Text;
type Event = PageImpression URL | Click { referrer: URL, target: URL };

When you receive this data into your service method from nstack it will appear as a namedtuple from the collections module in the standard-library. eg:

ClickData = collections.namedtuple("ClickData", ["referrer", "target"])

This means you can treat the data as both a normal tuple (each field appears in the order it was defined) but also access each field as a property of the value:

>> input = nstack.Event.Click(("http://www.nstack.com/", "http://demo.nstack.com/"))
>> input.getClick().referrer
"http://www.nstack.com/"
>> input.getClick().target
"http://demo.nstack.com/"

In the example IDL we didn't give the struct a name, it was defined in-line inside the Click branch of the Event type, this means we can't construct it directly if we need to return it from our method. That's ok, namedtuples are just tuples so we can just return a normal tuple and nstack ensure it is correct. We can see this at work in the code example above where the Click constructor is called with a standard python tuple but when we inspect the value we get a namedtuple with the referrer and target properties.