<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -12,7 +12,7 @@ much about server administration.
 PREREQUISITES
 
 * Google App Engine
-* Flex Builder or Flex SDK
+* Flex Builder 3 or Flex SDK
 * Python 2.5
 
 INSTRUCTIONS</diff>
      <filename>README.txt</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,6 @@
 Features:
+* Support delete operation.
+* Make a better use of objects on the Flex side.
 * Integrate user authentication on the Flex client and the GAE server.
 * Use the RESTful convention.
 </diff>
      <filename>TODO.txt</filename>
    </modified>
    <modified>
      <diff></diff>
      <filename>flex-client/bin-debug/main.swf</filename>
    </modified>
    <modified>
      <diff>@@ -1,69 +1,85 @@
 &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
 &lt;mx:Application xmlns:mx=&quot;http://www.adobe.com/2006/mxml&quot; layout=&quot;absolute&quot; creationComplete=&quot;onInit()&quot;&gt;
     &lt;mx:Script&gt;
-   	&lt;![CDATA[
-		import flash.net.Responder;
-		import mx.controls.Alert;
+        &lt;![CDATA[
+        import flash.net.Responder;
+        import mx.controls.Alert;
+        import mx.utils.ObjectUtil;
 
-   		[Bindable]
-		public var dataProvider:Array;
+        [Bindable]
+        public var dataProvider:Array;
 
-		[Bindable]
-		public var statusMsg:String;
+        [Bindable]
+        public var statusMsg:String;
+        
+        [Bindable]
+        public var project:Object;
 
-		public var gateway:NetConnection;
-		
-		public function onInit():void
-   		{
-			statusMsg = &quot;Loading data...&quot;;
-   			gateway = new NetConnection();
-   			gateway.connect(&quot;http://localhost:8080/&quot;);
-			getProjects();
-  		}
-  		
-		public function getProjects():void {
-			gateway.call(&quot;ProjectService.get_all&quot;, new Responder(getResult, onFault));
-		}
+        public var gateway:NetConnection;
+        
+        public function onInit():void {
+            statusMsg = &quot;Loading data...&quot;;
+            gateway = new NetConnection();
+            gateway.connect(&quot;http://localhost:8080/&quot;);
+            getProjects();
+        }
+          
+        public function getProjects():void {
+            gateway.call(&quot;ProjectService.get_all&quot;, new Responder(getResult, onFault));
+        }
 
-		public function getResult(result:Array):void {
-			dataProvider = result;
-			statusMsg = &quot;Data loaded.&quot;;
-		}
+        public function getResult(result:Array):void {
+            dataProvider = result;
+            statusMsg = &quot;Data loaded.&quot;;
+        }
 
-		public function submitProject():void {
-			var newProject:Object = new Object();
-			newProject.code = project_code.text;
-			newProject.name = project_name.text;
-			gateway.call(&quot;ProjectService.insert&quot;, new Responder(null, onFault), newProject);
-			getProjects();
-		}
+        public function submitProject():void {
+        	var newProject:Object = new Object();
+        	newProject.code = project_code.text;
+        	newProject.name = project_name.text;
+        	newProject._key = project._key;
+            gateway.call(&quot;ProjectService.save&quot;, new Responder(null, onFault), newProject);
+            getProjects();
+        }
 
-		public function onFault(info:Object):void {
-			statusMsg = info.toString();
-		}
-   	]]&gt;
+        public function onFault(info:Object):void {
+            statusMsg = info.toString();
+        }
+        
+        public function ProjectGridChanged():void {
+        	project = ObjectUtil.copy(dgProjects.selectedItem);
+        }
+        
+        public function AddNewProjectClicked():void {
+        	project = new Object();
+        	project.code = null;
+        	project.name = null;
+        	project.created_at = null;
+        	project.modified_at = null;
+        	project._key = null;
+        	project_code.setFocus();
+        }
+        ]]&gt;
     &lt;/mx:Script&gt;
     
-	&lt;mx:DataGrid id=&quot;dgProjects&quot; x=&quot;10&quot; y=&quot;10&quot; dataProvider=&quot;{dataProvider}&quot; width=&quot;356&quot; height=&quot;183&quot;&gt;
-		&lt;mx:columns&gt;
-			&lt;mx:DataGridColumn headerText=&quot;Code&quot; dataField=&quot;code&quot;/&gt;
-			&lt;mx:DataGridColumn headerText=&quot;Name&quot; dataField=&quot;name&quot;/&gt;
-		&lt;/mx:columns&gt;
-	&lt;/mx:DataGrid&gt;
-	&lt;mx:Button x=&quot;374&quot; y=&quot;11&quot; label=&quot;Reload&quot; click=&quot;onInit()&quot;/&gt;
-	&lt;mx:Label x=&quot;10&quot; y=&quot;203&quot; text=&quot;Created at&quot;/&gt;
-	&lt;mx:TextInput x=&quot;103&quot; y=&quot;201&quot; id=&quot;selected_created_at&quot; text=&quot;{dgProjects.selectedItem.created_at}&quot; width=&quot;263&quot;/&gt;
-    &lt;mx:Form x=&quot;10&quot; y=&quot;240&quot; width=&quot;356&quot; borderStyle=&quot;solid&quot; cornerRadius=&quot;2&quot;&gt;
-      &lt;mx:FormHeading label=&quot;New Project&quot;/&gt;
-      &lt;mx:HBox&gt;
-         &lt;mx:Label text=&quot;Code&quot;/&gt;
-         &lt;mx:TextInput id=&quot;project_code&quot; width=&quot;159&quot;/&gt;
-      &lt;/mx:HBox&gt;
-      &lt;mx:HBox&gt;
-         &lt;mx:Label text=&quot;Name&quot;/&gt;
-         &lt;mx:TextInput id=&quot;project_name&quot;/&gt;
-      &lt;/mx:HBox&gt;
-      &lt;mx:Button label=&quot;Insert&quot; click=&quot;submitProject()&quot;/&gt;
-    &lt;/mx:Form&gt;
-	&lt;mx:Label x=&quot;10&quot; y=&quot;384&quot; text=&quot;{statusMsg}&quot; width=&quot;356&quot;/&gt;
+    &lt;mx:DataGrid id=&quot;dgProjects&quot; x=&quot;10&quot; y=&quot;10&quot; dataProvider=&quot;{dataProvider}&quot; width=&quot;356&quot; height=&quot;183&quot; change=&quot;ProjectGridChanged()&quot;&gt;
+        &lt;mx:columns&gt;
+            &lt;mx:DataGridColumn headerText=&quot;Code&quot; dataField=&quot;code&quot;/&gt;
+            &lt;mx:DataGridColumn headerText=&quot;Name&quot; dataField=&quot;name&quot;/&gt;
+        &lt;/mx:columns&gt;
+    &lt;/mx:DataGrid&gt;
+    &lt;mx:Button x=&quot;374&quot; y=&quot;11&quot; label=&quot;Refresh&quot; click=&quot;onInit()&quot;/&gt;
+    &lt;mx:Button x=&quot;374&quot; y=&quot;41&quot; label=&quot;Add new project&quot; click=&quot;AddNewProjectClicked()&quot;/&gt;
+    &lt;mx:HRule x=&quot;10&quot; y=&quot;201&quot; width=&quot;356&quot;/&gt;
+    &lt;mx:TextInput id=&quot;project_code&quot; width=&quot;261&quot; x=&quot;105&quot; y=&quot;209&quot; text=&quot;{project.code}&quot;/&gt;
+    &lt;mx:Label text=&quot;Code&quot; x=&quot;10&quot; y=&quot;211&quot;/&gt;
+    &lt;mx:TextInput id=&quot;project_name&quot; x=&quot;105&quot; y=&quot;239&quot; width=&quot;261&quot; text=&quot;{project.name}&quot;/&gt;
+    &lt;mx:Label text=&quot;Name&quot; x=&quot;10&quot; y=&quot;241&quot;/&gt;
+    &lt;mx:Label x=&quot;10&quot; y=&quot;271&quot; text=&quot;Created at&quot;/&gt;
+    &lt;mx:TextInput x=&quot;105&quot; y=&quot;269&quot; id=&quot;selected_created_at&quot; text=&quot;{project.created_at}&quot; width=&quot;261&quot; editable=&quot;false&quot;/&gt;
+    &lt;mx:Label x=&quot;12&quot; y=&quot;297&quot; text=&quot;Modified at&quot;/&gt;
+    &lt;mx:TextInput x=&quot;105&quot; y=&quot;299&quot; width=&quot;261&quot; text=&quot;{project.modified_at}&quot; editable=&quot;false&quot;/&gt;
+    &lt;mx:Button label=&quot;Save&quot; click=&quot;submitProject()&quot; x=&quot;374&quot; y=&quot;299&quot;/&gt;
+    &lt;mx:HRule x=&quot;10&quot; y=&quot;323&quot; width=&quot;356&quot; height=&quot;8&quot;/&gt;
+    &lt;mx:Label x=&quot;10&quot; y=&quot;339&quot; text=&quot;{statusMsg}&quot; width=&quot;356&quot;/&gt;
 &lt;/mx:Application&gt;</diff>
      <filename>flex-client/src/main.mxml</filename>
    </modified>
    <modified>
      <diff>@@ -8,10 +8,13 @@ client.py insert 1 &quot;Project name&quot;
     Inserts a new project with code = 1 and name = &quot;Project name&quot;.
 client.py get 1
     Gets a project with code = 1.
+client.py update 1 &quot;New project name&quot;
+    Updates the name on the project with code = 1.
 client.py all
     Lists all projects.
 &quot;&quot;&quot;
 
+from pprint import pprint
 import sys
 from pyamf.remoting.client import RemotingService
 
@@ -32,7 +35,16 @@ def insert(code, name):
         &quot;code&quot;: int(code),
         &quot;name&quot;: name,
     }
-    service.insert(new_project)
+    project = service.save(new_project)
+    print_project(project)
+
+def update(code, name):
+    gw = RemotingService('http://localhost:8080/')
+    service = gw.getService('ProjectService')
+    project = service.get(int(code))
+    project.name = name
+    project = service.save(project)
+    print_project(project)
 
 def get(code):
     gw = RemotingService('http://localhost:8080/')
@@ -51,7 +63,7 @@ def all():
         print_project(project)
         
 def print_project(project):
-    print &quot;Project code = %s, name = %s, created at %s&quot; % (project.code, project.name, project.created_at)
+    pprint(project)
 
 def main(args):
     if len(args) == 0:
@@ -64,6 +76,8 @@ def main(args):
         insert(args[1], args[2])
     elif command == 'get' and len(args) == 2:
         get(args[1])
+    elif command == 'update' and len(args) == 3:
+        update(args[1], args[2])
     elif command == 'all' and len(args) == 1:
         all()
     else:</diff>
      <filename>python-client/client.py</filename>
    </modified>
    <modified>
      <diff>@@ -27,10 +27,7 @@ def writeObjectAMF0(self, obj, *args, **kwargs):
         remove = True
         self.context.class_aliases[obj.__class__] = pyamf.ClassAlias(obj.__class__, None)
 
-    self.writeObject(obj, *args, **kwargs)
-
-    if remove:
-        self.context.class_aliases[obj.__class__] = None
+    writeObjectAMF(self, obj, args, kwargs, remove)
 
 def writeObjectAMF3(self, obj, *args, **kwargs):
     try:
@@ -45,8 +42,18 @@ def writeObjectAMF3(self, obj, *args, **kwargs):
             alias = pyamf.ClassAlias(obj.__class__, None)
             self.context.class_aliases[obj.__class__] = alias
 
-    self.writeObject(obj, *args, **kwargs)
+    writeObjectAMF(self, obj, args, kwargs, remove)
 
+def writeObjectAMF(self, obj, args, kwargs, remove):
+    &quot;&quot;&quot;
+    Writes an object that has already been prepared by writeObjectAMF0 or writeObjectAMF3.
+    &quot;&quot;&quot;
+    try:
+        obj._key = str(obj.key())
+    except:
+        obj._key = None
+    self.writeObject(obj, *args, **kwargs)
+    del obj._key
     if remove:
         self.context.class_aliases[obj.__class__] = None
 
@@ -54,13 +61,13 @@ def get_attrs_for_model(obj):
     &quot;&quot;&quot;
     Returns a list of properties on an C{db.Model} instance.
     &quot;&quot;&quot;
-    return list(obj.__class__._properties)
+    return list(obj.__class__._properties) + ['_key']
 
 def get_attrs_for_expando(obj):
     &quot;&quot;&quot;
     Returns a list of dynamic properties on a C{db.Expando} instance.
     &quot;&quot;&quot;
-    return obj.dynamic_properties()
+    return obj.dynamic_properties() + ['_key']
 
 pyamf.register_class(db.Model, attr_func=get_attrs_for_model, metadata=['dynamic'])
 pyamf.register_class(db.Expando, attr_func=get_attrs_for_expando, metadata=['dynamic'])</diff>
      <filename>python-client/pyamf/adapters/_google_appengine_ext_db.py</filename>
    </modified>
    <modified>
      <diff>@@ -27,10 +27,7 @@ def writeObjectAMF0(self, obj, *args, **kwargs):
         remove = True
         self.context.class_aliases[obj.__class__] = pyamf.ClassAlias(obj.__class__, None)
 
-    self.writeObject(obj, *args, **kwargs)
-
-    if remove:
-        self.context.class_aliases[obj.__class__] = None
+    writeObjectAMF(self, obj, args, kwargs, remove)
 
 def writeObjectAMF3(self, obj, *args, **kwargs):
     try:
@@ -45,8 +42,18 @@ def writeObjectAMF3(self, obj, *args, **kwargs):
             alias = pyamf.ClassAlias(obj.__class__, None)
             self.context.class_aliases[obj.__class__] = alias
 
-    self.writeObject(obj, *args, **kwargs)
+    writeObjectAMF(self, obj, args, kwargs, remove)
 
+def writeObjectAMF(self, obj, args, kwargs, remove):
+    &quot;&quot;&quot;
+    Writes an object that has already been prepared by writeObjectAMF0 or writeObjectAMF3.
+    &quot;&quot;&quot;
+    try:
+        obj._key = str(obj.key())
+    except:
+        obj._key = None
+    self.writeObject(obj, *args, **kwargs)
+    del obj._key
     if remove:
         self.context.class_aliases[obj.__class__] = None
 
@@ -54,13 +61,13 @@ def get_attrs_for_model(obj):
     &quot;&quot;&quot;
     Returns a list of properties on an C{db.Model} instance.
     &quot;&quot;&quot;
-    return list(obj.__class__._properties)
+    return list(obj.__class__._properties) + ['_key']
 
 def get_attrs_for_expando(obj):
     &quot;&quot;&quot;
     Returns a list of dynamic properties on a C{db.Expando} instance.
     &quot;&quot;&quot;
-    return obj.dynamic_properties()
+    return obj.dynamic_properties() + ['_key']
 
 pyamf.register_class(db.Model, attr_func=get_attrs_for_model, metadata=['dynamic'])
 pyamf.register_class(db.Expando, attr_func=get_attrs_for_expando, metadata=['dynamic'])</diff>
      <filename>server/pyamf/adapters/_google_appengine_ext_db.py</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,6 @@
+# http://www.nabble.com/Python-Django-Google-App-Engine-De-serialization-Issue-td18221229.html
+# obj_to_gae
+
 import logging
 from google.appengine.ext import db
 
@@ -5,6 +8,7 @@ class Project(db.Model):
     code = db.IntegerProperty()
     name = db.StringProperty()
     created_at = db.DateTimeProperty(auto_now_add=True)
+    modified_at = db.DateTimeProperty(auto_now=True)
 
 class ProjectService:
     def get(self, code):
@@ -18,6 +22,21 @@ class ProjectService:
         new_project.code = int(project.code)
         new_project.name = project.name
         new_project.put()
+        return new_project
+
+    def update(self, project):
+        logging.debug('udpate %s' % (project))
+        existing_project = Project.get(project._key)
+        existing_project.name = project.name
+        existing_project.put()
+        return Project.get(project._key)
+
+    def save(self, project):
+        logging.debug('save %s' % (project))
+        if hasattr(project, '_key') and project._key != None:
+            return self.update(project)
+        else:
+            return self.insert(project)
 
     def get_all(self):
         logging.debug('get_all')</diff>
      <filename>server/services/ProjectService.py</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>b6e7458d6ecb037f1dc1293fccc2a7d3c15a5b93</id>
    </parent>
  </parents>
  <author>
    <name>Fernando Correia</name>
    <email>fernandoacorreia@gmail.com</email>
  </author>
  <url>http://github.com/fernandoacorreia/flex-and-python-test/commit/25770d9289ba2410668f00310d57ea51a0b6b97c</url>
  <id>25770d9289ba2410668f00310d57ea51a0b6b97c</id>
  <committed-date>2008-07-19T17:47:27-07:00</committed-date>
  <authored-date>2008-07-19T17:47:27-07:00</authored-date>
  <message>support for updating objects</message>
  <tree>8c6d6ac7105e2d5c726a0defade0544c34817afe</tree>
  <committer>
    <name>Fernando Correia</name>
    <email>fernandoacorreia@gmail.com</email>
  </committer>
</commit>
