-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #48 from jgeewax/demo-parser
Added DemoRunner and cleaned up demo scripts.
- Loading branch information
Showing
11 changed files
with
266 additions
and
221 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import os | ||
from gcloud import datastore | ||
|
||
|
||
__all__ = ['get_dataset', 'CLIENT_EMAIL', 'DATASET_ID', 'PRIVATE_KEY_PATH'] | ||
|
||
|
||
CLIENT_EMAIL = '754762820716-gimou6egs2hq1rli7el2t621a1b04t9i@developer.gserviceaccount.com' | ||
DATASET_ID = 'gcloud-datastore-demo' | ||
PRIVATE_KEY_PATH = os.path.join(os.path.dirname(__file__), 'demo.key') | ||
|
||
|
||
def get_dataset(): | ||
return datastore.get_dataset(DATASET_ID, CLIENT_EMAIL, PRIVATE_KEY_PATH) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from gcloud import demo | ||
from gcloud import datastore | ||
|
||
|
||
demo.DemoRunner.from_module(datastore).run() |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# Welcome to the gCloud Datastore Demo! (hit enter) | ||
|
||
# We're going to walk through some of the basics... | ||
# Don't worry though. You don't need to do anything, just keep hitting enter... | ||
|
||
# Let's start by importing the demo module and getting a dataset: | ||
from gcloud.datastore import demo | ||
dataset = demo.get_dataset() | ||
|
||
# Let's create a new entity of type "Thing" and name it 'Toy': | ||
toy = dataset.entity('Thing') | ||
toy.update({'name': 'Toy'}) | ||
|
||
# Now let's save it to our datastore: | ||
toy.save() | ||
|
||
# If we look it up by its key, we should find it... | ||
print dataset.get_entities([toy.key()]) | ||
|
||
# And we should be able to delete it... | ||
toy.delete() | ||
|
||
# Since we deleted it, if we do another lookup it shouldn't be there again: | ||
print dataset.get_entities([toy.key()]) | ||
|
||
# Now let's try a more advanced query. | ||
# We'll start by look at all Thing entities: | ||
query = dataset.query().kind('Thing') | ||
|
||
# Let's look at the first two. | ||
print query.limit(2).fetch() | ||
|
||
# Now let's check for Thing entities named 'Computer' | ||
print query.filter('name =', 'Computer').fetch() | ||
|
||
# If you want to filter by multiple attributes, | ||
# you can string .filter() calls together. | ||
print query.filter('name =', 'Computer').filter('age =', 10).fetch() | ||
|
||
# You can also work inside a transaction. | ||
# (Check the official docs for explanations of what's happening here.) | ||
with dataset.transaction(): | ||
print 'Creating and savng an entity...' | ||
thing = dataset.entity('Thing') | ||
thing.key(thing.key().name('foo')) | ||
thing['age'] = 10 | ||
thing.save() | ||
|
||
print 'Creating and saving another entity...' | ||
thing2 = dataset.entity('Thing') | ||
thing2.key(thing2.key().name('bar')) | ||
thing2['age'] = 15 | ||
thing2.save() | ||
|
||
print 'Committing the transaction...' | ||
|
||
# Now that the transaction is commited, let's delete the entities. | ||
print thing.delete(), thing2.delete() | ||
|
||
# To rollback a transaction, just call .rollback() | ||
with dataset.transaction() as t: | ||
thing = dataset.entity('Thing') | ||
thing.key(thing.key().name('another')) | ||
thing.save() | ||
t.rollback() | ||
|
||
# Let's check if the entity was actually created: | ||
created = dataset.get_entities([thing.key()]) | ||
print 'yes' if created else 'no' | ||
|
||
# Remember, a key won't be complete until the transaction is commited. | ||
# That is, while inside the transaction block, thing.key() will be incomplete. | ||
with dataset.transaction(): | ||
thing = dataset.entity('Thing') | ||
thing.save() | ||
print thing.key() # This will be partial | ||
|
||
print thing.key() # This will be complete | ||
|
||
# Now let's delete the entity. | ||
thing.delete() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
from code import interact | ||
import itertools | ||
import os.path | ||
import sys | ||
import time | ||
|
||
|
||
class DemoRunner(object): | ||
"""An interactive runner of demo scripts.""" | ||
|
||
KEYPRESS_DELAY = 0.05 | ||
GLOBALS, LOCALS = globals(), locals() | ||
CODE, COMMENT = 'code', 'comment' | ||
|
||
def __init__(self, fp): | ||
self.lines = [line.rstrip() for line in fp.readlines()] | ||
|
||
@classmethod | ||
def from_module(cls, module): | ||
path = os.path.join(os.path.dirname(module.__file__), | ||
'demo', 'demo.py') | ||
|
||
return cls(open(path, 'r')) | ||
|
||
def run(self): | ||
line_groups = itertools.groupby(self.lines, self.get_line_type) | ||
|
||
for group_type, lines in line_groups: | ||
if group_type == self.COMMENT: | ||
self.write(lines) | ||
|
||
elif group_type == self.CODE: | ||
self.code(lines) | ||
|
||
interact('(Hit CTRL-D to exit...)', local=self.LOCALS) | ||
|
||
def wait(self): | ||
raw_input() | ||
|
||
@classmethod | ||
def get_line_type(cls, line): | ||
if line.startswith('#'): | ||
return cls.COMMENT | ||
else: | ||
return cls.CODE | ||
|
||
@staticmethod | ||
def get_indent_level(line): | ||
if not line.strip(): | ||
return None | ||
return len(line) - len(line.lstrip()) | ||
|
||
def write(self, lines): | ||
print '\n'.join(lines), | ||
self.wait() | ||
|
||
def code(self, lines): | ||
code_lines = [] | ||
|
||
for line in lines: | ||
indent = self.get_indent_level(line) | ||
|
||
# If we've completed a block, | ||
# run whatever code was built up in code_lines. | ||
if indent == 0: | ||
self._execute_lines(code_lines) | ||
code_lines = [] | ||
|
||
# Print the prefix for the line depending on the indentation level. | ||
if indent == 0: | ||
print '>>> ', | ||
elif indent > 0: | ||
print '\n... ', | ||
elif indent is None: | ||
continue | ||
|
||
# Break the line into the code section and the comment section. | ||
if '#' in line: | ||
code, comment = line.split('#', 2) | ||
else: | ||
code, comment = line, None | ||
|
||
# 'Type' out the comment section. | ||
for char in code.rstrip(): | ||
time.sleep(self.KEYPRESS_DELAY) | ||
sys.stdout.write(char) | ||
sys.stdout.flush() | ||
|
||
# Print the comment section (not typed out). | ||
if comment: | ||
sys.stdout.write(' # %s' % comment.strip()) | ||
|
||
# Add the current line to the list of lines to be run in this block. | ||
code_lines.append(line) | ||
|
||
# If we had any code built up that wasn't part of a completed block | ||
# (ie, the lines ended with an indented line), | ||
# run that code. | ||
if code_lines: | ||
self._execute_lines(code_lines) | ||
|
||
def _execute_lines(self, lines): | ||
if lines: | ||
self.wait() | ||
|
||
# Yes, this is crazy unsafe... but it's demo code. | ||
exec('\n'.join(lines), self.GLOBALS, self.LOCALS) |
Oops, something went wrong.