Skip to content

Commit 0faf6be

Browse files
committed
Improved introduction to BabelAPI and example of code generation.
1 parent 7f8a6db commit 0faf6be

File tree

9 files changed

+534
-128
lines changed

9 files changed

+534
-128
lines changed

README.rst

Lines changed: 247 additions & 128 deletions
Large diffs are not rendered by default.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from babelapi.generator.generator import CodeGenerator
2+
3+
class ExampleGenerator(CodeGenerator):
4+
def generate(self):
5+
"""Generates a file that lists each namespace."""
6+
with self.output_to_relative_path('ex1.out'):
7+
for namespace in self.api.namespaces.values():
8+
self.emit_line(namespace.name)

example/generator/ex1/ex1.out

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
files
2+
users
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from babelapi.generator.generator import CodeGenerator
2+
3+
class ExamplePythonGenerator(CodeGenerator):
4+
def generate(self):
5+
"""Generates a module for each namespace."""
6+
for namespace in self.api.namespaces.values():
7+
# One module per namespace is created. The module takes the name
8+
# of the namespace.
9+
with self.output_to_relative_path('{}.py'.format(namespace.name)):
10+
self._generate_namespace_module(namespace)
11+
12+
def _generate_namespace_module(self, namespace):
13+
self.emit_line('def noop():')
14+
with self.indent():
15+
self.emit_line('pass')

example/generator/ex2/files.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def noop():
2+
pass

example/generator/ex2/users.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def noop():
2+
pass
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from babelapi.data_type import Struct
2+
from babelapi.generator.generator import CodeGeneratorMonolingual
3+
from babelapi.lang.python import PythonTargetLanguage
4+
5+
class ExamplePythonGenerator(CodeGeneratorMonolingual):
6+
7+
# PythonTargetLanguage has helper methods for formatting class, obj
8+
# and variable names (some languages use underscores to separate words,
9+
# others use camelcase).
10+
lang = PythonTargetLanguage()
11+
12+
def generate(self):
13+
"""Generates a module for each namespace."""
14+
for namespace in self.api.namespaces.values():
15+
# One module per namespace is created. The module takes the name
16+
# of the namespace.
17+
with self.output_to_relative_path('{}.py'.format(namespace.name)):
18+
self._generate_namespace_module(namespace)
19+
20+
def _generate_namespace_module(self, namespace):
21+
for data_type in namespace.linearize_data_types():
22+
if not isinstance(data_type, Struct):
23+
# Do not handle Union types
24+
continue
25+
26+
# Define a class for each struct
27+
class_def = 'class {}(object):'.format(self.lang.format_class(data_type.name))
28+
self.emit_line(class_def)
29+
30+
with self.indent():
31+
if data_type.doc:
32+
self.emit_line('"""')
33+
self.emit_wrapped_lines(data_type.doc)
34+
self.emit_line('"""')
35+
36+
self.emit_empty_line()
37+
38+
# Define constructor to take each field
39+
self.emit_line('def __init__', trailing_newline=False)
40+
args = ['self']
41+
for field in data_type.fields:
42+
args.append(self.lang.format_variable(field.name))
43+
self._generate_func_arg_list(args)
44+
self.emit(':')
45+
self.emit_empty_line()
46+
47+
with self.indent():
48+
if data_type.fields:
49+
# Body of init should assign all init vars
50+
for field in data_type.fields:
51+
if field.doc:
52+
self.emit_wrapped_lines(field.doc, prefix='# ')
53+
member_name = self.lang.format_variable(field.name)
54+
self.emit_line('self.{0} = {0}'.format(member_name))
55+
else:
56+
self.emit_line('pass')
57+
self.emit_empty_line()

