Removes python client. https://reviews.apache.org/r/45976


Project: http://git-wip-us.apache.org/repos/asf/incubator-wave/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-wave/commit/78cbf78f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-wave/tree/78cbf78f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-wave/diff/78cbf78f

Branch: refs/heads/master
Commit: 78cbf78fb74ee739f177920c8c5f25bc6a59af81
Parents: 4070747
Author: Yuri Zelikov <[email protected]>
Authored: Mon Apr 25 21:09:24 2016 +0300
Committer: Yuri Zelikov <[email protected]>
Committed: Mon Apr 25 21:09:24 2016 +0300

----------------------------------------------------------------------
 .gitignore                                      |   2 -
 LICENSE                                         |  46 -
 wave/dist/CHANGES                               | 180 ----
 wave/src/main/java/python/api/__init__.py       |  20 -
 .../java/python/api/appengine_robot_runner.py   | 204 ----
 wave/src/main/java/python/api/blip.py           | 949 -------------------
 wave/src/main/java/python/api/blip_test.py      | 383 --------
 .../java/python/api/commandline_robot_runner.py |  84 --
 .../python/api/commandline_robot_runner_test.py |  93 --
 wave/src/main/java/python/api/django_oauth.py   | 114 ---
 wave/src/main/java/python/api/element.py        | 370 --------
 wave/src/main/java/python/api/element_test.py   | 218 -----
 wave/src/main/java/python/api/errors.py         |  31 -
 wave/src/main/java/python/api/events.py         | 304 ------
 .../main/java/python/api/module_test_runner.py  |  43 -
 wave/src/main/java/python/api/oauth/LICENSE     |  22 -
 wave/src/main/java/python/api/oauth/__init__.py | 541 -----------
 wave/src/main/java/python/api/ops.py            | 482 ----------
 wave/src/main/java/python/api/ops_test.py       |  75 --
 wave/src/main/java/python/api/robot.py          | 343 -------
 wave/src/main/java/python/api/robot_test.py     | 257 -----
 wave/src/main/java/python/api/run_unit_tests.py |  49 -
 wave/src/main/java/python/api/search.py         | 153 ---
 wave/src/main/java/python/api/search_test.py    |  79 --
 .../src/main/java/python/api/simplejson/LICENSE |  19 -
 .../main/java/python/api/simplejson/__init__.py | 424 ---------
 .../main/java/python/api/simplejson/decoder.py  | 431 ---------
 .../main/java/python/api/simplejson/encoder.py  | 476 ----------
 .../java/python/api/simplejson/jsonfilter.py    |  60 --
 .../java/python/api/simplejson/ordered_dict.py  | 139 ---
 .../main/java/python/api/simplejson/scanner.py  |  87 --
 .../src/main/java/python/api/simplejson/tool.py |  57 --
 wave/src/main/java/python/api/testdata.py       | 225 -----
 wave/src/main/java/python/api/util.py           | 198 ----
 wave/src/main/java/python/api/util_test.py      | 187 ----
 wave/src/main/java/python/api/wavelet.py        | 481 ----------
 wave/src/main/java/python/api/wavelet_test.py   | 199 ----
 wave/src/main/java/python/api/waveservice.py    | 468 ---------
 .../main/java/python/api/waveservice_test.py    |  72 --
 39 files changed, 8565 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/78cbf78f/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index 267def7..a9cec8c 100755
--- a/.gitignore
+++ b/.gitignore
@@ -20,7 +20,6 @@
 */gwt-unitCache
 war/WEB-INF
 *.old
-*.log*
 .DS_Store
 
 ### IntelliJ Idea
@@ -50,7 +49,6 @@ reports/
 ### Generated Sources
 **/generated/
 ### Gwt Testing
-wave/gwt-unitCache
 ### config
 wave/local.net.cfg.lua
 wave/config/wave.conf

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/78cbf78f/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
index a2be50d..6bf7059 100644
--- a/LICENSE
+++ b/LICENSE
@@ -201,52 +201,6 @@
    limitations under the License.
 
 ***THE FOLLOWING LICENSE APPLIES TO***
-- The OAuth python library located at /src/python/api/oauth/
-  Copyright (c) 2007 Andy Smith
-
-The MIT License
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-***THE FOLLOWING LICENSE APPLIES TO***
-- SimpleJSON located at /src/python/api/simplejson/
-  Copyright (c) 2006 Bob Ippolito
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-***THE FOLLOWING LICENSE APPLIES TO***
 - Protobuf Descriptors located at /src/google/protobuf/descriptor.proto
 
 Protocol Buffers - Google's data interchange format

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/78cbf78f/wave/dist/CHANGES
----------------------------------------------------------------------
diff --git a/wave/dist/CHANGES b/wave/dist/CHANGES
index cf47949..a2d6c8e 100644
--- a/wave/dist/CHANGES
+++ b/wave/dist/CHANGES
@@ -437,147 +437,6 @@ Author: Yuri Zelikov <[email protected]>
 Date:   Sat Jan 18 16:06:56 2014 +0200
 
     Merge branch 'wave-0.4-release' into master
-    
-    Conflicts:
-       .classpath
-       .gitignore
-       .project_template
-       CHANGES
-       NOTICE
-       README
-       build.properties
-       build.xml
-       jaas.config
-       prosody.cfg.lua.example
-       proto_src/org/waveprotocol/box/attachment/AttachmentProto.java
-       
proto_src/org/waveprotocol/box/server/persistence/protos/ProtoAccountStoreData.java
-       run-server.bat
-       server-config.xml
-       server.federation.config
-       src/com/google/gwt/build.xml
-       src/com/google/gwt/websockets/WebSockets.gwt.xml
-       src/com/google/wave/api/data/Data.gwt.xml
-       src/com/google/wave/api/robot/Robot.gwt.xml
-       src/org/waveprotocol/box/server/frontend/WaveletInfo.java
-       src/org/waveprotocol/box/server/persistence/protos/delta-store.proto
-       src/org/waveprotocol/box/server/waveserver/SimpleSearchProviderImpl.java
-       src/org/waveprotocol/box/server/waveserver/Wave.java
-       
src/org/waveprotocol/box/webclient/search/i18n/SearchPresenterMessages_sl.properties
-       
src/org/waveprotocol/box/webclient/search/i18n/SearchWidgetMessages_sl.properties
-       src/org/waveprotocol/box/webclient/search/mock/search.html
-       src/org/waveprotocol/protobuf/build.xml
-       src/org/waveprotocol/pst/templates/api/properties
-       src/org/waveprotocol/pst/templates/builder/properties
-       src/org/waveprotocol/pst/templates/gson/properties
-       src/org/waveprotocol/pst/templates/jso/properties
-       src/org/waveprotocol/pst/templates/pojo/properties
-       src/org/waveprotocol/pst/templates/proto/properties
-       src/org/waveprotocol/pst/templates/util/properties
-       src/org/waveprotocol/wave/client/build.xml
-       src/org/waveprotocol/wave/client/common/build.xml
-       src/org/waveprotocol/wave/client/scheduler/build.xml
-       
src/org/waveprotocol/wave/client/wavepanel/impl/toolbar/color/ComplexColorPicker.css
-       
src/org/waveprotocol/wave/client/wavepanel/impl/toolbar/color/SimpleColorPicker.css
-       
src/org/waveprotocol/wave/client/wavepanel/impl/toolbar/color/i18n/ColorPickerMessages_en.properties
-       
src/org/waveprotocol/wave/client/wavepanel/impl/toolbar/color/i18n/ColorPickerMessages_es.properties
-       
src/org/waveprotocol/wave/client/wavepanel/impl/toolbar/i18n/LinkerMessages_fr.properties
-       src/org/waveprotocol/wave/common/build.xml
-       src/org/waveprotocol/wave/communication/build.xml
-       src/org/waveprotocol/wave/concurrencycontrol/build.xml
-       src/org/waveprotocol/wave/crypto/build.xml
-       src/org/waveprotocol/wave/diff/build.xml
-       src/org/waveprotocol/wave/federation/build.xml
-       src/org/waveprotocol/wave/media/build.xml
-       src/org/waveprotocol/wave/model/build.xml
-       src/org/waveprotocol/wave/testing/build.xml
-       src/org/waveprotocol/wave/util/build.xml
-       src/python/api/__init__.py
-       src/python/api/appengine_robot_runner.py
-       src/python/api/blip.py
-       src/python/api/blip_test.py
-       src/python/api/commandline_robot_runner.py
-       src/python/api/commandline_robot_runner_test.py
-       src/python/api/django_oauth.py
-       src/python/api/element.py
-       src/python/api/element_test.py
-       src/python/api/errors.py
-       src/python/api/events.py
-       src/python/api/module_test_runner.py
-       src/python/api/ops.py
-       src/python/api/ops_test.py
-       src/python/api/robot.py
-       src/python/api/robot_test.py
-       src/python/api/run_unit_tests.py
-       src/python/api/search.py
-       src/python/api/search_test.py
-       src/python/api/testdata.py
-       src/python/api/util.py
-       src/python/api/util_test.py
-       src/python/api/wavelet.py
-       src/python/api/wavelet_test.py
-       src/python/api/waveservice.py
-       src/python/api/waveservice_test.py
-       test/org/waveprotocol/wave/concurrencycontrol/Tests.gwt.xml
-       test/org/waveprotocol/wave/model/experimental/schema/bad1.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad10.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad11.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad12.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad13.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad14.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad15.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad16.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad17.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad18.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad19.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad2.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad20.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad21.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad22.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad23.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad24.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad3.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad4.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad5.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad6.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad7.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad8.schema
-       test/org/waveprotocol/wave/model/experimental/schema/bad9.schema
-       test/org/waveprotocol/wave/model/experimental/schema/good1.schema
-       test/org/waveprotocol/wave/model/experimental/schema/good10.schema
-       test/org/waveprotocol/wave/model/experimental/schema/good11.schema
-       test/org/waveprotocol/wave/model/experimental/schema/good12.schema
-       test/org/waveprotocol/wave/model/experimental/schema/good13.schema
-       test/org/waveprotocol/wave/model/experimental/schema/good14.schema
-       test/org/waveprotocol/wave/model/experimental/schema/good15.schema
-       test/org/waveprotocol/wave/model/experimental/schema/good16.schema
-       test/org/waveprotocol/wave/model/experimental/schema/good2.schema
-       test/org/waveprotocol/wave/model/experimental/schema/good3.schema
-       test/org/waveprotocol/wave/model/experimental/schema/good4.schema
-       test/org/waveprotocol/wave/model/experimental/schema/good5.schema
-       test/org/waveprotocol/wave/model/experimental/schema/good6.schema
-       test/org/waveprotocol/wave/model/experimental/schema/good7.schema
-       test/org/waveprotocol/wave/model/experimental/schema/good8.schema
-       test/org/waveprotocol/wave/model/experimental/schema/good9.schema
-       test/org/waveprotocol/wave/model/supplement/tests.gwt.xml
-       test/org/waveprotocol/wave/model/tests.gwt.xml
-       third_party/codegen/gwt/README.google
-       third_party/codegen/gwt/gwt-dev.jar
-       third_party/codegen/gwt/gwt-user.jar
-       third_party/runtime/bouncycastle/LICENSE.html
-       third_party/runtime/gson/LICENSE
-       third_party/runtime/guava/README.google
-       third_party/runtime/jetty/README.google
-       third_party/runtime/libidn/LICENSE
-       third_party/runtime/libidn/README.google
-       third_party/runtime/libidn/libidn-1.26.jar
-       third_party/runtime/mongo-driver/README.google
-       third_party/runtime/protobuf/README.google
-       third_party/test/jmock/README.google
-       third_party/test/mockito/README.google
-       third_party/test/mockito/mockito-all-1.9.5.jar
-       
tools/eclipse-launch/src.org.waveprotocol.wave.client.editor.examples.img.Img_Example-launch
-       
tools/eclipse-launch/src.org.waveprotocol.wave.client.editor.harness.EditorTest-launch
-       war/.gitignore
 
 commit 0b550672da3c923fbc6be0a963d2bf54c735b783
 Author: Yuri Zelikov <[email protected]>
