|
1 | 1 | ***** |
2 | | -Babel |
| 2 | +Stone |
3 | 3 | ***** |
4 | 4 |
|
5 | | -Define an API once in Babel. Use code generators to translate your |
| 5 | +Define an API once in Stone. Use code generators to translate your |
6 | 6 | specification into objects and functions in the programming languages |
7 | 7 | of your choice. |
8 | 8 |
|
@@ -13,8 +13,7 @@ actively worked on, and the intention is to support |
13 | 13 | * Introduction |
14 | 14 | * Motivation_ |
15 | 15 | * Installation_ |
16 | | - * `Taste of Babel <#a-taste-of-babel>`_ |
17 | | - * `Language Reference (.babel) <doc/lang_ref.rst>`_ |
| 16 | + * `Language Reference (.stone) <doc/lang_ref.rst>`_ |
18 | 17 | * `Choosing a Filename <doc/lang_ref.rst#choosing-a-filename>`_ |
19 | 18 | * `Comments <doc/lang_ref.rst#comments>`_ |
20 | 19 | * `Namespace <doc/lang_ref.rst#ns>`_ |
@@ -43,7 +42,7 @@ actively worked on, and the intention is to support |
43 | 42 | * `Planning for Backwards Compatibility <doc/evolve_spec.rst#planning-for-backwards-compatibility>`_ |
44 | 43 | * `Leader-Clients <doc/evolve_spec.rst#leader-clients>`_ |
45 | 44 | * `Route Versioning <doc/evolve_spec.rst#route-versioning>`_ |
46 | | - * `Writing a Generator (.babelg.py) <doc/generator_ref.rst>`_ |
| 45 | + * `Writing a Generator (.stoneg.py) <doc/generator_ref.rst>`_ |
47 | 46 | * `Using the API Object <doc/generator_ref.rst#using-the-api-object>`_ |
48 | 47 | * `Creating an Output File <doc/generator_ref.rst#creating-an-output-file>`_ |
49 | 48 | * `Emit Methods <doc/generator_ref.rst#emit-methods>`_ |
@@ -63,7 +62,7 @@ over HTTP is gaining popularity, but just a few years ago, XML was the |
63 | 62 | standard. To compound the issue, developers need to support an increasing |
64 | 63 | number of language-specific SDKs to gain wide adoption. |
65 | 64 |
|
66 | | -Babel seeks to: |
| 65 | +Stone seeks to: |
67 | 66 |
|
68 | 67 | 1. Define API endpoints in terms of input and output data types that can |
69 | 68 | be consistently implemented in different protocols and languages. |
@@ -72,25 +71,21 @@ Babel seeks to: |
72 | 71 | 3. Improve the visibility developers have into their APIs by centralizing |
73 | 72 | specification and documentation. |
74 | 73 |
|
75 | | -If we only had one protocol and one language Babel API wouldn't be needed, but |
76 | | -unfortunately humanity was handicapped for good reason. See |
77 | | -`Why do we have multiple programming languages? <doc/joke.rst>`_ |
78 | | - |
79 | 74 | Assumptions |
80 | 75 | ----------- |
81 | 76 |
|
82 | | -Babel makes no assumptions about the protocol layer being used to make API |
| 77 | +Stone makes no assumptions about the protocol layer being used to make API |
83 | 78 | requests and return responses; its first use case is the Dropbox v2 API which |
84 | | -operates over HTTP. Babel does not come with nor enforce any particular RPC |
| 79 | +operates over HTTP. Stone does not come with nor enforce any particular RPC |
85 | 80 | framework. |
86 | 81 |
|
87 | | -Babel makes some assumptions about the data types supported in the serialization |
| 82 | +Stone makes some assumptions about the data types supported in the serialization |
88 | 83 | format and target programming language. It's assumed that there is a capacity |
89 | 84 | for representing dictionaries (unordered string keys -> value), lists, numeric |
90 | | -types, and strings. The intention is for Babel to map to a multitude of |
| 85 | +types, and strings. The intention is for Stone to map to a multitude of |
91 | 86 | serialization formats from JSON to more space-efficient representations. |
92 | 87 |
|
93 | | -Babel assumes that a route (or API endpoint) can have its request and |
| 88 | +Stone assumes that a route (or API endpoint) can have its request and |
94 | 89 | response types defined without relation to each other. In other words, the |
95 | 90 | type of response does not change based on the input to the endpoint. An |
96 | 91 | exception to this rule is afforded for error responses. |
@@ -100,122 +95,31 @@ exception to this rule is afforded for error responses. |
100 | 95 | Installation |
101 | 96 | ============ |
102 | 97 |
|
103 | | -Download or clone BabelAPI, and run the following in its root directory:: |
| 98 | +Download or clone StoneAPI, and run the following in its root directory:: |
104 | 99 |
|
105 | 100 | $ sudo python setup.py install |
106 | 101 |
|
107 | | -This will install a script ``babelapi`` to your PATH that can be run from the |
| 102 | +This will install a script ``stone`` to your PATH that can be run from the |
108 | 103 | command line:: |
109 | 104 |
|
110 | | - $ babelapi -h |
| 105 | + $ stone -h |
111 | 106 |
|
112 | 107 | Alternative |
113 | 108 | ----------- |
114 | 109 |
|
115 | | -If you choose not to install ``babelapi`` using the method above, you will need |
| 110 | +If you choose not to install ``stone`` using the method above, you will need |
116 | 111 | to ensure that you have the Python packages ``ply`` and ``six``, which can be |
117 | 112 | installed through ``pip``:: |
118 | 113 |
|
119 | 114 | $ pip install ply>=3.4 six>=1.3.0 |
120 | 115 |
|
121 | | -If the ``babelapi`` package is in your PYTHONPATH, you can replace ``babelapi`` |
122 | | -with ``python -m babelapi.cli`` as follows:: |
| 116 | +If the ``stone`` package is in your PYTHONPATH, you can replace ``stone`` |
| 117 | +with ``python -m stone.cli`` as follows:: |
123 | 118 |
|
124 | | - $ python -m babelapi.cli -h |
| 119 | + $ python -m stone.cli -h |
125 | 120 |
|
126 | | -If you have the ``babelapi`` package on your machine, but did not install it or |
| 121 | +If you have the ``stone`` package on your machine, but did not install it or |
127 | 122 | add its location to your PYTHONPATH, you can use the following:: |
128 | 123 |
|
129 | | - $ PYTOHNPATH=path/to/babelapi python -m babelapi.cli -h |
130 | | - |
131 | | -.. taste-of-babel: |
132 | | -
|
133 | | -A Taste of Babel |
134 | | -================ |
135 | | - |
136 | | -Here we define a hypothetical route that shows up in some form or another in |
137 | | -APIs for web services: querying the account information for a user of a |
138 | | -service. Our hypothetical spec lives in a file called ``users.babel``:: |
139 | | - |
140 | | - # We put this in the "users" namespace in anticipation that |
141 | | - # there would be many user-account-related routes. |
142 | | - namespace users |
143 | | - |
144 | | - # We define an AccountId as being a 10-character string |
145 | | - # once here to avoid declaring it each time. |
146 | | - alias AccountId = String(min_length=10, max_length=10) |
147 | | - |
148 | | - union Status |
149 | | - active |
150 | | - "The account is active." |
151 | | - inactive Timestamp("%a, %d %b %Y %H:%M:%S") |
152 | | - "The account is inactive. The value is when the account was |
153 | | - deactivated." |
154 | | - |
155 | | - struct Account |
156 | | - "Information about a user's account." |
157 | | - |
158 | | - account_id AccountId |
159 | | - "A unique identifier for the user's account." |
160 | | - email String(pattern="^[^@]+@[^@]+\.[^@]+$") |
161 | | - "The e-mail address of the user." |
162 | | - name String(min_length=1)? |
163 | | - "The user's full name. :val:`null` if no name was provided." |
164 | | - status Status |
165 | | - "The status of the account." |
166 | | - |
167 | | - example default "A regular user" |
168 | | - account_id="id-48sa2f0" |
169 | | - |
170 | | - name="Alexander the Great" |
171 | | - status=active |
172 | | - |
173 | | - # This struct represents the input data to the route. |
174 | | - struct GetAccountReq |
175 | | - account_id AccountId |
176 | | - |
177 | | - # This union represents the possible errors that might be returned. |
178 | | - union GetAccountErr |
179 | | - no_account |
180 | | - "No account with the requested id could be found." |
181 | | - perm_denied |
182 | | - "Insufficient privileges to query account information." |
183 | | - unknown* |
184 | | - |
185 | | - route get_account (GetAccountReq, Account, GetAccountErr) |
186 | | - "Get information about a specified user's account." |
187 | | - |
188 | | -Using the Python generator, we can generate a Python module that mirrors this |
189 | | -specification using the command-line interface. From the top-level of the |
190 | | -``babelapi`` folder, try:: |
191 | | - |
192 | | - $ babelapi generator/python/python.babelg.py users.babel . |
193 | | - INFO:babelapi.idl:Parsing spec users.babel |
194 | | - INFO:babelapi.compiler:Found generator at ... |
195 | | - INFO:babelapi.compiler:Running generator ... |
196 | | - INFO:bablesdk.generator.PythonGenerator:Copying babel_data_types.py to output folder |
197 | | - INFO:bablesdk.generator.PythonGenerator:Copying babel_serializers.py to output folder |
198 | | - INFO:bablesdk.generator.PythonGenerator:Generating ./users.py |
199 | | - |
200 | | -Now we can interact with the specification in Python:: |
201 | | - |
202 | | - $ python -i users.py |
203 | | - >>> a = Account() |
204 | | - >>> a.account_id = 1234 # fails type validation |
205 | | - Traceback (most recent call last): |
206 | | - ... |
207 | | - babel_data_types.ValidationError: '1234' expected to be a string, got integer |
208 | | - |
209 | | - >>> a.account_id = '1234' # fails length validation |
210 | | - Traceback (most recent call last): |
211 | | - ... |
212 | | - babel_data_types.ValidationError: '1234' must be at least 10 characters, got 4 |
213 | | - |
214 | | - >>> a.account_id = 'id-48sa2f0' # passes validation |
215 | | - |
216 | | - >>> # Now we use the included JSON serializer |
217 | | - >>> from babel_serializers import json_encode |
218 | | - >>> a2 = Account(account_id='id-48sa2f0', name='Alexander the Great', |
219 | | - |
220 | | - >>> json_encode(GetAccountRoute.result_data_type, a2) |
221 | | - '{"status": "active", "account_id": "id-48sa2f0", "name": "Alexander the Great", "email": "[email protected]"}' |
| 124 | + $ PYTOHNPATH=path/to/stone python -m stone.cli -h |
| 125 | + |