example/generator/ex3/files.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
class Empty(object):
2+
3+
def __init__(self):
4+
pass
5+
6+
class FileTarget(object):
7+
8+
def __init__(self,
9+
path,
10+
rev):
11+
# Path from root. Should be an empty string for root.
12+
self.path = path
13+
# Revision of target file.
14+
self.rev = rev
15+
16+
class FileInfo(object):
17+
18+
def __init__(self,
19+
name):
20+
# Name of file.
21+
self.name = name
22+
23+
class SubError(object):
24+
25+
def __init__(self,
26+
reason):
27+
# A code indicating the type of error.
28+
self.reason = reason
29+
30+
class UploadSessionStart(object):
31+
32+
def __init__(self,
33+
upload_id):
34+
# A unique identifier for the upload session.
35+
self.upload_id = upload_id
36+
37+
class UploadAppend(object):
38+
39+
def __init__(self,
40+
upload_id,
41+
offset):
42+
# Identifies the upload session to append data to.
43+
self.upload_id = upload_id
44+
# The offset into the file of the current chunk of data being uploaded.
45+
# It can also be thought of as the amount of data that has been uploaded
46+
# so far. We use the offset as a sanity check.
47+
self.offset = offset
48+
49+
class IncorrectOffsetError(object):
50+
51+
def __init__(self,
52+
correct_offset):
53+
self.correct_offset = correct_offset
54+
55+
class UpdateParentRev(object):
56+
57+
def __init__(self,
58+
parent_rev):
59+
self.parent_rev = parent_rev
60+
61+
class UploadCommit(object):
62+
63+
def __init__(self,
64+
path,
65+
mode,
66+
append_to,
67+
autorename,
68+
client_modified_utc,
69+
mute):
70+
# Path in the user's Dropbox to save the file.
71+
self.path = path
72+
# The course of action to take if a file already exists at
73+
# :field:`path`.
74+
self.mode = mode
75+
# If specified, the current chunk of data should be appended to an
76+
# existing upload session.
77+
self.append_to = append_to
78+
# Whether the file should be autorenamed in the event of a conflict.
79+
self.autorename = autorename
80+
# Self reported time of when this file was created or modified.
81+
self.client_modified_utc = client_modified_utc
82+
# Whether the devices that the user has linked should notify them of the
83+
# new or updated file.
84+
self.mute = mute
85+
86+
class ConflictError(object):
87+
88+
def __init__(self,
89+
reason):
90+
self.reason = reason
91+

example/generator/ex3/users.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
class Empty(object):
2+
3+
def __init__(self):
4+
pass
5+
6+
class Space(object):
7+
"""
8+
The space quota info for a user.
9+
"""
10+
11+
def __init__(self,
12+
quota,
13+
private,
14+
shared,
15+
datastores):
16+
# The user's total quota allocation (bytes).
17+
self.quota = quota
18+
# The user's used quota outside of shared folders (bytes).
19+
self.private = private
20+
# The user's used quota in shared folders (bytes).
21+
self.shared = shared
22+
# The user's used quota in datastores (bytes).
23+
self.datastores = datastores
24+
25+
class Team(object):
26+
"""
27+
Information about a team.
28+
"""
29+
30+
def __init__(self,
31+
id,
32+
name):
33+
# The team's unique ID.
34+
self.id = id
35+
# The name of the team.
36+
self.name = name
37+
38+
class Name(object):
39+
"""
40+
Contains several ways a name might be represented to make
41+
internationalization more convenient.
42+
"""
43+
44+
def __init__(self,
45+
given_name,
46+
surname,
47+
familiar_name,
48+
display_name):
49+
# Also known as a first name.
50+
self.given_name = given_name
51+
# Also known as a last name or family name.
52+
self.surname = surname
53+
# Locale-dependent familiar name. Generally matches :field:`given_name`
54+
# or :field:`display_name`.
55+
self.familiar_name = familiar_name
56+
# A name that can be used directly to represent the name of a user's
57+
# Dropbox account.
58+
self.display_name = display_name
59+
60+
class BasicAccountInfo(object):
61+
"""
62+
Basic information about a user's account.
63+
"""
64+
65+
def __init__(self,
66+
account_id,
67+
name):
68+
# The user's unique Dropbox ID.
69+
self.account_id = account_id
70+
# Details of a user's name.
71+
self.name = name
72+
73+
class MeInfo(object):
74+
"""
75+
Information about a user's account.
76+
"""
77+
78+
def __init__(self,
79+
email,
80+
country,
81+
locale,
82+
referral_link,
83+
space,
84+
team,
85+
is_paired):
86+
# The user's e-mail address.
87+
self.email = email
88+
# The user's two-letter country code, if available.
89+
self.country = country
90+
# The language setting that user specified.
91+
self.locale = locale
92+
# The user's :link:`referral link https://www.dropbox.com/referrals`.
93+
self.referral_link = referral_link
94+
# The user's quota.
95+
self.space = space
96+
# If this account is a member of a team.
97+
self.team = team
98+
# Whether the user has a personal and work account. If the authorized
99+
# account is personal, then :field:`team` will always be :val:`Null`,
100+
# but :field:`is_paired` will indicate if a work account is linked.
101+
self.is_paired = is_paired
102+
103+
class InfoRequest(object):
104+
105+
def __init__(self,
106+
account_id):
107+
# A user's account identifier. Use :val:`"me"` to get information for
108+
# the current account.
109+
self.account_id = account_id
110+

0 commit comments

Comments
 (0)