@@ -911,45 +770,6 @@ Author: Ali Lown <[email protected]>
 Date:   Tue Aug 27 19:14:34 2013 +0000
 
     Merge branch 'trunk' into 0.4-release-staging
-    
-    Conflicts:
-       README
-       src/org/waveprotocol/box/waveimport/WaveExport.java
-       src/org/waveprotocol/box/waveimport/WaveImport.java
-       src/org/waveprotocol/box/waveimport/google/RobotApi.java
-       src/org/waveprotocol/box/waveimport/google/RobotSearchDigest.java
-       
src/org/waveprotocol/box/waveimport/google/RobotSearchDigestGsonImpl.java
-       src/org/waveprotocol/box/waveimport/google/RobotSearchDigestImpl.java
-       src/org/waveprotocol/box/waveimport/google/RobotSearchDigestUtil.java
-       
src/org/waveprotocol/box/waveimport/google/oauth/NeedNewOAuthTokenException.java
-       src/org/waveprotocol/box/waveimport/google/oauth/OAuthCredentials.java
-       src/org/waveprotocol/box/waveimport/google/oauth/OAuthRequestHelper.java
-       
src/org/waveprotocol/box/waveimport/google/oauth/OAuthedFetchService.java
-       src/org/waveprotocol/box/waveimport/google/oauth/StableUserId.java
-       src/org/waveprotocol/box/waveimport/google/oauth/UserContext.java
-       
src/org/waveprotocol/box/webclient/client/i18n/SessionMessages_es.properties
-       
src/org/waveprotocol/box/webclient/client/i18n/SessionMessages_fr.properties
-       
src/org/waveprotocol/box/webclient/client/i18n/WebClientMessages_es.properties
-       
src/org/waveprotocol/box/webclient/client/i18n/WebClientMessages_fr.properties
-       
src/org/waveprotocol/box/webclient/search/i18n/SearchPresenterMessages_sl.properties
-       
src/org/waveprotocol/box/webclient/search/i18n/SearchWidgetMessages_es.properties
-       
src/org/waveprotocol/box/webclient/search/i18n/SearchWidgetMessages_sl.properties
-       
src/org/waveprotocol/box/webclient/widget/error/i18n/ErrorMessages_es.properties
-       
src/org/waveprotocol/wave/client/wavepanel/impl/edit/i18n/ActionMessages_es.properties
-       
src/org/waveprotocol/wave/client/wavepanel/impl/menu/i18n/MenuMessages_fr.properties
-       
src/org/waveprotocol/wave/client/wavepanel/impl/menu/i18n/MenuMessages_sl.properties
-       
src/org/waveprotocol/wave/client/wavepanel/impl/toolbar/attachment/i18n/AttachmentMessages_fr.properties
-       
src/org/waveprotocol/wave/client/wavepanel/impl/toolbar/attachment/i18n/AttachmentMessages_sl.properties
-       
src/org/waveprotocol/wave/client/wavepanel/impl/toolbar/gadget/i18n/GadgetCategoryMessages_es.properties
-       
src/org/waveprotocol/wave/client/wavepanel/impl/toolbar/gadget/i18n/GadgetSelectorMessages_sl.properties
-       
src/org/waveprotocol/wave/client/wavepanel/impl/toolbar/i18n/LinkerMessages_es.properties
-       
src/org/waveprotocol/wave/client/wavepanel/impl/toolbar/i18n/LinkerMessages_fr.properties
-       
src/org/waveprotocol/wave/client/wavepanel/impl/toolbar/i18n/ToolbarMessages_fr.properties
-       
src/org/waveprotocol/wave/client/wavepanel/view/dom/full/i18n/ReplyBoxMessages_es.properties
-       
src/org/waveprotocol/wave/client/wavepanel/view/dom/full/i18n/ReplyBoxMessages_fr.properties
-       
src/org/waveprotocol/wave/client/widget/profile/i18n/ProfilePopupMessages_es.properties
-       src/org/waveprotocol/wave/migration/build.xml
-    
     git-svn-id: 
