RAMLfications

Lynn Root

Backend Engineer @ Spotify

@roguelynn

What Is RAML?

RAML stands for RESTful API Modeling Language.

Very similar to Swagger and Blueprint, it's used to describe REST APIs.

What it looks like:

#%RAML 0.8
title: Spotify Web API
version: v1
baseUri: https://api.spotify.com/{version}
mediaType: application/json
documentation:
  - title: Spotify Web API Docs
    content: |
      Welcome to the _Spotify Web API_ specification. For more information about
      how to use the API, check out [developer site](https://developer.spotify.com/web-api/).
/albums:
  displayName: several-albums
  get:
    description: |
      [Get Several Albums](https://developer.spotify.com/web-api/get-several-albums/)
    queryParameters:
      ids:
        displayName: Spotify Album IDs
        type: string
        description: A comma-separated list of IDs
        required: true
        example: "382ObEPsp2rxGrnsizN5TX,1A2GTWGtFfWp7KSQTwWOyo,2noRn2Aes5aoNVsU6iWThc"
      market:
        displayName: Market
        description: The market (an ISO 3166-1 alpha-2 country code)
        type: string
        example: ES
        required: false
    responses:
      200:
        body:
          application/json:
            example: !include example/get-albums-example.json

Why?

Why a description language for your API?

  • Have a single source-of-truth reference for your API
  • Machine & human-ish readable
  • Clear definition of own versioned API specification

Why RAML?

  • not limited to describing in JSON (Swagger only supports JSON Schema)
  • Can support different API versioning (Blueprint can as well)
  • Include sample representations (Blueprint can as well)
  • Allows for including of external files from either local filesystem or via an HTTP request - no need for one massive .raml file (Neither Swagger nor Blueprints supports this)
  • It's not WADL

Why did Spotify choose RAML

  • "new kid on the block" & very active development - also means it's very young
  • more readable from our PoV
    • actual syntax & file structure
    • external file inclusions
  • open-source spec

Setting the scene

I hated answering repeated questions

So I built a thing

It takes our RAML file

And makes an interactive console


In [3]:
from IPython.display import Image

In [4]:
Image(filename='api-console-snapshot.png')


Out[4]:

In [6]:
Image(filename='api-console-snapshot-resp.png')


Out[6]:

enter: RAMLfications

TL;DR: Python reference implementation for RAML

Let's play:

$ pip install ramlfications

In [7]:
!pip install ramlfications


Downloading/unpacking ramlfications
  Downloading ramlfications-0.1.2-py2.py3-none-any.whl
Downloading/unpacking click (from ramlfications)
  Downloading click-4.0-py2.py3-none-any.whl (62kB): 62kB downloaded
Downloading/unpacking six (from ramlfications)
  Downloading six-1.9.0-py2.py3-none-any.whl
Downloading/unpacking termcolor (from ramlfications)
  Downloading termcolor-1.1.0.tar.gz
  Running setup.py (path:/Users/lynnroot/.virtualenvs/raml-lt/build/termcolor/setup.py) egg_info for package termcolor
    
Downloading/unpacking markdown2 (from ramlfications)
  Downloading markdown2-2.3.0.zip (145kB): 145kB downloaded
  Running setup.py (path:/Users/lynnroot/.virtualenvs/raml-lt/build/markdown2/setup.py) egg_info for package markdown2
    
Downloading/unpacking xmltodict (from ramlfications)
  Downloading xmltodict-0.9.2.tar.gz
  Running setup.py (path:/Users/lynnroot/.virtualenvs/raml-lt/build/xmltodict/setup.py) egg_info for package xmltodict
    
Downloading/unpacking pyyaml (from ramlfications)
  Downloading PyYAML-3.11.tar.gz (248kB): 248kB downloaded
  Running setup.py (path:/Users/lynnroot/.virtualenvs/raml-lt/build/pyyaml/setup.py) egg_info for package pyyaml
    
Downloading/unpacking attrs (from ramlfications)
  Downloading attrs-15.0.0-py2-none-any.whl
Installing collected packages: ramlfications, click, six, termcolor, markdown2, xmltodict, pyyaml, attrs
  Running setup.py install for termcolor
    
  Running setup.py install for markdown2
    changing mode of build/scripts-2.7/markdown2 from 644 to 755
    
    changing mode of /Users/lynnroot/.virtualenvs/raml-lt/bin/markdown2 to 755
  Running setup.py install for xmltodict
    
  Running setup.py install for pyyaml
    checking if libyaml is compilable
    gcc -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7 -c build/temp.macosx-10.4-x86_64-2.7/check_libyaml.c -o build/temp.macosx-10.4-x86_64-2.7/check_libyaml.o
    checking if libyaml is linkable
    gcc build/temp.macosx-10.4-x86_64-2.7/check_libyaml.o -lyaml -o build/temp.macosx-10.4-x86_64-2.7/check_libyaml
    building '_yaml' extension
    gcc -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7 -c ext/_yaml.c -o build/temp.macosx-10.4-x86_64-2.7/ext/_yaml.o
    In file included from ext/_yaml.c:343:
    ext/_yaml.h:6:9: warning: 'PyUnicode_FromString' macro redefined [-Wmacro-redefined]
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
            ^
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:194:10: note: previous definition is here
    # define PyUnicode_FromString PyUnicodeUCS2_FromString
             ^
    ext/_yaml.c:1346:17: warning: assigning to 'char *' from 'const char *' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers]
      __pyx_v_value = yaml_get_version_string();
                    ^ ~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.c:2471:52: warning: incompatible pointer types passing 'int (void *, char *, int, int *)' to parameter of type 'yaml_read_handler_t *' (aka 'int (*)(void *, unsigned char *, size_t, size_t *)') [-Wincompatible-pointer-types]
        yaml_parser_set_input((&__pyx_v_self->parser), __pyx_f_5_yaml_input_handler, ((void *)__pyx_v_self));
                                                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /usr/local/include/yaml.h:1368:30: note: passing argument to parameter 'handler' here
            yaml_read_handler_t *handler, void *data);
                                 ^
    ext/_yaml.c:2664:59: warning: passing 'char [1]' to parameter of type 'const unsigned char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        yaml_parser_set_input_string((&__pyx_v_self->parser), PyString_AS_STRING(__pyx_v_stream), PyString_GET_SIZE(__pyx_v_stream));
                                                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/stringobject.h:91:32: note: expanded from macro 'PyString_AS_STRING'
    #define PyString_AS_STRING(op) (((PyStringObject *)(op))->ob_sval)
                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /usr/local/include/yaml.h:1342:30: note: passing argument to parameter 'input' here
            const unsigned char *input, size_t size);
                                 ^
    ext/_yaml.c:4183:38: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_3 = PyUnicode_FromString(__pyx_v_token->data.tag_directive.handle); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 417; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:4183:17: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_3 = PyUnicode_FromString(__pyx_v_token->data.tag_directive.handle); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 417; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:4195:38: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_3 = PyUnicode_FromString(__pyx_v_token->data.tag_directive.prefix); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 418; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:4195:17: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_3 = PyUnicode_FromString(__pyx_v_token->data.tag_directive.prefix); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 418; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:4741:38: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_3 = PyUnicode_FromString(__pyx_v_token->data.alias.value); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 448; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:4741:17: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_3 = PyUnicode_FromString(__pyx_v_token->data.alias.value); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 448; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:4792:38: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_4 = PyUnicode_FromString(__pyx_v_token->data.anchor.value); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 451; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:4792:17: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_4 = PyUnicode_FromString(__pyx_v_token->data.anchor.value); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 451; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:4843:38: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_3 = PyUnicode_FromString(__pyx_v_token->data.tag.handle); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 454; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:4843:17: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_3 = PyUnicode_FromString(__pyx_v_token->data.tag.handle); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 454; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:4855:38: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_3 = PyUnicode_FromString(__pyx_v_token->data.tag.suffix); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 455; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:4855:17: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_3 = PyUnicode_FromString(__pyx_v_token->data.tag.suffix); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 455; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:4938:38: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_2 = PyUnicode_DecodeUTF8(__pyx_v_token->data.scalar.value, __pyx_v_token->data.scalar.length, __pyx_k_strict); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 460; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:6435:42: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
            __pyx_t_4 = PyUnicode_FromString(__pyx_v_tag_directive->handle); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 574; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:6435:21: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
            __pyx_t_4 = PyUnicode_FromString(__pyx_v_tag_directive->handle); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 574; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:6447:42: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
            __pyx_t_4 = PyUnicode_FromString(__pyx_v_tag_directive->prefix); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:6447:21: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
            __pyx_t_4 = PyUnicode_FromString(__pyx_v_tag_directive->prefix); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 575; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:6616:38: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_2 = PyUnicode_FromString(__pyx_v_event->data.alias.anchor); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 586; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:6616:17: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_2 = PyUnicode_FromString(__pyx_v_event->data.alias.anchor); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 586; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:6687:40: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_1 = PyUnicode_FromString(__pyx_v_event->data.scalar.anchor); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 591; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:6687:19: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_1 = PyUnicode_FromString(__pyx_v_event->data.scalar.anchor); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 591; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:6722:40: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_1 = PyUnicode_FromString(__pyx_v_event->data.scalar.tag); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 594; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:6722:19: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_1 = PyUnicode_FromString(__pyx_v_event->data.scalar.tag); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 594; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:6737:38: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_1 = PyUnicode_DecodeUTF8(__pyx_v_event->data.scalar.value, __pyx_v_event->data.scalar.length, __pyx_k_strict); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 595; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:7031:40: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_3 = PyUnicode_FromString(__pyx_v_event->data.sequence_start.anchor); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 620; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:7031:19: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_3 = PyUnicode_FromString(__pyx_v_event->data.sequence_start.anchor); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 620; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:7066:40: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_3 = PyUnicode_FromString(__pyx_v_event->data.sequence_start.tag); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 623; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:7066:19: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_3 = PyUnicode_FromString(__pyx_v_event->data.sequence_start.tag); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 623; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:7253:40: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_2 = PyUnicode_FromString(__pyx_v_event->data.mapping_start.anchor); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 637; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:7253:19: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_2 = PyUnicode_FromString(__pyx_v_event->data.mapping_start.anchor); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 637; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:7288:40: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_2 = PyUnicode_FromString(__pyx_v_event->data.mapping_start.tag); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 640; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:7288:19: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_2 = PyUnicode_FromString(__pyx_v_event->data.mapping_start.tag); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 640; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:8704:38: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_3 = PyUnicode_FromString(__pyx_v_self->parsed_event.data.alias.anchor); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 734; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:8704:17: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_3 = PyUnicode_FromString(__pyx_v_self->parsed_event.data.alias.anchor); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 734; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:8924:38: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_6 = PyUnicode_FromString(__pyx_v_self->parsed_event.data.scalar.anchor); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 750; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:8924:17: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_6 = PyUnicode_FromString(__pyx_v_self->parsed_event.data.scalar.anchor); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 750; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:8962:38: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_6 = PyUnicode_FromString(__pyx_v_self->parsed_event.data.sequence_start.anchor); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 753; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:8962:17: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_6 = PyUnicode_FromString(__pyx_v_self->parsed_event.data.sequence_start.anchor); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 753; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:9000:38: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_6 = PyUnicode_FromString(__pyx_v_self->parsed_event.data.mapping_start.anchor); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 756; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:9000:17: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_6 = PyUnicode_FromString(__pyx_v_self->parsed_event.data.mapping_start.anchor); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 756; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:9532:36: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
      __pyx_t_2 = PyUnicode_DecodeUTF8(__pyx_v_self->parsed_event.data.scalar.value, __pyx_v_self->parsed_event.data.scalar.length, __pyx_k_strict); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 791; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:9688:38: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_9 = PyUnicode_FromString(__pyx_v_self->parsed_event.data.scalar.tag); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 804; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:9688:17: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_9 = PyUnicode_FromString(__pyx_v_self->parsed_event.data.scalar.tag); if (unlikely(!__pyx_t_9)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 804; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:10128:38: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_2 = PyUnicode_FromString(__pyx_v_self->parsed_event.data.sequence_start.tag); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:10128:17: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_2 = PyUnicode_FromString(__pyx_v_self->parsed_event.data.sequence_start.tag); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 837; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:10654:38: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_2 = PyUnicode_FromString(__pyx_v_self->parsed_event.data.mapping_start.tag); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 876; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:66: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                                     ^
    /usr/include/string.h:82:28: note: passing argument to parameter here
    size_t   strlen(const char *);
                                ^
    ext/_yaml.c:10654:17: warning: passing 'yaml_char_t *' (aka 'unsigned char *') to parameter of type 'const char *' converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_2 = PyUnicode_FromString(__pyx_v_self->parsed_event.data.mapping_start.tag); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 876; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.h:6:54: note: expanded from macro 'PyUnicode_FromString'
    #define PyUnicode_FromString(s) PyUnicode_DecodeUTF8((s), strlen(s), "strict")
                                                         ^~~
    /Users/lynnroot/.pyenv/versions/2.7.8/include/python2.7/unicodeobject.h:751:17: note: passing argument to parameter 'string' here
        const char *string,         /* UTF-8 encoded string */
                    ^
    ext/_yaml.c:11721:53: warning: incompatible pointer types passing 'int (void *, char *, int)' to parameter of type 'yaml_write_handler_t *' (aka 'int (*)(void *, unsigned char *, size_t)') [-Wincompatible-pointer-types]
      yaml_emitter_set_output((&__pyx_v_self->emitter), __pyx_f_5_yaml_output_handler, ((void *)__pyx_v_self));
                                                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /usr/local/include/yaml.h:1830:31: note: passing argument to parameter 'handler' here
            yaml_write_handler_t *handler, void *data);
                                  ^
    ext/_yaml.c:12898:44: warning: assigning to 'yaml_char_t *' (aka 'unsigned char *') from 'char [1]' converts between pointers to integer types with different sign [-Wpointer-sign]
            __pyx_v_tag_directives_end->handle = PyString_AS_STRING(__pyx_v_handle);
                                               ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.c:12991:44: warning: assigning to 'yaml_char_t *' (aka 'unsigned char *') from 'char [1]' converts between pointers to integer types with different sign [-Wpointer-sign]
            __pyx_v_tag_directives_end->prefix = PyString_AS_STRING(__pyx_v_prefix);
                                               ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.c:13248:62: warning: passing 'char *' to parameter of type 'yaml_char_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_4 = ((yaml_alias_event_initialize(__pyx_v_event, __pyx_v_anchor) == 0) != 0);
                                                                 ^~~~~~~~~~~~~~
    /usr/local/include/yaml.h:553:63: note: passing argument to parameter 'anchor' here
    yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor);
                                                                  ^
    ext/_yaml.c:13824:63: warning: passing 'char *' to parameter of type 'yaml_char_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_3 = ((yaml_scalar_event_initialize(__pyx_v_event, __pyx_v_anchor, __pyx_v_tag, __pyx_v_value, __pyx_v_length, __pyx_v_plain_implicit, __pyx_v_quoted_implicit, __pyx_v_scalar_style) == 0) != 0);
                                                                  ^~~~~~~~~~~~~~
    /usr/local/include/yaml.h:579:22: note: passing argument to parameter 'anchor' here
            yaml_char_t *anchor, yaml_char_t *tag,
                         ^
    ext/_yaml.c:13824:79: warning: passing 'char *' to parameter of type 'yaml_char_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_3 = ((yaml_scalar_event_initialize(__pyx_v_event, __pyx_v_anchor, __pyx_v_tag, __pyx_v_value, __pyx_v_length, __pyx_v_plain_implicit, __pyx_v_quoted_implicit, __pyx_v_scalar_style) == 0) != 0);
                                                                                  ^~~~~~~~~~~
    /usr/local/include/yaml.h:579:43: note: passing argument to parameter 'tag' here
            yaml_char_t *anchor, yaml_char_t *tag,
                                              ^
    ext/_yaml.c:13824:92: warning: passing 'char *' to parameter of type 'yaml_char_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_3 = ((yaml_scalar_event_initialize(__pyx_v_event, __pyx_v_anchor, __pyx_v_tag, __pyx_v_value, __pyx_v_length, __pyx_v_plain_implicit, __pyx_v_quoted_implicit, __pyx_v_scalar_style) == 0) != 0);
                                                                                               ^~~~~~~~~~~~~
    /usr/local/include/yaml.h:580:22: note: passing argument to parameter 'value' here
            yaml_char_t *value, int length,
                         ^
    ext/_yaml.c:14166:71: warning: passing 'char *' to parameter of type 'yaml_char_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_4 = ((yaml_sequence_start_event_initialize(__pyx_v_event, __pyx_v_anchor, __pyx_v_tag, __pyx_v_implicit, __pyx_v_sequence_style) == 0) != 0);
                                                                          ^~~~~~~~~~~~~~
    /usr/local/include/yaml.h:602:22: note: passing argument to parameter 'anchor' here
            yaml_char_t *anchor, yaml_char_t *tag, int implicit,
                         ^
    ext/_yaml.c:14166:87: warning: passing 'char *' to parameter of type 'yaml_char_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_4 = ((yaml_sequence_start_event_initialize(__pyx_v_event, __pyx_v_anchor, __pyx_v_tag, __pyx_v_implicit, __pyx_v_sequence_style) == 0) != 0);
                                                                                          ^~~~~~~~~~~
    /usr/local/include/yaml.h:602:43: note: passing argument to parameter 'tag' here
            yaml_char_t *anchor, yaml_char_t *tag, int implicit,
                                              ^
    ext/_yaml.c:14508:70: warning: passing 'char *' to parameter of type 'yaml_char_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_3 = ((yaml_mapping_start_event_initialize(__pyx_v_event, __pyx_v_anchor, __pyx_v_tag, __pyx_v_implicit, __pyx_v_mapping_style) == 0) != 0);
                                                                         ^~~~~~~~~~~~~~
    /usr/local/include/yaml.h:634:22: note: passing argument to parameter 'anchor' here
            yaml_char_t *anchor, yaml_char_t *tag, int implicit,
                         ^
    ext/_yaml.c:14508:86: warning: passing 'char *' to parameter of type 'yaml_char_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_3 = ((yaml_mapping_start_event_initialize(__pyx_v_event, __pyx_v_anchor, __pyx_v_tag, __pyx_v_implicit, __pyx_v_mapping_style) == 0) != 0);
                                                                                         ^~~~~~~~~~~
    /usr/local/include/yaml.h:634:43: note: passing argument to parameter 'tag' here
            yaml_char_t *anchor, yaml_char_t *tag, int implicit,
                                              ^
    ext/_yaml.c:15784:42: warning: assigning to 'yaml_char_t *' (aka 'unsigned char *') from 'char [1]' converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_v_tag_directives_end->handle = PyString_AS_STRING(__pyx_v_handle);
                                             ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.c:15877:42: warning: assigning to 'yaml_char_t *' (aka 'unsigned char *') from 'char [1]' converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_v_tag_directives_end->prefix = PyString_AS_STRING(__pyx_v_prefix);
                                             ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    ext/_yaml.c:16616:65: warning: passing 'char *' to parameter of type 'yaml_char_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
        __pyx_t_2 = ((yaml_alias_event_initialize((&__pyx_v_event), __pyx_v_anchor) == 0) != 0);
                                                                    ^~~~~~~~~~~~~~
    /usr/local/include/yaml.h:553:63: note: passing argument to parameter 'anchor' here
    yaml_alias_event_initialize(yaml_event_t *event, yaml_char_t *anchor);
                                                                  ^
    ext/_yaml.c:17195:68: warning: passing 'char *' to parameter of type 'yaml_char_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_8 = ((yaml_scalar_event_initialize((&__pyx_v_event), __pyx_v_anchor, __pyx_v_tag, __pyx_v_value, __pyx_v_length, __pyx_v_plain_implicit, __pyx_v_quoted_implicit, __pyx_v_scalar_style) == 0) != 0);
                                                                       ^~~~~~~~~~~~~~
    /usr/local/include/yaml.h:579:22: note: passing argument to parameter 'anchor' here
            yaml_char_t *anchor, yaml_char_t *tag,
                         ^
    ext/_yaml.c:17195:84: warning: passing 'char *' to parameter of type 'yaml_char_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_8 = ((yaml_scalar_event_initialize((&__pyx_v_event), __pyx_v_anchor, __pyx_v_tag, __pyx_v_value, __pyx_v_length, __pyx_v_plain_implicit, __pyx_v_quoted_implicit, __pyx_v_scalar_style) == 0) != 0);
                                                                                       ^~~~~~~~~~~
    /usr/local/include/yaml.h:579:43: note: passing argument to parameter 'tag' here
            yaml_char_t *anchor, yaml_char_t *tag,
                                              ^
    ext/_yaml.c:17195:97: warning: passing 'char *' to parameter of type 'yaml_char_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_8 = ((yaml_scalar_event_initialize((&__pyx_v_event), __pyx_v_anchor, __pyx_v_tag, __pyx_v_value, __pyx_v_length, __pyx_v_plain_implicit, __pyx_v_quoted_implicit, __pyx_v_scalar_style) == 0) != 0);
                                                                                                    ^~~~~~~~~~~~~
    /usr/local/include/yaml.h:580:22: note: passing argument to parameter 'value' here
            yaml_char_t *value, int length,
                         ^
    ext/_yaml.c:17473:76: warning: passing 'char *' to parameter of type 'yaml_char_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_8 = ((yaml_sequence_start_event_initialize((&__pyx_v_event), __pyx_v_anchor, __pyx_v_tag, __pyx_v_implicit, __pyx_v_sequence_style) == 0) != 0);
                                                                               ^~~~~~~~~~~~~~
    /usr/local/include/yaml.h:602:22: note: passing argument to parameter 'anchor' here
            yaml_char_t *anchor, yaml_char_t *tag, int implicit,
                         ^
    ext/_yaml.c:17473:92: warning: passing 'char *' to parameter of type 'yaml_char_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_8 = ((yaml_sequence_start_event_initialize((&__pyx_v_event), __pyx_v_anchor, __pyx_v_tag, __pyx_v_implicit, __pyx_v_sequence_style) == 0) != 0);
                                                                                               ^~~~~~~~~~~
    /usr/local/include/yaml.h:602:43: note: passing argument to parameter 'tag' here
            yaml_char_t *anchor, yaml_char_t *tag, int implicit,
                                              ^
    ext/_yaml.c:17874:75: warning: passing 'char *' to parameter of type 'yaml_char_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_8 = ((yaml_mapping_start_event_initialize((&__pyx_v_event), __pyx_v_anchor, __pyx_v_tag, __pyx_v_implicit, __pyx_v_mapping_style) == 0) != 0);
                                                                              ^~~~~~~~~~~~~~
    /usr/local/include/yaml.h:634:22: note: passing argument to parameter 'anchor' here
            yaml_char_t *anchor, yaml_char_t *tag, int implicit,
                         ^
    ext/_yaml.c:17874:91: warning: passing 'char *' to parameter of type 'yaml_char_t *' (aka 'unsigned char *') converts between pointers to integer types with different sign [-Wpointer-sign]
          __pyx_t_8 = ((yaml_mapping_start_event_initialize((&__pyx_v_event), __pyx_v_anchor, __pyx_v_tag, __pyx_v_implicit, __pyx_v_mapping_style) == 0) != 0);
                                                                                              ^~~~~~~~~~~
    /usr/local/include/yaml.h:634:43: note: passing argument to parameter 'tag' here
            yaml_char_t *anchor, yaml_char_t *tag, int implicit,
                                              ^
    ext/_yaml.c:22027:28: warning: unused function '__Pyx_PyObject_AsString' [-Wunused-function]
    static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject* o) {
                               ^
    ext/_yaml.c:22024:32: warning: unused function '__Pyx_PyUnicode_FromString' [-Wunused-function]
    static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(char* c_str) {
                                   ^
    ext/_yaml.c:405:29: warning: unused function '__Pyx_Py_UNICODE_strlen' [-Wunused-function]
    static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u)
                                ^
    ext/_yaml.c:22146:33: warning: unused function '__Pyx_PyIndex_AsSsize_t' [-Wunused-function]
    static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
                                    ^
    ext/_yaml.c:22175:33: warning: unused function '__Pyx_PyInt_FromSize_t' [-Wunused-function]
    static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) {
                                    ^
    ext/_yaml.c:20925:27: warning: unused function '__Pyx_ErrFetch' [-Wunused-function]
    static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) {
                              ^
    ext/_yaml.c:21319:32: warning: unused function '__Pyx_GetItemInt_List_Fast' [-Wunused-function]
    static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i,
                                   ^
    ext/_yaml.c:21333:32: warning: unused function '__Pyx_GetItemInt_Tuple_Fast' [-Wunused-function]
    static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i,
                                   ^
    ext/_yaml.c:21718:27: warning: function '__Pyx_PyInt_As_long' is not needed and will not be emitted [-Wunneeded-internal-declaration]
    static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) {
                              ^
    81 warnings generated.
    gcc -bundle -undefined dynamic_lookup -L/usr/local/opt/readline/lib -L/usr/local/opt/readline/lib -L/Users/lynnroot/.pyenv/versions/2.7.8/lib build/temp.macosx-10.4-x86_64-2.7/ext/_yaml.o -lyaml -o build/lib.macosx-10.4-x86_64-2.7/_yaml.so
    
Successfully installed ramlfications click six termcolor markdown2 xmltodict pyyaml attrs
Cleaning up...

using RAMLfications within your library


In [8]:
from ramlfications import parse

In [16]:
RAML_FILE = "spotify-web-api.raml"
api = parse(RAML_FILE)

In [17]:
api


Out[17]:
RootNode(title='Spotify Web API')

In [29]:
#metadata
api.title


Out[29]:
'Spotify Web API'

In [19]:
api.version


Out[19]:
'v1'

In [30]:
api.base_uri


Out[30]:
'https://api.spotify.com/v1'

In [67]:
api.protocols


Out[67]:
['HTTPS']

In [28]:
# security schemes
api.security_schemes


Out[28]:
[SecurityScheme(name='oauth_2_0')]

In [27]:
oauth = api.security_schemes[0]
oauth.settings.get("scopes")


Out[27]:
['playlist-read-private',
 'playlist-modify-public',
 'playlist-modify-private',
 'user-library-read',
 'user-library-modify',
 'user-read-private',
 'user-read-birthdate',
 'user-read-email',
 'user-follow-read',
 'user-follow-modify']

In [31]:
# API endpoints
res = api.resources
res


Out[31]:
[ResourceNode(method='get', path='/albums'),
 ResourceNode(method='get', path='/albums/{id}'),
 ResourceNode(method='get', path='/albums/{id}/tracks'),
 ResourceNode(method='get', path='/artists'),
 ResourceNode(method='get', path='/artists/{id}'),
 ResourceNode(method='get', path='/artists/{id}/top-tracks'),
 ResourceNode(method='get', path='/artists/{id}/related-artists'),
 ResourceNode(method='get', path='/artists/{id}/albums'),
 ResourceNode(method='get', path='/tracks'),
 ResourceNode(method='get', path='/tracks/{id}'),
 ResourceNode(method='get', path='/search'),
 ResourceNode(method='get', path='/me'),
 ResourceNode(method='get', path='/me/tracks'),
 ResourceNode(method='put', path='/me/tracks'),
 ResourceNode(method='delete', path='/me/tracks'),
 ResourceNode(method='get', path='/me/tracks/contains'),
 ResourceNode(method='get', path='/users/{user_id}'),
 ResourceNode(method='get', path='/users/{user_id}/playlists'),
 ResourceNode(method='post', path='/users/{user_id}/playlists'),
 ResourceNode(method='get', path='/users/{user_id}/playlists/{playlist_id}'),
 ResourceNode(method='put', path='/users/{user_id}/playlists/{playlist_id}'),
 ResourceNode(method='get', path='/users/{user_id}/playlists/{playlist_id}/tracks'),
 ResourceNode(method='post', path='/users/{user_id}/playlists/{playlist_id}/tracks'),
 ResourceNode(method='put', path='/users/{user_id}/playlists/{playlist_id}/tracks'),
 ResourceNode(method='delete', path='/users/{user_id}/playlists/{playlist_id}/tracks'),
 ResourceNode(method='put', path='/users/{user_id}/playlists/{playlist_id}/followers'),
 ResourceNode(method='delete', path='/users/{user_id}/playlists/{playlist_id}/followers'),
 ResourceNode(method='get', path='/users/{user_id}/playlists/{playlist_id}/followers/contains'),
 ResourceNode(method='get', path='/browse/new-releases'),
 ResourceNode(method='get', path='/browse/featured-playlists'),
 ResourceNode(method='get', path='/browse/categories'),
 ResourceNode(method='get', path='/browse/categories/{category_id}'),
 ResourceNode(method='get', path='/browse/categories/{category_id}/playlists'),
 ResourceNode(method='put', path='/me/following'),
 ResourceNode(method='delete', path='/me/following'),
 ResourceNode(method='get', path='/me/following/contains')]

In [36]:
get_an_album = res[1]
get_an_album.uri_params


Out[36]:
[URIParameter(name='id')]

In [54]:
get_an_album.method


Out[54]:
'get'

In [55]:
get_an_album.description


Out[55]:
[Get an Album](https://developer.spotify.com/web-api/get-album/)

In [56]:
get_an_album.description.html


Out[56]:
u'<p><a href="https://developer.spotify.com/web-api/get-album/">Get an Album</a></p>\n'

In [58]:
get_an_album.display_name


Out[58]:
'album'

In [68]:
get_an_album.path


Out[68]:
'/albums/{id}'

In [69]:
get_an_album.absolute_uri


Out[69]:
'https://api.spotify.com/v1/albums/{id}'

In [70]:
# parameters
uri_param = get_an_album.uri_params[0]
uri_param.name


Out[70]:
'id'

In [40]:
uri_param.required


Out[40]:
True

In [41]:
uri_param.example


Out[41]:
'4aawyAB9vmqN3uQ7FjRGTy'

In [42]:
get_an_album.parent


Out[42]:
ResourceNode(method='get', path='/albums')

In [71]:
# API traits
api.traits


Out[71]:
[TraitNode(name='filterable'), TraitNode(name='paged')]

In [72]:
paged = api.traits[1]
paged.query_params


Out[72]:
[QueryParameter(name='limit'), QueryParameter(name='offset')]

In [73]:
query_param = _[0]

In [74]:
query_param.name


Out[74]:
'limit'

In [75]:
query_param.raw


Out[75]:
OrderedDict([('displayName', 'Limit'), ('description', 'The maximum number of track objects to return'), ('type', 'integer'), ('example', 10), ('minimum', 0), ('default', 20), ('maximum', 50), ('required', False)])

fun from the command line

validate your RAML file


In [81]:
!ramlfications validate spotify-web-api.raml


Success! Valid RAML file: spotify-web-api.raml

In [82]:
!ramlfications validate invalid.raml


Error validating file invalid.raml: 'FTP' not a valid protocol for a RAML-defined API.

Your API does in fact support FTP?

Just add it to your config file!

$ cat raml_config.ini
[custom]
protocols = FTP

In [84]:
!ramlfications validate --config raml_config.ini invalid.raml


Success! Valid RAML file: invalid.raml

visualize your RAML file


In [76]:
!ramlfications tree spotify-web-api.raml


===============
Spotify Web API
===============
Base URI: https://api.spotify.com/v1
|- /albums
|  - /albums/{id}
|    - /albums/{id}/tracks
|- /artists
|  - /artists/{id}
|    - /artists/{id}/top-tracks
|    - /artists/{id}/related-artists
|    - /artists/{id}/albums
|- /tracks
|  - /tracks/{id}
|- /search
|- /me
|  - /me/tracks
|  - /me/tracks
|  - /me/tracks
|    - /me/tracks/contains
|- /users/{user_id}
|- /users/{user_id}/playlists
|- /users/{user_id}/playlists
|  - /users/{user_id}/playlists/{playlist_id}
|  - /users/{user_id}/playlists/{playlist_id}
|    - /users/{user_id}/playlists/{playlist_id}/tracks
|    - /users/{user_id}/playlists/{playlist_id}/tracks
|    - /users/{user_id}/playlists/{playlist_id}/tracks
|    - /users/{user_id}/playlists/{playlist_id}/tracks
|    - /users/{user_id}/playlists/{playlist_id}/followers
|    - /users/{user_id}/playlists/{playlist_id}/followers
|      - /users/{user_id}/playlists/{playlist_id}/followers/contains

|- /browse/featured-playlists
|- /browse/categories
|  - /browse/categories/{category_id}
|    - /browse/categories/{category_id}/playlists
|- /me/following
|- /me/following
|  - /me/following/contains

In [78]:
# MOAR!
!ramlfications tree spotify-web-api.raml -v


===============
Spotify Web API
===============
Base URI: https://api.spotify.com/v1
|- /albums
|  ⌙ GET
|  - /albums/{id}
|    ⌙ GET
|    - /albums/{id}/tracks
|      ⌙ GET
|- /artists
|  ⌙ GET
|  - /artists/{id}
|    ⌙ GET
|    - /artists/{id}/top-tracks
|      ⌙ GET
|    - /artists/{id}/related-artists
|      ⌙ GET
|    - /artists/{id}/albums
|      ⌙ GET
|- /tracks
|  ⌙ GET
|  - /tracks/{id}
|    ⌙ GET
|- /search
|  ⌙ GET
|- /me
|  ⌙ GET
|  - /me/tracks
|    ⌙ GET
|  - /me/tracks
|    ⌙ PUT
|  - /me/tracks
|    ⌙ DELETE
|    - /me/tracks/contains
|      ⌙ GET
|- /users/{user_id}
|  ⌙ GET
|- /users/{user_id}/playlists
|  ⌙ GET
|- /users/{user_id}/playlists
|  ⌙ POST
|  - /users/{user_id}/playlists/{playlist_id}
|    ⌙ GET
|  - /users/{user_id}/playlists/{playlist_id}
|    ⌙ PUT
|    - /users/{user_id}/playlists/{playlist_id}/tracks
|      ⌙ GET
|    - /users/{user_id}/playlists/{playlist_id}/tracks
|      ⌙ POST
|    - /users/{user_id}/playlists/{playlist_id}/tracks
|      ⌙ PUT
|    - /users/{user_id}/playlists/{playlist_id}/tracks
|      ⌙ DELETE
|    - /users/{user_id}/playlists/{playlist_id}/followers
|      ⌙ PUT
|    - /users/{user_id}/playlists/{playlist_id}/followers
|      ⌙ DELETE
|      - /users/{user_id}/playlists/{playlist_id}/followers/contains
|        ⌙ GET
|- /browse/new-releases
|  ⌙ GET
|- /browse/featured-playlists
|  ⌙ GET
|- /browse/categories
|  ⌙ GET
|  - /browse/categories/{category_id}
|    ⌙ GET
|    - /browse/categories/{category_id}/playlists
|      ⌙ GET
|- /me/following
|  ⌙ PUT
|- /me/following
|  ⌙ DELETE
|  - /me/following/contains
|    ⌙ GET

In [79]:
# I want MOAR
!ramlfications tree spotify-web-api.raml -vv


===============
Spotify Web API
===============
Base URI: https://api.spotify.com/v1
|- /albums
|  ⌙ GET
|     Query Params
|      ⌙ ids
|      ⌙ market
|  - /albums/{id}
|    ⌙ GET
|       Query Params
|        ⌙ market
|       URI Params
|        ⌙ id
|    - /albums/{id}/tracks
|      ⌙ GET
|         Query Params
|          ⌙ limit
|          ⌙ offset
|          ⌙ market
|         URI Params
|          ⌙ id
|- /artists
|  ⌙ GET
|     Query Params
|      ⌙ ids
|  - /artists/{id}
|    ⌙ GET
|       URI Params
|        ⌙ id
|    - /artists/{id}/top-tracks
|      ⌙ GET
|         Query Params
|          ⌙ country
|         URI Params
|          ⌙ id
|    - /artists/{id}/related-artists
|      ⌙ GET
|         URI Params
|          ⌙ id
|    - /artists/{id}/albums
|      ⌙ GET
|         Query Params
|          ⌙ limit
|          ⌙ offset
|          ⌙ album_type
|          ⌙ market
|         URI Params
|          ⌙ id
|- /tracks
|  ⌙ GET
|     Query Params
|      ⌙ ids
|      ⌙ market
|  - /tracks/{id}
|    ⌙ GET
|       Query Params
|        ⌙ market
|       URI Params
|        ⌙ id
|- /search
|  ⌙ GET
|     Query Params
|      ⌙ limit
|      ⌙ offset
|      ⌙ q
|      ⌙ type
|      ⌙ market
|- /me
|  ⌙ GET
|  - /me/tracks
|    ⌙ GET
|       Query Params
|        ⌙ limit
|        ⌙ offset
|        ⌙ market
|  - /me/tracks
|    ⌙ PUT
|       Query Params
|        ⌙ ids
|  - /me/tracks
|    ⌙ DELETE
|       Query Params
|        ⌙ ids
|    - /me/tracks/contains
|      ⌙ GET
|         Query Params
|          ⌙ ids
|- /users/{user_id}
|  ⌙ GET
|     URI Params
|      ⌙ user_id
|- /users/{user_id}/playlists
|  ⌙ GET
|     Query Params
|      ⌙ limit
|      ⌙ offset
|     URI Params
|      ⌙ user_id
|- /users/{user_id}/playlists
|  ⌙ POST
|     URI Params
|      ⌙ user_id
|  - /users/{user_id}/playlists/{playlist_id}
|    ⌙ GET
|       Query Params
|        ⌙ fields
|       URI Params
|        ⌙ playlist_id
|        ⌙ user_id
|  - /users/{user_id}/playlists/{playlist_id}
|    ⌙ PUT
|       URI Params
|        ⌙ playlist_id
|        ⌙ user_id
|    - /users/{user_id}/playlists/{playlist_id}/tracks
|      ⌙ GET
|         Query Params
|          ⌙ fields
|          ⌙ limit
|          ⌙ offset
|          ⌙ market
|         URI Params
|          ⌙ playlist_id
|          ⌙ user_id
|    - /users/{user_id}/playlists/{playlist_id}/tracks
|      ⌙ POST
|         Query Params
|          ⌙ position
|          ⌙ uris
|         URI Params
|          ⌙ playlist_id
|          ⌙ user_id
|    - /users/{user_id}/playlists/{playlist_id}/tracks
|      ⌙ PUT
|         URI Params
|          ⌙ playlist_id
|          ⌙ user_id
|    - /users/{user_id}/playlists/{playlist_id}/tracks
|      ⌙ DELETE
|         URI Params
|          ⌙ playlist_id
|          ⌙ user_id
|    - /users/{user_id}/playlists/{playlist_id}/followers
|      ⌙ PUT
|         URI Params
|          ⌙ playlist_id
|          ⌙ user_id
|    - /users/{user_id}/playlists/{playlist_id}/followers
|      ⌙ DELETE
|         URI Params
|          ⌙ playlist_id
|          ⌙ user_id
|      - /users/{user_id}/playlists/{playlist_id}/followers/contains
|        ⌙ GET
|           Query Params
|            ⌙ ids
|           URI Params
|            ⌙ playlist_id
|            ⌙ user_id
|- /browse/new-releases
|  ⌙ GET
|     Query Params
|      ⌙ limit
|      ⌙ offset
|      ⌙ country
|- /browse/featured-playlists
|  ⌙ GET
|     Query Params
|      ⌙ limit
|      ⌙ offset
|      ⌙ country
|      ⌙ locale
|      ⌙ timestamp
|- /browse/categories
|  ⌙ GET
|     Query Params
|      ⌙ country
|      ⌙ locale
|      ⌙ limit
|      ⌙ offset
|  - /browse/categories/{category_id}
|    ⌙ GET
|       Query Params
|        ⌙ country
|        ⌙ locale
|       URI Params
|        ⌙ category_id
|    - /browse/categories/{category_id}/playlists
|      ⌙ GET
|         Query Params
|          ⌙ country
|          ⌙ limit
|          ⌙ offset
|         URI Params
|          ⌙ category_id
|- /me/following
|  ⌙ PUT
|     Query Params
|      ⌙ type
|      ⌙ ids
|- /me/following
|  ⌙ DELETE
|     Query Params
|      ⌙ type
|      ⌙ ids
|  - /me/following/contains
|    ⌙ GET
|       Query Params
|        ⌙ type
|        ⌙ ids

In [80]:
# I WANT MOOOOARRRRR
!ramlfications tree spotify-web-api.raml -vvv


===============
Spotify Web API
===============
Base URI: https://api.spotify.com/v1
|- /albums
|  ⌙ GET
|     Query Params
|      ⌙ ids: Spotify Album IDs
|      ⌙ market: Market
|  - /albums/{id}
|    ⌙ GET
|       Query Params
|        ⌙ market: Market
|       URI Params
|        ⌙ id: Spotify Album ID
|    - /albums/{id}/tracks
|      ⌙ GET
|         Query Params
|          ⌙ limit: Limit
|          ⌙ offset: Offset
|          ⌙ market: Market
|         URI Params
|          ⌙ id: Spotify Album ID
|- /artists
|  ⌙ GET
|     Query Params
|      ⌙ ids: Spotify Artist IDs
|  - /artists/{id}
|    ⌙ GET
|       URI Params
|        ⌙ id: Spotify Artist ID
|    - /artists/{id}/top-tracks
|      ⌙ GET
|         Query Params
|          ⌙ country: Country
|         URI Params
|          ⌙ id: Spotify Artist ID
|    - /artists/{id}/related-artists
|      ⌙ GET
|         URI Params
|          ⌙ id: Spotify Artist ID
|    - /artists/{id}/albums
|      ⌙ GET
|         Query Params
|          ⌙ limit: Limit
|          ⌙ offset: Offset
|          ⌙ album_type: Album Type (single, album, appears_on, compilation)
|          ⌙ market: Market
|         URI Params
|          ⌙ id: Spotify Artist ID
|- /tracks
|  ⌙ GET
|     Query Params
|      ⌙ ids: Spotify Track IDs
|      ⌙ market: Market
|  - /tracks/{id}
|    ⌙ GET
|       Query Params
|        ⌙ market: Market
|       URI Params
|        ⌙ id: Spotify Track ID
|- /search
|  ⌙ GET
|     Query Params
|      ⌙ limit: Limit
|      ⌙ offset: Offset
|      ⌙ q: Query
|      ⌙ type: Item Type (album, artist, track, playlist)
|      ⌙ market: Market
|- /me
|  ⌙ GET
|  - /me/tracks
|    ⌙ GET
|       Query Params
|        ⌙ limit: Limit
|        ⌙ offset: Offset
|        ⌙ market: Market
|  - /me/tracks
|    ⌙ PUT
|       Query Params
|        ⌙ ids: Spotify Track IDs
|  - /me/tracks
|    ⌙ DELETE
|       Query Params
|        ⌙ ids: Spotify Track IDs
|    - /me/tracks/contains
|      ⌙ GET
|         Query Params
|          ⌙ ids: Spotify Track IDs
|- /users/{user_id}
|  ⌙ GET
|     URI Params
|      ⌙ user_id: User ID
|- /users/{user_id}/playlists
|  ⌙ GET
|     Query Params
|      ⌙ limit: Limit
|      ⌙ offset: Offset
|     URI Params
|      ⌙ user_id: Owner ID
|- /users/{user_id}/playlists
|  ⌙ POST
|     URI Params
|      ⌙ user_id: Owner ID
|  - /users/{user_id}/playlists/{playlist_id}
|    ⌙ GET
|       Query Params
|        ⌙ fields: Fields
|       URI Params
|        ⌙ playlist_id: Playlist ID
|        ⌙ user_id: Owner ID
|  - /users/{user_id}/playlists/{playlist_id}
|    ⌙ PUT
|       URI Params
|        ⌙ playlist_id: Playlist ID
|        ⌙ user_id: Owner ID
|    - /users/{user_id}/playlists/{playlist_id}/tracks
|      ⌙ GET
|         Query Params
|          ⌙ fields: Fields
|          ⌙ limit: Limit
|          ⌙ offset: Offset
|          ⌙ market: Market
|         URI Params
|          ⌙ playlist_id: Playlist ID
|          ⌙ user_id: Owner ID
|    - /users/{user_id}/playlists/{playlist_id}/tracks
|      ⌙ POST
|         Query Params
|          ⌙ position: Position (append by default)
|          ⌙ uris: Spotify Track URIs
|         URI Params
|          ⌙ playlist_id: Playlist ID
|          ⌙ user_id: Owner ID
|    - /users/{user_id}/playlists/{playlist_id}/tracks
|      ⌙ PUT
|         URI Params
|          ⌙ playlist_id: Playlist ID
|          ⌙ user_id: Owner ID
|    - /users/{user_id}/playlists/{playlist_id}/tracks
|      ⌙ DELETE
|         URI Params
|          ⌙ playlist_id: Playlist ID
|          ⌙ user_id: Owner ID
|    - /users/{user_id}/playlists/{playlist_id}/followers
|      ⌙ PUT
|         URI Params
|          ⌙ playlist_id: Playlist ID
|          ⌙ user_id: Owner ID
|    - /users/{user_id}/playlists/{playlist_id}/followers
|      ⌙ DELETE
|         URI Params
|          ⌙ playlist_id: Playlist ID
|          ⌙ user_id: Owner ID
|      - /users/{user_id}/playlists/{playlist_id}/followers/contains
|        ⌙ GET
|           Query Params
|            ⌙ ids: Spotify user IDs
|           URI Params
|            ⌙ playlist_id: Playlist ID
|            ⌙ user_id: Owner ID
|- /browse/new-releases
|  ⌙ GET
|     Query Params
|      ⌙ limit: Limit
|      ⌙ offset: Offset
|      ⌙ country: Country
|- /browse/featured-playlists
|  ⌙ GET
|     Query Params
|      ⌙ limit: Limit
|      ⌙ offset: Offset
|      ⌙ country: Country
|      ⌙ locale: Locale
|      ⌙ timestamp: Timestamp
|- /browse/categories
|  ⌙ GET
|     Query Params
|      ⌙ country: Country
|      ⌙ locale: Locale
|      ⌙ limit: Limit
|      ⌙ offset: Offset
|  - /browse/categories/{category_id}
|    ⌙ GET
|       Query Params
|        ⌙ country: Country
|        ⌙ locale: Locale
|       URI Params
|        ⌙ category_id: Category ID
|    - /browse/categories/{category_id}/playlists
|      ⌙ GET
|         Query Params
|          ⌙ country: Country
|          ⌙ limit: Limit
|          ⌙ offset: Offset
|         URI Params
|          ⌙ category_id: Category ID
|- /me/following
|  ⌙ PUT
|     Query Params
|      ⌙ type: Item Type
|      ⌙ ids: Spotify IDs
|- /me/following
|  ⌙ DELETE
|     Query Params
|      ⌙ type: Item Type
|      ⌙ ids: Spotify IDs
|  - /me/following/contains
|    ⌙ GET
|       Query Params
|        ⌙ type: Item Type
|        ⌙ ids: Spotify IDs

What's next?

Coming soon:

  • Documentation generator based off of RAML
  • API console

FIN

Docs: ramlfications.readthedocs.org

Code: github.com/spotify/ramlfications

Slides: rogue.ly/ramlfications

Thanks!