https://svn.apache.org/repos/asf/incubator/wave/branches/wave-0.4-release@1517927
 13f79535-47bb-0310-9956-ffa450edef68
 
 commit 615d44352fccf53db12bc43829d7d7f2c2155410

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/78cbf78f/wave/src/main/java/python/api/__init__.py
----------------------------------------------------------------------
diff --git a/wave/src/main/java/python/api/__init__.py 
b/wave/src/main/java/python/api/__init__.py
deleted file mode 100644
index a92a86c..0000000
--- a/wave/src/main/java/python/api/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/usr/bin/python
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-"""Declares the api package."""

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/78cbf78f/wave/src/main/java/python/api/appengine_robot_runner.py
----------------------------------------------------------------------
diff --git a/wave/src/main/java/python/api/appengine_robot_runner.py 
b/wave/src/main/java/python/api/appengine_robot_runner.py
deleted file mode 100644
index 776f825..0000000
--- a/wave/src/main/java/python/api/appengine_robot_runner.py
+++ /dev/null
@@ -1,204 +0,0 @@
-#!/usr/bin/python
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-"""A module to run wave robots on app engine."""
-
-
-import logging
-import sys
-
-import events
-
-from google.appengine.api import urlfetch
-from google.appengine.ext import webapp
-from google.appengine.ext.webapp.util import run_wsgi_app
-
-
-class CapabilitiesHandler(webapp.RequestHandler):
-  """Handler to forward a request ot a handler of a robot."""
-
-  def __init__(self, method, contenttype):
-    """Initializes this handler with a specific robot."""
-    self._method = method
-    self._contenttype = contenttype
-
-  def get(self):
-    """Handles HTTP GET request."""
-    self.response.headers['Content-Type'] = self._contenttype
-    self.response.out.write(self._method())
-
-class ProfileHandler(webapp.RequestHandler):
-  """Handler to forward a request ot a handler of a robot."""
-
-  def __init__(self, method, contenttype):
-    """Initializes this handler with a specific robot."""
-    self._method = method
-    self._contenttype = contenttype
-
-  def get(self):
-    """Handles HTTP GET request."""
-    self.response.headers['Content-Type'] = self._contenttype
-    # Respond with proxied profile if name specified
-    if self.request.get('name'):
-      self.response.out.write(self._method(self.request.get('name')))
-    else:
-      self.response.out.write(self._method())
-
-class RobotEventHandler(webapp.RequestHandler):
-  """Handler for the dispatching of events to various handlers to a robot.
-
-  This handler only responds to post events with a JSON post body. Its primary
-  task is to separate out the context data from the events in the post body
-  and dispatch all events in order. Once all events have been dispatched
-  it serializes the context data and its associated operations as a response.
-  """
-
-  def __init__(self, robot):
-    """Initializes self with a specific robot."""
-    self._robot = robot
-
-  def get(self):
-    """Handles the get event for debugging.
-
-    This is useful for debugging but since event bundles tend to be
-    rather big it often won't fit for more complex requests.
-    """
-    ops = self.request.get('events')
-    if ops:
-      self.request.body = events
-      self.post()
-
-  def post(self):
-    """Handles HTTP POST requests."""
-    json_body = self.request.body
-    if not json_body:
-      # TODO(davidbyttow): Log error?
-      return
-
-    # Redirect stdout to stderr while executing handlers. This way, any stray
-    # "print" statements in bot code go to the error logs instead of breaking
-    # the JSON response sent to the HTTP channel.
-    saved_stdout, sys.stdout = sys.stdout, sys.stderr
-
-    json_body = unicode(json_body, 'utf8')
-    logging.info('Incoming: %s', json_body)
-    json_response = self._robot.process_events(json_body)
-    logging.info('Outgoing: %s', json_response)
-
-    sys.stdout = saved_stdout
-
-    # Build the response.
-    self.response.headers['Content-Type'] = 'application/json; charset=utf-8'
-    self.response.out.write(json_response.encode('utf-8'))
-
-
-def operation_error_handler(event, wavelet):
-  """Default operation error handler, logging what went wrong."""
-  if isinstance(event, events.OperationError):
-    logging.error('Previously operation failed: id=%s, message: %s',
-                  event.operation_id, event.error_message)
-
-
-def appengine_post(url, data, headers):
-  result = urlfetch.fetch(
-      method='POST',
-      url=url,
-      payload=data,
-      headers=headers,
-      deadline=10)
-  return result.status_code, result.content
-
-
-class RobotVerifyTokenHandler(webapp.RequestHandler):
-  """Handler for the token_verify request."""
-
-  def __init__(self, robot):
-    """Initializes self with a specific robot."""
-    self._robot = robot
-
-  def get(self):
-    """Handles the get event for debugging. Ops usually too long."""
-    token, st = self._robot.get_verification_token_info()
-    logging.info('token=' + token)
-    if token is None:
-      self.error(404)
-      self.response.out.write('No token set')
-      return
-    if st is not None:
-      if self.request.get('st') != st:
-        self.response.out.write('Invalid st value passed')
-        return
-    self.response.out.write(token)
-
-
-def create_robot_webapp(robot, debug=False, extra_handlers=None):
-  """Returns an instance of webapp.WSGIApplication with robot handlers."""
-  if not extra_handlers:
-    extra_handlers = []
-  return webapp.WSGIApplication([('.*/_wave/capabilities.xml',
-                                  lambda: CapabilitiesHandler(
-                                                     robot.capabilities_xml,
-                                                     'application/xml')),
-                                 ('.*/_wave/robot/profile',
-                                  lambda: ProfileHandler(
-                                                     robot.profile_json,
-                                                     'application/json')),
-                                 ('.*/_wave/robot/jsonrpc',
-                                  lambda: RobotEventHandler(robot)),
-                                 ('.*/_wave/verify_token',
-                                  lambda: RobotVerifyTokenHandler(robot)),
-                                ] + extra_handlers,
-                                debug=debug)
-
-
-def run(robot, debug=False, log_errors=True, extra_handlers=None):
-  """Sets up the webapp handlers for this robot and starts listening.
-
-    A robot is typically setup in the following steps:
-      1. Instantiate and define robot.
-      2. Register various handlers that it is interested in.
-      3. Call Run, which will setup the handlers for the app.
-    For example:
-      robot = Robot('Terminator',
-                    image_url='http://www.sky.net/models/t800.png',
-                    profile_url='http://www.sky.net/models/t800.html')
-      robot.register_handler(WAVELET_PARTICIPANTS_CHANGED, KillParticipant)
-      run(robot)
-
-    Args:
-      robot: the robot to run. This robot is modified to use app engines
-          urlfetch for posting http.
-      debug: Optional variable that defaults to False and is passed through
-          to the webapp application to determine if it should show debug info.
-      log_errors: Optional flag that defaults to True and determines whether
-          a default handlers to catch errors should be setup that uses the
-          app engine logging to log errors.
-      extra_handlers: Optional list of tuples that are passed to the webapp
-          to install more handlers. For example, passing
-            [('/about', AboutHandler),] would install an extra about handler
-            for the robot.
-  """
-  # App Engine expects to construct a class with no arguments, so we
-  # pass a lambda that constructs the appropriate handler with
-  # arguments from the enclosing scope.
-  if log_errors:
-    robot.register_handler(events.OperationError, operation_error_handler)
-  robot.set_http_post(appengine_post)
-  app = create_robot_webapp(robot, debug, extra_handlers)
-  run_wsgi_app(app)

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/78cbf78f/wave/src/main/java/python/api/blip.py
----------------------------------------------------------------------
diff --git a/wave/src/main/java/python/api/blip.py 
b/wave/src/main/java/python/api/blip.py
deleted file mode 100644
index 7f103d9..0000000
--- a/wave/src/main/java/python/api/blip.py
+++ /dev/null
@@ -1,949 +0,0 @@
-#!/usr/bin/python2.4
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-import UserDict
-
-import element
-import errors
-
-import util
-
-class Annotation(object):
-  """Models an annotation on a document.
-
-  Annotations are key/value pairs over a range of content. Annotations
-  can be used to store data or to be interpreted by a client when displaying
-  the data.
-  """
-
-  # Use the following constants to control the display of the client
-
-  #: Reserved annotation for setting background color of text.
-  BACKGROUND_COLOR = "style/backgroundColor"
-  #: Reserved annotation for setting color of text.
-  COLOR = "style/color"
-  #: Reserved annotation for setting font family of text.
-  FONT_FAMILY = "style/fontFamily"
-  #: Reserved annotation for setting font family of text.
-  FONT_SIZE = "style/fontSize"
-  #: Reserved annotation for setting font style of text.
-  FONT_STYLE = "style/fontStyle"
-  #: Reserved annotation for setting font weight of text.
-  FONT_WEIGHT = "style/fontWeight"
-  #: Reserved annotation for setting text decoration.
-  TEXT_DECORATION = "style/textDecoration"
-  #: Reserved annotation for setting vertical alignment.
-  VERTICAL_ALIGN = "style/verticalAlign"
-  #: Reserved annotation for setting link.
-  LINK = "link/manual"
-
-  def __init__(self, name, value, start, end):
-    self._name = name
-    self._value = value
-    self._start = start
-    self._end = end
-
-  @property
-  def name(self):
-    return self._name
-
-  @property
-  def value(self):
-    return self._value
-
-  @property
-  def start(self):
-    return self._start
-
-  @property
-  def end(self):
-    return self._end
-
-  def _shift(self, where, inc):
-    """Shift annotation by 'inc' if it (partly) overlaps with 'where'."""
-    if self._start >= where:
-      self._start += inc
-    if self._end >= where:
-      self._end += inc
-
-  def serialize(self):
-    """Serializes the annotation.
-
-    Returns:
-      A dict containing the name, value, and range values.
-    """
-    return {'name': self._name,
-            'value': self._value,
-            'range': {'start': self._start,
-                      'end': self._end}}
-
-
-class Annotations(object, UserDict.DictMixin):
-  """A dictionary-like object containing the annotations, keyed by name."""
-
-  def __init__(self, operation_queue, blip):
-    self._operation_queue = operation_queue
-    self._blip = blip
-    self._store = {}
-
-  def __contains__(self, what):
-    if isinstance(what, Annotation):
-      what = what.name
-    return what in self._store
-
-  def _add_internal(self, name, value, start, end):
-    """Internal add annotation does not send out operations."""
-    if name in self._store:
-      # TODO: use bisect to make this more efficient.
-      new_list = []
-      for existing in self._store[name]:
-        if start > existing.end or end < existing.start:
-          new_list.append(existing)
-        else:
-          if existing.value == value:
-            # merge the annotations:
-            start = min(existing.start, start)
-            end = max(existing.end, end)
-          else:
-            # chop the bits off the existing annotation
-            if existing.start < start:
-              new_list.append(Annotation(
-                  existing.name, existing.value, existing.start, start))
-            if existing.end > end:
-              new_list.append(Annotation(
-                  existing.name, existing.value, existing.end, end))
-      new_list.append(Annotation(name, value, start, end))
-      self._store[name] = new_list
-    else:
-      self._store[name] = [Annotation(name, value, start, end)]
-
-  def _delete_internal(self, name, start=0, end=-1):
-    """Remove the passed annotaion from the internal representation."""
-    if not name in self._store:
-      return
-    if end < 0:
-      end = len(self._blip) + end
-
-    new_list = []
-    for a in self._store[name]:
-      if start > a.end or end < a.start:
-        new_list.append(a)
-      elif start < a.start and end > a.end:
-        continue
-      else:
-        if a.start < start:
-          new_list.append(Annotation(name, a.value, a.start, start))
-        if a.end > end:
-          new_list.append(Annotation(name, a.value, end, a.end))
-    if new_list:
-      self._store[name] = new_list
-    else:
-      del self._store[name]
-
-  def _shift(self, where, inc):
-    """Shift annotation by 'inc' if it (partly) overlaps with 'where'."""
-    for annotations in self._store.values():
-      for annotation in annotations:
-        annotation._shift(where, inc)
-
-    # Merge fragmented annotations that should be contiguous, for example:
-    # Annotation('foo', 'bar', 1, 2) and Annotation('foo', 'bar', 2, 3).
-    for name, annotations in self._store.items():
-      new_list = []
-      for i, annotation in enumerate(annotations):
-        name = annotation.name
-        value = annotation.value
-        start = annotation.start
-        end = annotation.end
-
-        # Find the last end index.
-        for j, next_annotation in enumerate(annotations[i + 1:]):
-          # Not contiguous, skip.
-          if (end < next_annotation.start):
-            break
-
-          # Contiguous, merge.
-          if (end == next_annotation.start and value == next_annotation.value):
-            end = next_annotation.end
-            del annotations[j]
-        new_list.append(Annotation(name, value, start, end))
-      self._store[name] = new_list
-
-  def __len__(self):
-    return len(self._store)
-
-  def __getitem__(self, key):
-    return self._store[key]
-
-  def __iter__(self):
-    for l in self._store.values():
-      for ann in l:
-        yield ann
-
-  def names(self):
-    """Return the names of the annotations in the store."""
-    return self._store.keys()
-
-  def serialize(self):
-    """Return a list of the serialized annotations."""
-    res = []
-    for v in self._store.values():
-      res += [a.serialize() for a in v]
-    return res
-
-
-class Blips(object, UserDict.DictMixin):
-  """A dictionary-like object containing the blips, keyed on blip ID."""
-
-  def __init__(self, blips):
-    self._blips = blips
-
-  def __contains__(self, blip_id):
-    return blip_id in self._blips
-
-  def __getitem__(self, blip_id):
-    return self._blips[blip_id]
-
-  def __iter__(self):
-    return self._blips.__iter__()
-
-  def __len__(self):
-    return len(self._blips)
-
-  def _add(self, ablip):
-    self._blips[ablip.blip_id] = ablip
-
-  def _remove_with_id(self, blip_id):
-    del_blip = self._blips[blip_id]
-    if del_blip:
-      # Remove the reference to this blip from its parent.
-      parent_blip = self._blips[blip_id].parent_blip
-      if parent_blip:
-        parent_blip._child_blip_ids.remove(blip_id)
-    del self._blips[blip_id]
-
-  def get(self, blip_id, default_value=None):
-    """Retrieves a blip.
-
-    Returns:
-      A Blip object. If none found for the ID, it returns None,
-      or if default_value is specified, it returns that.
-    """
-    return self._blips.get(blip_id, default_value)
-
-  def serialize(self):
-    """Serializes the blips.
-    Returns:
-      A dict of serialized blips.
-    """
-    res = {}
-    for blip_id, item in self._blips.items():
-      res[blip_id] = item.serialize()
-    return res
-
-  def values(self):
-    """Return the blips themselves."""
-    return self._blips.values()
-
-
-class BlipRefs(object):
-  """Represents a set of references to contents in a blip.
-
-  For example, a BlipRefs instance can represent the results
-  of a search, an explicitly set range, a regular expression,
-  or refer to the entire blip. BlipRefs are used to express
-  operations on a blip in a consistent way that can easily
-  be transfered to the server.
-
-  The typical way of creating a BlipRefs object is to use
-  selector methods on the Blip object. Developers will not
-  usually instantiate a BlipRefs object directly.
-  """
-
-  DELETE = 'DELETE'
-  REPLACE = 'REPLACE'
-  INSERT = 'INSERT'
-  INSERT_AFTER = 'INSERT_AFTER'
-  ANNOTATE = 'ANNOTATE'
-  CLEAR_ANNOTATION = 'CLEAR_ANNOTATION'
-  UPDATE_ELEMENT = 'UPDATE_ELEMENT'
-
-  def __init__(self, blip, maxres=1):
-    self._blip = blip
-    self._maxres = maxres
-
-  @classmethod
-  def all(cls, blip, findwhat, maxres=-1, **restrictions):
-    """Construct an instance representing the search for text or elements."""
-    obj = cls(blip, maxres)
-    obj._findwhat = findwhat
-    obj._restrictions = restrictions
-    obj._hits = lambda: obj._find(findwhat, maxres, **restrictions)
-    if findwhat is None:
-      # No findWhat, take the entire blip
-      obj._params = {}
-    else:
-      query = {'maxRes': maxres}
-      if isinstance(findwhat, basestring):
-        query['textMatch'] = findwhat
-      else:
-        query['elementMatch'] = findwhat.class_type
-        query['restrictions'] = restrictions
-      obj._params = {'modifyQuery': query}
-    return obj
-
-  @classmethod
-  def range(cls, blip, begin, end):
-    """Constructs an instance representing an explicitly set range."""
-    obj = cls(blip)
-    obj._begin = begin
-    obj._end = end
-    obj._hits = lambda: [(begin, end)]
-    obj._params = {'range': {'start': begin, 'end': end}}
-    return obj
-
-  def _elem_matches(self, elem, clz, **restrictions):
-    if not isinstance(elem, clz):
-      return False
-    for key, val in restrictions.items():
-      if getattr(elem, key) != val:
-        return False
-    return True
-
-  def _find(self, what, maxres=-1, **restrictions):
-    """Iterates where 'what' occurs in the associated blip.
-
-    What can be either a string or a class reference.
-    Examples:
-        self._find('hello') will return the first occurence of the word hello
-        self._find(element.Gadget, url='http://example.com/gadget.xml')
-            will return the first gadget that has as url example.com.
-
-    Args:
-      what: what to search for. Can be a class or a string. The class
-          should be an element from element.py
-      maxres: number of results to return at most, or <= 0 for all.
-      restrictions: if what specifies a class, further restrictions
-         of the found instances.
-    Yields:
-      Tuples indicating the range of the matches. For a one
-      character/element match at position x, (x, x+1) is yielded.
-    """
-    blip = self._blip
-    if what is None:
-      yield 0, len(blip)
-      raise StopIteration
-    if isinstance(what, basestring):
-      idx = blip._content.find(what)
-      count = 0
-      while idx != -1:
-        yield idx, idx + len(what)
-        count += 1
-        if count == maxres:
-          raise StopIteration
-        idx = blip._content.find(what, idx + len(what))
-    else:
-      count = 0
-      for idx, el in blip._elements.items():
-        if self._elem_matches(el, what, **restrictions):
-          yield idx, idx + 1
-          count += 1
-          if count == maxres:
-            raise StopIteration
-
-  def _execute(self, modify_how, what, bundled_annotations=None):
-    """Executes this BlipRefs object.
-
-    Args:
-      modify_how: What to do. Any of the operation declared at the top.
-      what: Depending on the operation. For delete, has to be None.
-            For the others it is a singleton, a list or a function returning
-            what to do; for ANNOTATE tuples of (key, value), for the others
-            either string or elements.
-            If what is a function, it takes three parameters, the content of
-            the blip, the beginning of the matching range and the end.
-      bundled_annotations: Annotations to apply immediately.
-    Raises:
-      IndexError when trying to access content outside of the blip.
-      ValueError when called with the wrong values.
-    Returns:
-      self for chainability.
-    """
-    blip = self._blip
-
-    if modify_how != BlipRefs.DELETE:
-      if not isinstance(what, list):
-        what = [what]
-      next_index = 0
-
-    matched = []
-    # updated_elements is used to store the element type of the
-    # element to update
-    updated_elements = []
-    
-    # For now, if we find one markup, we'll use it everywhere.
-    next = None
-    hit_found = False
-
-    for start, end in self._hits():
-      hit_found = True
-      if start < 0:
-        start += len(blip)
-        if end == 0:
-          end += len(blip)
-      if end < 0:
-        end += len(blip)
-      if len(blip) == 0:
-        if start != 0 or end != 0:
-          raise IndexError('Start and end have to be 0 for empty document')
-      elif start < 0 or end < 1 or start >= len(blip) or end > len(blip):
-        raise IndexError('Position outside the document')
-      if modify_how == BlipRefs.DELETE:
-        for i in range(start, end):
-          if i in blip._elements:
-            del blip._elements[i]
-        blip._delete_annotations(start, end)
-        blip._shift(end, start - end)
-        blip._content = blip._content[:start] + blip._content[end:]
-      else:
-        if callable(what):
-          next = what(blip._content, start, end)
-          matched.append(next)
-        else:
-          next = what[next_index]
-          next_index = (next_index + 1) % len(what)
-        if isinstance(next, str):
-          next = util.force_unicode(next)
-        if modify_how == BlipRefs.ANNOTATE:
-          key, value = next
-          blip.annotations._add_internal(key, value, start, end)
-        elif modify_how == BlipRefs.CLEAR_ANNOTATION:
-          blip.annotations._delete_internal(next, start, end)
-        elif modify_how == BlipRefs.UPDATE_ELEMENT:
-          el = blip._elements.get(start)
-          if not el:
-            raise ValueError('No element found at index %s' % start)
-          # the passing around of types this way feels a bit dirty:
-          updated_elements.append(element.Element.from_json({'type': el.type,
-              'properties': next}))
-          for k, b in next.items():
-            setattr(el, k, b)
-        else:
-          if modify_how == BlipRefs.INSERT:
-            end = start
-          elif modify_how == BlipRefs.INSERT_AFTER:
-            start = end
-          elif modify_how == BlipRefs.REPLACE:
-            pass
-          else:
-            raise ValueError('Unexpected modify_how: ' + modify_how)
-
-          if isinstance(next, element.Element):
-            text = ' '
-          else:
-            text = next
-
-          # in the case of a replace, and the replacement text is shorter,
-          # delete the delta.
-          if start != end and len(text) < end - start:
-            blip._delete_annotations(start + len(text), end)
-
-          blip._shift(end, len(text) + start - end)
-          blip._content = blip._content[:start] + text + blip._content[end:]
-          if bundled_annotations:
-            end_annotation = start + len(text)
-            blip._delete_annotations(start, end_annotation)
-            for key, value in bundled_annotations:
-              blip.annotations._add_internal(key, value, start, end_annotation)
-
-          if isinstance(next, element.Element):
-            blip._elements[start] = next
-
-    # No match found, return immediately without generating op.
-    if not hit_found:
-      return
-
-    operation = blip._operation_queue.document_modify(blip.wave_id,
-                                                      blip.wavelet_id,
-                                                      blip.blip_id)
-    for param, value in self._params.items():
-      operation.set_param(param, value)
-
-    modify_action = {'modifyHow': modify_how}
-    if modify_how == BlipRefs.DELETE:
-      pass
-    elif modify_how == BlipRefs.UPDATE_ELEMENT:
-      modify_action['elements'] = updated_elements
-    elif (modify_how == BlipRefs.REPLACE or
-          modify_how == BlipRefs.INSERT or
-          modify_how == BlipRefs.INSERT_AFTER):
-      if callable(what):
-        what = matched
-      if what:
-        if not isinstance(next, element.Element):
-          modify_action['values'] = [util.force_unicode(value) for value in 
what]
-        else:
-          modify_action['elements'] = what
-    elif modify_how == BlipRefs.ANNOTATE:
-      modify_action['values'] = [x[1] for x in what]
-      modify_action['annotationKey'] = what[0][0]
-    elif modify_how == BlipRefs.CLEAR_ANNOTATION:
-      modify_action['annotationKey'] = what[0]
-    if bundled_annotations:
-      modify_action['bundledAnnotations'] = [
-          {'key': key, 'value': value} for key, value in bundled_annotations]
-    operation.set_param('modifyAction', modify_action)
-
-    return self
-
-  def insert(self, what, bundled_annotations=None):
-    """Inserts what at the matched positions."""
-    return self._execute(
-        BlipRefs.INSERT, what, bundled_annotations=bundled_annotations)
-
-  def insert_after(self, what, bundled_annotations=None):
-    """Inserts what just after the matched positions."""
-    return self._execute(
-        BlipRefs.INSERT_AFTER, what, bundled_annotations=bundled_annotations)
-
-  def replace(self, what, bundled_annotations=None):
-    """Replaces the matched positions with what."""
-    return self._execute(
-        BlipRefs.REPLACE, what, bundled_annotations=bundled_annotations)
-
-  def delete(self):
-    """Deletes the content at the matched positions."""
-    return self._execute(BlipRefs.DELETE, None)
-
-  def annotate(self, name, value=None):
-    """Annotates the content at the matched positions.
-
-    You can either specify both name and value to set the
-    same annotation, or supply as the first parameter something
-    that yields name/value pairs. The name and value should both be strings.
-    """
-    if value is None:
-      what = name
-    else:
-      what = (name, value)
-    return self._execute(BlipRefs.ANNOTATE, what)
-
-  def clear_annotation(self, name):
-    """Clears the annotation at the matched positions."""
-    return self._execute(BlipRefs.CLEAR_ANNOTATION, name)
-
-  def update_element(self, new_values):
-    """Update an existing element with a set of new values.
-
-    For example, this code would update a button value:
-    button.update_element({'value': 'Yes'})
-    This code would update the 'seen' key in a gadget's state:
-    gadget.update_element({'seen': 'yes'})
-
-    Args:
-      new_values: A dictionary of property names and values.
-    """
-    return self._execute(BlipRefs.UPDATE_ELEMENT, new_values)
-
-  def __nonzero__(self):
-    """Return whether we have a value."""
-    for start, end in self._hits():
-      return True
-    return False
-
-  def value(self):
-    """Convenience method to convert a BlipRefs to value of its first match."""
-    for start, end in self._hits():
-      if end - start == 1 and start in self._blip._elements:
-        return self._blip._elements[start]
-      else:
-        return self._blip.text[start:end]
-    raise ValueError('BlipRefs has no values')
-
-  def __getattr__(self, attribute):
-    """Mirror the getattr of value().
-
-    This allows for clever things like
-    first(IMAGE).url
-
-    or
-
-    blip.annotate_with(key, value).upper()
-    """
-    return getattr(self.value(), attribute)
-
-  def __radd__(self, other):
-    """Make it possible to add this to a string."""
-    return other + self.value()
-
-  def __cmp__(self, other):
-    """Support comparision with target."""
-    return cmp(self.value(), other)
-
-  def __iter__(self):
-    for start_end in self._hits():
-      yield start_end
-
-
-class Blip(object):
-  """Models a single blip instance.
-
-  Blips are essentially the documents that make up a conversation. Blips can
-  live in a hierarchy of blips. A root blip has no parent blip id, but all
-  blips have the ids of the wave and wavelet that they are associated with.
-
-  Blips also contain annotations, content and elements, which are accessed via
-  the Document object.
-  """ 
-
-  def __init__(self, json, other_blips, operation_queue, thread=None,
-               reply_threads=None):
-    """Inits this blip with JSON data.
-
-    Args:
-      json: JSON data dictionary from Wave server.
-      other_blips: A dictionary like object that can be used to resolve
-        ids of blips to blips.
-      thread: The BlipThread object that this blip belongs to.
-      reply_threads: A list BlipThread objects that are replies to this blip.
-      operation_queue: An OperationQueue object to store generated operations
-        in.
-    """
-    self._blip_id = json.get('blipId')
-    self._reply_threads = reply_threads or []
-    self._thread = thread
-    self._operation_queue = operation_queue
-    self._child_blip_ids = list(json.get('childBlipIds', []))
-    self._content = json.get('content', '')
-    self._contributors = set(json.get('contributors', []))
-    self._creator = json.get('creator')
-    self._last_modified_time = json.get('lastModifiedTime', 0)
-    self._version = json.get('version', 0)
-    self._parent_blip_id = json.get('parentBlipId')
-    self._wave_id = json.get('waveId')
-    self._wavelet_id = json.get('waveletId')
-    if isinstance(other_blips, Blips):
-      self._other_blips = other_blips
-    else:
-      self._other_blips = Blips(other_blips)
-    self._annotations = Annotations(operation_queue, self)
-    for annjson in json.get('annotations', []):
-      r = annjson['range']
-      self._annotations._add_internal(annjson['name'],
-                                      annjson['value'],
-                                      r['start'],
-                                      r['end'])
-    self._elements = {}
-    json_elements = json.get('elements', {})
-    for elem in json_elements:
-      self._elements[int(elem)] = 
element.Element.from_json(json_elements[elem])
-    self.raw_data = json
-
-  @property
-  def blip_id(self):
-    """The id of this blip."""
-    return self._blip_id
-
-  @property
-  def wave_id(self):
-    """The id of the wave that this blip belongs to."""
-    return self._wave_id
-
-  @property
-  def wavelet_id(self):
-    """The id of the wavelet that this blip belongs to."""
-    return self._wavelet_id
-
-  @property
-  def child_blip_ids(self):
-    """The list of the ids of this blip's children."""
-    return self._child_blip_ids
-
-  @property
-  def child_blips(self):
-    """The list of blips that are children of this blip."""
-    return [self._other_blips[blid_id] for blid_id in self._child_blip_ids
-                if blid_id in self._other_blips]
-
-  @property
-  def thread(self):
-    """The thread that this blip belongs to."""
-    return self._thread
-
-  @property
-  def reply_threads(self):
-    """The list of threads that are replies to this blip."""
-    return self._reply_threads
-
-  @property
-  def inline_reply_threads(self):
-    # TODO: Consider moving to constructor
-    inline_reply_threads = []
-    for reply_thread in self._reply_threads:
-      if reply_thread.location > -1:
-        inline_reply_threads.append(reply_thread)
-    return inline_reply_threads
-
-  @property
-  def contributors(self):
-    """The set of participant ids that contributed to this blip."""
-    return self._contributors
-
-  @property
-  def creator(self):
-    """The id of the participant that created this blip."""
-    return self._creator
-
-  @property
-  def last_modified_time(self):
-    """The time in seconds since epoch when this blip was last modified."""
-    return self._last_modified_time
-
-  @property
-  def version(self):
-    """The version of this blip."""
-    return self._version
-
-  @property
-  def parent_blip_id(self):
-    """The parent blip_id or None if this is the root blip."""
-    return self._parent_blip_id
-
-  @property
-  def parent_blip(self):
-    """The parent blip or None if it is the root."""
-    # if parent_blip_id is None, get will also return None
-    return self._other_blips.get(self._parent_blip_id)
-
-  @property
-  def inline_blip_offset(self):
-    """The offset in the parent if this blip is inline or -1 if not.
-
-    If the parent is not in the context, this function will always
-    return -1 since it can't determine the inline blip status.
-    """
-    parent = self.parent_blip
-    if not parent:
-      return -1
-    for offset, el in parent._elements.items():
-      if el.type == element.Element.INLINE_BLIP_TYPE and el.id == self.blip_id:
-        return offset
-    return -1
-
-  def is_root(self):
-    """Returns whether this is the root blip of a wavelet."""
-    return self._parent_blip_id is None
-
-  @property
-  def annotations(self):
-    """The annotations for this document."""
-    return self._annotations
-
-  @property
-  def elements(self):
-    """Returns a list of elements for this document.
-    The elements of a blip are things like forms elements and gadgets
-    that cannot be expressed as plain text. In the text of the blip, you'll
-    typically find a space as a place holder for the element.
-    If you want to retrieve the element at a particular index in the blip, use
-    blip[index].value().
-    """
-    return self._elements.values()
-
-  def __len__(self):
-    return len(self._content)
-
-  def __getitem__(self, item):
-    """returns a BlipRefs for the given slice."""
-    if isinstance(item, slice):
-      if item.step:
-        raise errors.Error('Step not supported for blip slices')
-      return self.range(item.start, item.stop)
-    else:
-      return self.at(item)
-
-  def __setitem__(self, item, value):
-    """short cut for self.range/at().replace(value)."""
-    self.__getitem__(item).replace(value)
-
-  def __delitem__(self, item):
-    """short cut for self.range/at().delete()."""
-    self.__getitem__(item).delete()
-
-  def _shift(self, where, inc):
-    """Move element and annotations after 'where' up by 'inc'."""
-    new_elements = {}
-    for idx, el in self._elements.items():
-      if idx >= where:
-        idx += inc
-      new_elements[idx] = el
-    self._elements = new_elements
-    self._annotations._shift(where, inc)
-    
-  def _delete_annotations(self, start, end):
-    """Delete all annotations between 'start' and 'end'."""
-    for annotation_name in self._annotations.names():
-      self._annotations._delete_internal(annotation_name, start, end)
-
-  def all(self, findwhat=None, maxres=-1, **restrictions):
-    """Returns a BlipRefs object representing all results for the search.
-    If searching for an element, the restrictions can be used to specify
-    additional element properties to filter on, like the url of a Gadget.
-    """
-    return BlipRefs.all(self, findwhat, maxres, **restrictions)
-
-  def first(self, findwhat=None, **restrictions):
-    """Returns a BlipRefs object representing the first result for the search.
-    If searching for an element, the restrictions can be used to specify
-    additional element properties to filter on, like the url of a Gadget.
-    """
-    return BlipRefs.all(self, findwhat, 1, **restrictions)
-
-  def at(self, index):
-    """Returns a BlipRefs object representing a 1-character range."""
-    return BlipRefs.range(self, index, index + 1)
-
-  def range(self, start, end):
-    """Returns a BlipRefs object representing the range."""
-    return BlipRefs.range(self, start, end)
-
-  def serialize(self):
-    """Return a dictionary representation of this blip ready for json."""
-    return {'blipId': self._blip_id,
-            'childBlipIds': list(self._child_blip_ids),
-            'content': self._content,
-            'creator': self._creator,
-            'contributors': list(self._contributors),
-            'lastModifiedTime': self._last_modified_time,
-            'version': self._version,
-            'parentBlipId': self._parent_blip_id,
-            'waveId': self._wave_id,
-            'waveletId': self._wavelet_id,
-            'annotations': self._annotations.serialize(),
-            'elements': dict([(index, e.serialize())
-                              for index, e in self._elements.items()])
-           }
-
-  def proxy_for(self, proxy_for_id):
-    """Return a view on this blip that will proxy for the specified id.
-
-    A shallow copy of the current blip is returned with the proxy_for_id
-    set. Any modifications made to this copy will be done using the
-    proxy_for_id, i.e. the robot+<proxy_for_id>@appspot.com address will
-    be used.
-    """
-    util.check_is_valid_proxy_for_id(proxy_for_id)
-    operation_queue = self._operation_queue.proxy_for(proxy_for_id)
-    res = Blip(json={},
-               other_blips={},
-               operation_queue=operation_queue)
-    res._blip_id = self._blip_id
-    res._child_blip_ids = self._child_blip_ids
-    res._content = self._content
-    res._contributors = self._contributors
-    res._creator = self._creator
-    res._last_modified_time = self._last_modified_time
-    res._version = self._version
-    res._parent_blip_id = self._parent_blip_id
-    res._wave_id = self._wave_id
-    res._wavelet_id = self._wavelet_id
-    res._other_blips = self._other_blips
-    res._annotations = self._annotations
-    res._elements = self._elements
-    res.raw_data = self.raw_data
-    return res
-
-  @property
-  def text(self):
-    """Returns the raw text content of this document."""
-    return self._content
-
-  def find(self, what, **restrictions):
-    """Iterate to matching bits of contents.
-
-    Yield either elements or pieces of text.
-    """
-    br = BlipRefs.all(self, what, **restrictions)
-    for start, end in br._hits():
-      if end - start == 1 and start in self._elements:
-        yield self._elements[start]
-      else:
-        yield self._content[start:end]
-    raise StopIteration
-
-  def append(self, what, bundled_annotations=None):
-    """Convenience method covering a common pattern."""
-    return BlipRefs.all(self, findwhat=None).insert_after(
-        what, bundled_annotations=bundled_annotations)
-
-  def continue_thread(self):
-    """Create and return a blip in the same thread as this blip."""
-    blip_data = self._operation_queue.blip_continue_thread(self.wave_id,
-                                                           self.wavelet_id,
-                                                           self.blip_id)
-    new_blip = Blip(blip_data, self._other_blips, self._operation_queue,
-                    thread=self._thread)
-    if self._thread:
-      self._thread._add_internal(new_blip)
-    self._other_blips._add(new_blip)
-    return new_blip
-
-  def reply(self):
-    """Create and return a reply to this blip."""
-    blip_data = self._operation_queue.blip_create_child(self.wave_id,
-                                                        self.wavelet_id,
-                                                        self.blip_id)
-    new_blip = Blip(blip_data, self._other_blips, self._operation_queue)
-    self._other_blips._add(new_blip)
-    return new_blip
-
-  def append_markup(self, markup):
-    """Interpret the markup text as xhtml and append the result to the doc.
-
-    Args:
-      markup: The markup'ed text to append.
-    """
-    markup = util.force_unicode(markup)
-    self._operation_queue.document_append_markup(self.wave_id,
-                                                 self.wavelet_id,
-                                                 self.blip_id,
-                                                 markup)
-    self._content += util.parse_markup(markup)
-
-  def insert_inline_blip(self, position):
-    """Inserts an inline blip into this blip at a specific position.
-
-    Args:
-      position: Position to insert the blip at. This has to be greater than 0.
-
-    Returns:
-      The JSON data of the blip that was created.
-    """
-    if position <= 0:
-      raise IndexError(('Illegal inline blip position: %d. Position has to ' +
-                        'be greater than 0.') % position)
-
-    blip_data = self._operation_queue.document_inline_blip_insert(
-        self.wave_id,
-        self.wavelet_id,
-        self.blip_id,
-        position)
-    new_blip = Blip(blip_data, self._other_blips, self._operation_queue)
-    self._other_blips._add(new_blip)
-    return new_blip

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/78cbf78f/wave/src/main/java/python/api/blip_test.py
----------------------------------------------------------------------
diff --git a/wave/src/main/java/python/api/blip_test.py 
b/wave/src/main/java/python/api/blip_test.py
deleted file mode 100644
index 7cd66e0..0000000
--- a/wave/src/main/java/python/api/blip_test.py
+++ /dev/null
@@ -1,383 +0,0 @@
-#!/usr/bin/python2.4
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-"""Unit tests for the blip module."""
-
-
-import unittest
-
-import blip
-import element
-import ops
-import simplejson
-
-TEST_BLIP_DATA = {
-    'childBlipIds': [],
-    'content': '\nhello world!\nanother line',
-    'contributors': ['[email protected]', '[email protected]'],
-    'creator': '[email protected]',
-    'lastModifiedTime': 1000,
-    'parentBlipId': None,
-    'annotations': [{'range': {'start': 2, 'end': 3},
-                     'name': 'key', 'value': 'val'}],
-    'waveId': 'test.com!w+g3h3im',
-    'waveletId': 'test.com!root+conv',
-    'elements':{'14':{'type':'GADGET','properties':{'url':'http://a/b.xml'}}},
-}
-
-CHILD_BLIP_ID = 'b+42'
-ROOT_BLIP_ID = 'b+43'
-
-
-class TestBlip(unittest.TestCase):
-  """Tests the primary data structures for the wave model."""
-
-  def assertBlipStartswith(self, expected, totest):
-    actual = totest.text[:len(expected)]
-    self.assertEquals(expected, actual)
-
-  def new_blip(self, **args):
-    """Create a blip for testing."""
-    data = TEST_BLIP_DATA.copy()
-    data.update(args)
-    res = blip.Blip(data, self.all_blips, self.operation_queue)
-    self.all_blips[res.blip_id] = res
-    return res
-
-  def setUp(self):
-    self.all_blips = {}
-    self.operation_queue = ops.OperationQueue()
-
-  def testBlipProperties(self):
-    root = self.new_blip(blipId=ROOT_BLIP_ID,
-                         childBlipIds=[CHILD_BLIP_ID])
-    child = self.new_blip(blipId=CHILD_BLIP_ID,
-                          parentBlipId=ROOT_BLIP_ID)
-    self.assertEquals(ROOT_BLIP_ID, root.blip_id)
-    self.assertEquals([CHILD_BLIP_ID], root.child_blip_ids)
-    self.assertEquals(set(TEST_BLIP_DATA['contributors']), root.contributors)
-    self.assertEquals(TEST_BLIP_DATA['creator'], root.creator)
-    self.assertEquals(TEST_BLIP_DATA['content'], root.text)
-    self.assertEquals(TEST_BLIP_DATA['lastModifiedTime'],
-                      root.last_modified_time)
-    self.assertEquals(TEST_BLIP_DATA['parentBlipId'], root.parent_blip_id)
-    self.assertEquals(TEST_BLIP_DATA['waveId'], root.wave_id)
-    self.assertEquals(TEST_BLIP_DATA['waveletId'], root.wavelet_id)
-    self.assertEquals(TEST_BLIP_DATA['content'][3], root[3])
-    self.assertEquals(element.Gadget.class_type, root[14].type)
-    self.assertEquals('http://a/b.xml', root[14].url)
-    self.assertEquals('a', root.text[14])
-    self.assertEquals(len(TEST_BLIP_DATA['content']), len(root))
-    self.assertTrue(root.is_root())
-    self.assertFalse(child.is_root())
-    self.assertEquals(root, child.parent_blip)
-
-  def testBlipSerialize(self):
-    root = self.new_blip(blipId=ROOT_BLIP_ID,
-                         childBlipIds=[CHILD_BLIP_ID])
-    serialized = root.serialize()
-    unserialized = blip.Blip(serialized, self.all_blips, self.operation_queue)
-    self.assertEquals(root.blip_id, unserialized.blip_id)
-    self.assertEquals(root.child_blip_ids, unserialized.child_blip_ids)
-    self.assertEquals(root.contributors, unserialized.contributors)
-    self.assertEquals(root.creator, unserialized.creator)
-    self.assertEquals(root.text, unserialized.text)
-    self.assertEquals(root.last_modified_time, unserialized.last_modified_time)
-    self.assertEquals(root.parent_blip_id, unserialized.parent_blip_id)
-    self.assertEquals(root.wave_id, unserialized.wave_id)
-    self.assertEquals(root.wavelet_id, unserialized.wavelet_id)
-    self.assertTrue(unserialized.is_root())
-
-  def testDocumentOperations(self):
-    blip = self.new_blip(blipId=ROOT_BLIP_ID)
-    newlines = [x for x in blip.find('\n')]
-    self.assertEquals(2, len(newlines))
-    blip.first('world').replace('jupiter')
-    bits = blip.text.split('\n')
-    self.assertEquals(3, len(bits))
-    self.assertEquals('hello jupiter!', bits[1])
-    blip.range(2, 5).delete()
-    self.assertBlipStartswith('\nho jupiter', blip)
-
-    blip.first('ho').insert_after('la')
-    self.assertBlipStartswith('\nhola jupiter', blip)
-    blip.at(3).insert(' ')
-    self.assertBlipStartswith('\nho la jupiter', blip)
-
-  def testElementHandling(self):
-    blip = self.new_blip(blipId=ROOT_BLIP_ID)
-    url = 'http://www.test.com/image.png'
-
-    org_len = len(blip)
-    blip.append(element.Image(url=url))
-
-    elems = [elem for elem in blip.find(element.Image, url=url)]
-    self.assertEquals(1, len(elems))
-    elem = elems[0]
-    self.assertTrue(isinstance(elem, element.Image))
-    blip.at(1).insert('twelve chars')
-    self.assertTrue(blip.text.startswith('\ntwelve charshello'))
-
-    elem = blip[org_len + 12].value()
-    self.assertTrue(isinstance(elem, element.Image))
-
-    blip.first('twelve ').delete()
-    self.assertTrue(blip.text.startswith('\nchars'))
-
-    elem = blip[org_len + 12 - len('twelve ')].value()
-    self.assertTrue(isinstance(elem, element.Image))
-
-    blip.first('chars').replace(element.Image(url=url))
-    elems = [elem for elem in blip.find(element.Image, url=url)]
-    self.assertEquals(2, len(elems))
-    self.assertTrue(blip.text.startswith('\n hello'))
-    elem = blip[1].value()
-    self.assertTrue(isinstance(elem, element.Image))
-
-  def testAnnotationHandling(self):
-    key = 'style/fontWeight'
-
-    def get_bold():
-      for an in blip.annotations[key]:
-        if an.value == 'bold':
-          return an
-      return None
-
-    json = ('[{"range":{"start":3,"end":6},"name":"%s","value":"bold"}]'
-            % key)
-    blip = self.new_blip(blipId=ROOT_BLIP_ID,
-                         annotations=simplejson.loads(json))
-    self.assertEquals(1, len(blip.annotations))
-    self.assertNotEqual(None, get_bold().value)
-    self.assertTrue(key in blip.annotations)
-
-    # extend the bold annotation by adding:
-    blip.range(5, 8).annotate(key, 'bold')
-    self.assertEquals(1, len(blip.annotations))
-    self.assertEquals(8, get_bold().end)
-
-    # clip by adding a same keyed:
-    blip[4:12].annotate(key, 'italic')
-    self.assertEquals(2, len(blip.annotations[key]))
-    self.assertEquals(4, get_bold().end)
-
-    # now split the italic one:
-    blip.range(6, 7).clear_annotation(key)
-    self.assertEquals(3, len(blip.annotations[key]))
-
-    # test names and iteration
-    self.assertEquals(1, len(blip.annotations.names()))
-    self.assertEquals(3, len([x for x in blip.annotations]))
-    blip[3: 5].annotate('foo', 'bar')
-    self.assertEquals(2, len(blip.annotations.names()))
-    self.assertEquals(4, len([x for x in blip.annotations]))
-    blip[3: 5].clear_annotation('foo')
-
-    # clear the whole thing
-    blip.all().clear_annotation(key)
-    # getting to the key should now throw an exception
-    self.assertRaises(KeyError, blip.annotations.__getitem__, key)
-
-  def testBlipOperations(self):
-    blip = self.new_blip(blipId=ROOT_BLIP_ID)
-    self.assertEquals(1, len(self.all_blips))
-
-    otherblip = blip.reply()
-    otherblip.append('hello world')
-    self.assertEquals('hello world', otherblip.text)
-    self.assertEquals(blip.blip_id, otherblip.parent_blip_id)
-    self.assertEquals(2, len(self.all_blips))
-
-    another = blip.continue_thread()
-    another.append('hello world')
-    self.assertEquals('hello world', another.text)
-    self.assertEquals(blip.parent_blip_id, another.parent_blip_id)
-    self.assertEquals(3, len(self.all_blips))
-
-    inline = blip.insert_inline_blip(3)
-    self.assertEquals(blip.blip_id, inline.parent_blip_id)
-    self.assertEquals(4, len(self.all_blips))
-
-  def testInsertInlineBlipCantInsertAtTheBeginning(self):
-    blip = self.new_blip(blipId=ROOT_BLIP_ID)
-    self.assertEquals(1, len(self.all_blips))
-    self.assertRaises(IndexError, blip.insert_inline_blip, 0)
-    self.assertEquals(1, len(self.all_blips))
-
-  def testDocumentModify(self):
-    blip = self.new_blip(blipId=ROOT_BLIP_ID)
-    blip.all().replace('a text with text and then some text')
-    blip[7].insert('text ')
-    blip.all('text').replace('thing')
-    self.assertEquals('a thing thing with thing and then some thing',
-                      blip.text)
-
-  def testIteration(self):
-    blip = self.new_blip(blipId=ROOT_BLIP_ID)
-    blip.all().replace('aaa 012 aaa 345 aaa 322')
-    count = 0
-    prev = -1
-    for start, end in blip.all('aaa'):
-      count += 1
-      self.assertTrue(prev < start)
-      prev = start
-    self.assertEquals(3, count)
-
-
-  def testBlipRefValue(self):
-    blip = self.new_blip(blipId=ROOT_BLIP_ID)
-    content = blip.text
-    content = content[:4] + content[5:]
-    del blip[4]
-    self.assertEquals(content, blip.text)
-
-    content = content[:2] + content[3:]
-    del blip[2:3]
-    self.assertEquals(content, blip.text)
-
-    blip[2:3] = 'bike'
-    content = content[:2] + 'bike' + content[3:]
-    self.assertEquals(content, blip.text)
-
-    url = 'http://www.test.com/image.png'
-    blip.append(element.Image(url=url))
-    self.assertEqual(url, blip.first(element.Image).url)
-
-    url2 = 'http://www.test.com/another.png'
-    blip[-1].update_element({'url': url2})
-    self.assertEqual(url2, blip.first(element.Image).url)
-
-    self.assertTrue(blip[3:5] == blip.text[3:5])
-
-    blip.append('geheim')
-    self.assertTrue(blip.first('geheim'))
-    self.assertFalse(blip.first(element.Button))
-    blip.append(element.Button(name='test1', value='Click'))
-    button = blip.first(element.Button)
-    button.update_element({'name': 'test2'})
-    self.assertEqual('test2', button.name)
-
-  def testReplace(self):
-    blip = self.new_blip(blipId=ROOT_BLIP_ID)
-    blip.all().replace('\nxxxx')
-    blip.all('yyy').replace('zzz')
-    self.assertEqual('\nxxxx', blip.text)
-
-  def testDeleteRangeThatSpansAcrossAnnotationEndPoint(self):
-    json = ('[{"range":{"start":1,"end":3},"name":"style","value":"bold"}]')
-    blip = self.new_blip(blipId=ROOT_BLIP_ID,
-                         annotations=simplejson.loads(json),
-                         content='\nFoo bar.')
-    blip.range(2, 4).delete()
-    self.assertEqual('\nF bar.', blip.text)
-    self.assertEqual(1, blip.annotations['style'][0].start)
-    self.assertEqual(2, blip.annotations['style'][0].end)
-
-  def testInsertBeforeAnnotationStartPoint(self):
-    json = ('[{"range":{"start":4,"end":9},"name":"style","value":"bold"}]')
-    blip = self.new_blip(blipId=ROOT_BLIP_ID,
-                         annotations=simplejson.loads(json),
-                         content='\nFoo bar.')
-    blip.at(4).insert('d and')
-    self.assertEqual('\nFood and bar.', blip.text)
-    self.assertEqual(9, blip.annotations['style'][0].start)
-    self.assertEqual(14, blip.annotations['style'][0].end)
-
-  def testDeleteRangeInsideAnnotation(self):
-    json = ('[{"range":{"start":1,"end":5},"name":"style","value":"bold"}]')
-    blip = self.new_blip(blipId=ROOT_BLIP_ID,
-                         annotations=simplejson.loads(json),
-                         content='\nFoo bar.')
-    blip.range(2, 4).delete()
-
-    self.assertEqual('\nF bar.', blip.text)
-    self.assertEqual(1, blip.annotations['style'][0].start)
-    self.assertEqual(3, blip.annotations['style'][0].end)
-
-  def testReplaceInsideAnnotation(self):
-    json = ('[{"range":{"start":1,"end":5},"name":"style","value":"bold"}]')
-    blip = self.new_blip(blipId=ROOT_BLIP_ID,
-                         annotations=simplejson.loads(json),
-                         content='\nFoo bar.')
-    blip.range(2, 4).replace('ooo')
-    self.assertEqual('\nFooo bar.', blip.text)
-    self.assertEqual(1, blip.annotations['style'][0].start)
-    self.assertEqual(6, blip.annotations['style'][0].end)
-
-    blip.range(2, 5).replace('o')
-    self.assertEqual('\nFo bar.', blip.text)
-    self.assertEqual(1, blip.annotations['style'][0].start)
-    self.assertEqual(4, blip.annotations['style'][0].end)
-
-  def testReplaceSpanAnnotation(self):
-    json = ('[{"range":{"start":1,"end":4},"name":"style","value":"bold"}]')
-    blip = self.new_blip(blipId=ROOT_BLIP_ID,
-                         annotations=simplejson.loads(json),
-                         content='\nFoo bar.')
-    blip.range(2, 9).replace('')
-    self.assertEqual('\nF', blip.text)
-    self.assertEqual(1, blip.annotations['style'][0].start)
-    self.assertEqual(2, blip.annotations['style'][0].end)
-
-  def testSearchWithNoMatchShouldNotGenerateOperation(self):
-    blip = self.new_blip(blipId=ROOT_BLIP_ID)
-    self.assertEqual(-1, blip.text.find(':('))
-    self.assertEqual(0, len(self.operation_queue))
-    blip.all(':(').replace(':)')
-    self.assertEqual(0, len(self.operation_queue))
-
-  def testBlipsRemoveWithId(self):
-    blip_dict = {
-        ROOT_BLIP_ID: self.new_blip(blipId=ROOT_BLIP_ID,
-                                    childBlipIds=[CHILD_BLIP_ID]),
-        CHILD_BLIP_ID: self.new_blip(blipId=CHILD_BLIP_ID,
-                                     parentBlipId=ROOT_BLIP_ID)
-    }
-    blips = blip.Blips(blip_dict)
-    blips._remove_with_id(CHILD_BLIP_ID)
-    self.assertEqual(1, len(blips))
-    self.assertEqual(0, len(blips[ROOT_BLIP_ID].child_blip_ids))
-
-  def testAppendMarkup(self):
-    blip = self.new_blip(blipId=ROOT_BLIP_ID, content='\nFoo bar.')
-    markup = '<p><span>markup<span> content</p>'
-    blip.append_markup(markup)
-    self.assertEqual(1, len(self.operation_queue))
-    self.assertEqual('\nFoo bar.\nmarkup content', blip.text)
-
-  def testBundledAnnotations(self):
-    blip = self.new_blip(blipId=ROOT_BLIP_ID, content='\nFoo bar.')
-    blip.append('not bold')
-    blip.append('bold', bundled_annotations=[('style/fontWeight', 'bold')])
-    self.assertEqual(2, len(blip.annotations))
-    self.assertEqual('bold', blip.annotations['style/fontWeight'][0].value)
-
-  def testInlineBlipOffset(self):
-    offset = 14
-    self.new_blip(blipId=ROOT_BLIP_ID,
-                  childBlipIds=[CHILD_BLIP_ID],
-                  elements={str(offset):
-                      {'type': element.Element.INLINE_BLIP_TYPE,
-                       'properties': {'id': CHILD_BLIP_ID}}})
-    child = self.new_blip(blipId=CHILD_BLIP_ID,
-                          parentBlipId=ROOT_BLIP_ID)
-    self.assertEqual(offset, child.inline_blip_offset)
-
-if __name__ == '__main__':
-  unittest.main()

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/78cbf78f/wave/src/main/java/python/api/commandline_robot_runner.py
----------------------------------------------------------------------
diff --git a/wave/src/main/java/python/api/commandline_robot_runner.py 
b/wave/src/main/java/python/api/commandline_robot_runner.py
deleted file mode 100644
index 9cb3eab..0000000
--- a/wave/src/main/java/python/api/commandline_robot_runner.py
+++ /dev/null
@@ -1,84 +0,0 @@
-#!/usr/bin/python2.4
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-"""Run robot from the commandline for testing.
-
-This robot_runner let's you define event handlers using flags and takes the
-json input from the std in and writes out the json output to stdout.
-
-for example
-  cat events | commandline_robot_runner.py \
-      --eventdef-blip_submitted="wavelet.title='title'"
-"""
-
-__author__ = '[email protected] (Douwe Osinga)'
-
-import sys
-import urllib
-
-from google3.pyglib import app
-from google3.pyglib import flags
-
-from google3.walkabout.externalagents import api
-
-from google3.walkabout.externalagents.api import blip
-from google3.walkabout.externalagents.api import element
-from google3.walkabout.externalagents.api import errors
-from google3.walkabout.externalagents.api import events
-from google3.walkabout.externalagents.api import ops
-from google3.walkabout.externalagents.api import robot
-from google3.walkabout.externalagents.api import util
-
-FLAGS = flags.FLAGS
-
-for event in events.ALL:
-  flags.DEFINE_string('eventdef_' + event.type.lower(),
-                      '',
-                      'Event definition for the %s event' % event.type)
-
-
-def handle_event(src, bot, e, w):
-  """Handle an event by executing the source code src."""
-  globs = {'e': e, 'w': w, 'api': api, 'bot': bot,
-           'blip': blip, 'element': element, 'errors': errors,
-           'events': events, 'ops': ops, 'robot': robot,
-           'util': util}
-  exec src in globs
-
-
-def run_bot(input_file, output_file):
-  """Run a robot defined on the command line."""
-  cmdbot = robot.Robot('Commandline bot')
-  for event in events.ALL:
-    src = getattr(FLAGS, 'eventdef_' + event.type.lower())
-    src = urllib.unquote_plus(src)
-    if src:
-      cmdbot.register_handler(event,
-          lambda event, wavelet, src=src, bot=cmdbot:
-              handle_event(src, bot, event, wavelet))
-  json_body = unicode(input_file.read(), 'utf8')
-  json_response = cmdbot.process_events(json_body)
-  output_file.write(json_response)
-
-
-def main(argv):
-  run_bot(sys.stdin, sys.stdout)
-
-if __name__ == '__main__':
-  app.run()

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/78cbf78f/wave/src/main/java/python/api/commandline_robot_runner_test.py
----------------------------------------------------------------------
diff --git a/wave/src/main/java/python/api/commandline_robot_runner_test.py 
b/wave/src/main/java/python/api/commandline_robot_runner_test.py
deleted file mode 100644
index 3acbca5..0000000
--- a/wave/src/main/java/python/api/commandline_robot_runner_test.py
+++ /dev/null
@@ -1,93 +0,0 @@
-#!/usr/bin/python2.4
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-"""Tests for google3.walkabout.externalagents.api.commandline_robot_runner."""
-
-__author__ = '[email protected] (Douwe Osinga)'
-
-import StringIO
-
-from google3.pyglib import app
-from google3.pyglib import flags
-
-from google3.testing.pybase import googletest
-from google3.walkabout.externalagents.api import commandline_robot_runner
-from google3.walkabout.externalagents.api import events
-
-FLAGS = flags.FLAGS
-
-
-BLIP_JSON = ('{"wdykLROk*13":'
-             '{"lastModifiedTime":1242079608457,'
-             '"contributors":["[email protected]"],'
-             '"waveletId":"test.com!conv+root",'
-             '"waveId":"test.com!wdykLROk*11",'
-             '"parentBlipId":null,'
-             '"version":3,'
-             '"creator":"[email protected]",'
-             '"content":"\\nContent!",'
-             '"blipId":"wdykLROk*13",'
-             '"annotations":[{"range":{"start":0,"end":1},'
-             '"name":"user/e/[email protected]","value":"Other"}],'
-             '"elements":{},'
-             '"childBlipIds":[]}'
-             '}')
-
-WAVELET_JSON = ('{"lastModifiedTime":1242079611003,'
-                 '"title":"A title",'
-                 '"waveletId":"test.com!conv+root",'
-                 '"rootBlipId":"wdykLROk*13",'
-                 '"dataDocuments":null,'
-                 '"creationTime":1242079608457,'
-                 '"waveId":"test.com!wdykLROk*11",'
-                 '"participants":["[email protected]","[email protected]"],'
-                 '"creator":"[email protected]",'
-                 '"rootThread": '
-                 '{"id":"", "location": "-1", "blipIds": ["wdykLROk*13"]},'
-                 '"version":5}')
-
-EVENTS_JSON = ('[{"timestamp":1242079611003,'
-               '"modifiedBy":"[email protected]",'
-               '"properties":{"participantsRemoved":[],'
-               '"participantsAdded":["[email protected]"]},'
-               '"type":"WAVELET_PARTICIPANTS_CHANGED"}]')
-
-TEST_JSON = '{"blips":%s,"wavelet":%s,"events":%s}' % (
-    BLIP_JSON, WAVELET_JSON, EVENTS_JSON)
-
-
-class CommandlineRobotRunnerTest(googletest.TestCase):
-
-  def testSimpleFlow(self):
-    FLAGS.eventdef_wavelet_participants_changed = 'x'
-    flag = 'eventdef_' + events.WaveletParticipantsChanged.type.lower()
-    setattr(FLAGS, flag, 'w.title="New title!"')
-    input_stream = StringIO.StringIO(TEST_JSON)
-    output_stream = StringIO.StringIO()
-    commandline_robot_runner.run_bot(input_stream, output_stream)
-    res = output_stream.getvalue()
-    self.assertTrue('wavelet.setTitle' in res)
-
-
-def main(unused_argv):
-  googletest.main()
-
-
-if __name__ == '__main__':
-  app.run()

http://git-wip-us.apache.org/repos/asf/incubator-wave/blob/78cbf78f/wave/src/main/java/python/api/django_oauth.py
----------------------------------------------------------------------
diff --git a/wave/src/main/java/python/api/django_oauth.py 
b/wave/src/main/java/python/api/django_oauth.py
deleted file mode 100644
index 6fd8a3f..0000000
--- a/wave/src/main/java/python/api/django_oauth.py
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/usr/bin/python2.4
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-"""Filter and decorator to wave enable django sites.
-
-If you want to require wave authentication for every handler, just add
-WaveOAuthMiddleware to your middleware. If you only want to require
-authentication for specific handlers, decorate those with @waveoauth.
-
-In any wave authenticated handler the request object should have a
-waveservice field that can be used to talk to wave.
-
-You can specify the following in your settings:
-WAVE_CONSUMER_KEY: the consumer key passed to the waveservice. defaults to
-    anonymous if not set.
-WAVE_CONSUMER_SECRET: the consumer key passed to the waveservice. defaults to
-    anonymous if not set.
-WAVE_USE_SANDBOX: whether to use the sandbox for this app. Defaults to false.
-"""
-
-from django.conf import settings
-from django.http import HttpResponse, HttpResponseRedirect
-from django.contrib.auth import authenticate
-
-import base64
-import logging
-from functools import wraps
-
-import waveservice
-
-
-class WaveOAuthMiddleware(object):
-  """Wave middleware to authenticate all requests at this site."""
-  def process_request(self, request):
-    return _oauth_helper(request)
-
-
-def waveoauth(func):
-  """Decorator used to specify that a handler requires wave authentication."""
-  @wraps(func)
-  def inner(request, *args, **kwargs):
-    result = _oauth_helper(request)
-    if result is not None:
-      return result
-    return func(request, *args, **kwargs)
-  return inner
-
-
-def _oauth_helper(request):
-  "Check if we're authenticated and if not, execute the oauth dance."
-
-  consumer_key = getattr(settings, 'WAVE_CONSUMER_KEY', 'anonymous')
-  consumer_secret = getattr(settings, 'WAVE_CONSUMER_SECRET', 'anonymous')
-  use_sandbox = getattr(settings, 'WAVE_USE_SANDBOX', False)
-
-  service = waveservice.WaveService(
-      consumer_key=consumer_key, consumer_secret=consumer_secret, 
use_sandbox=use_sandbox)
-
-  access_token = request.COOKIES.get('WAVE_ACCESS_TOKEN')
-  if access_token:
-    service.set_access_token(access_token)
-    request.waveservice = service
-    return None
-
-  # no access token. dance monkey dance.
-  oauth_token = request.GET.get('oauth_token')
-  verifier = request.GET.get('oauth_verifier')
-  request_token = request.COOKIES.get('WAVE_REQUEST_TOKEN')
-  meta = request.META
-
-  # you'd think there would be something better than this madness:
-  this_url = meta.get('HTTP_HOST')
-  if not this_url:
-    this_url = meta.get('SERVER_NAME')
-    port = meta.get('SEVER_PORT')
-    if port:
-      this_url += ':' + port
-  this_url += request.path
-  schema = meta.get('wsgi.url_scheme', 'http')
-  this_url = schema + '://' + this_url
-
-  if not oauth_token or not verifier or not request_token:
-    # we're here not returning from a callback. Start.
-    request_token = service.fetch_request_token(callback=this_url)
-    auth_url = service.generate_authorization_url()
-    response = HttpResponseRedirect(auth_url)
-    # set a session cookie
-    response.set_cookie('WAVE_REQUEST_TOKEN', request_token.to_string())
-    return response
-  else:
-    logging.info('upgrading to access token')
-    access_token = service.upgrade_to_access_token(request_token=request_token,
-                                                   verifier=verifier)
-    # This redirect could be avoided if the caller would set the cookie. This 
way
-    # however we keep the cgi arguments clean.
-    response = HttpResponseRedirect(this_url)
-    response.set_cookie('WAVE_ACCESS_TOKEN', access_token.to_string(), 
max_age=24*3600*365)
-    return response

Reply via email to