Author: philz
Date: Mon Apr 22 17:50:57 2013
New Revision: 1470635

URL: http://svn.apache.org/r1470635
Log:
AVRO-1296. Python: Fix schemas retrieved from protocol types to not ignore 
namespaces. Contributed by Jeremy Kahn.



Modified:
    avro/trunk/CHANGES.txt
    avro/trunk/lang/py/src/avro/protocol.py
    avro/trunk/lang/py/src/avro/schema.py
    avro/trunk/lang/py/test/test_protocol.py

Modified: avro/trunk/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/avro/trunk/CHANGES.txt?rev=1470635&r1=1470634&r2=1470635&view=diff
==============================================================================
--- avro/trunk/CHANGES.txt (original)
+++ avro/trunk/CHANGES.txt Mon Apr 22 17:50:57 2013
@@ -30,6 +30,9 @@ Trunk (not yet released)
 
   BUG FIXES
 
+    AVRO-1296. Python: Fix schemas retrieved from protocol types
+    to not ignore namespaces. (Jeremy Kahn via philz)
+
     AVRO-1266. Java: Fix mapred.AvroMultipleOutputs to support multiple
     different schemas.  (Ashish Nagavaram via martinkl)
 

Modified: avro/trunk/lang/py/src/avro/protocol.py
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/py/src/avro/protocol.py?rev=1470635&r1=1470634&r2=1470635&view=diff
==============================================================================
--- avro/trunk/lang/py/src/avro/protocol.py (original)
+++ avro/trunk/lang/py/src/avro/protocol.py Mon Apr 22 17:50:57 2013
@@ -123,7 +123,7 @@ class Protocol(object):
   def to_json(self):
     to_dump = {}
     to_dump['protocol'] = self.name
-    names = schema.Names()
+    names = schema.Names(default_namespace=self.namespace)
     if self.namespace: 
       to_dump['namespace'] = self.namespace
     if self.types:

Modified: avro/trunk/lang/py/src/avro/schema.py
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/py/src/avro/schema.py?rev=1470635&r1=1470634&r2=1470635&view=diff
==============================================================================
--- avro/trunk/lang/py/src/avro/schema.py (original)
+++ avro/trunk/lang/py/src/avro/schema.py Mon Apr 22 17:50:57 2013
@@ -234,7 +234,24 @@ class Names(object):
       if not self.names.has_key(test):
           return None
       return self.names[test]
-      
+  
+  def prune_namespace(self, properties):
+    """given a properties, return properties with namespace removed if
+    it matches the own default namespace"""
+    if self.default_namespace is None:
+      # I have no default -- no change
+      return properties
+    if 'namespace' not in properties:
+      # he has no namespace - no change
+      return properties
+    if properties['namespace'] != self.default_namespace:
+      # we're different - leave his stuff alone
+      return properties
+    # we each have a namespace and it's redundant. delete his.
+    prunable = properties.copy()
+    del(prunable['namespace'])
+    return prunable
+
   def add_name(self, name_attr, space_attr, new_schema):
     """
     Add a new schema object to the name set.
@@ -414,7 +431,7 @@ class FixedSchema(NamedSchema):
       return self.name_ref(names)
     else:
       names.names[self.fullname] = self
-      return self.props
+      return names.prune_namespace(self.props)
 
   def __eq__(self, that):
     return self.props == that.props
@@ -450,7 +467,7 @@ class EnumSchema(NamedSchema):
       return self.name_ref(names)
     else:
       names.names[self.fullname] = self
-      return self.props
+      return names.prune_namespace(self.props)
 
   def __eq__(self, that):
     return self.props == that.props
@@ -671,7 +688,7 @@ class RecordSchema(NamedSchema):
     else:
       names.names[self.fullname] = self
 
-    to_dump = self.props.copy()
+    to_dump = names.prune_namespace(self.props.copy())
     to_dump['fields'] = [ f.to_json(names) for f in self.fields ]
     return to_dump
 
@@ -709,7 +726,7 @@ def make_avsc_object(json_data, names=No
       return PrimitiveSchema(type)
     elif type in NAMED_TYPES:
       name = json_data.get('name')
-      namespace = json_data.get('namespace')
+      namespace = json_data.get('namespace', names.default_namespace)
       if type == 'fixed':
         size = json_data.get('size')
         return FixedSchema(name, namespace, size, names, other_props)

Modified: avro/trunk/lang/py/test/test_protocol.py
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/py/test/test_protocol.py?rev=1470635&r1=1470634&r2=1470635&view=diff
==============================================================================
--- avro/trunk/lang/py/test/test_protocol.py (original)
+++ avro/trunk/lang/py/test/test_protocol.py Mon Apr 22 17:50:57 2013
@@ -38,9 +38,7 @@ class ExampleProtocol(object):
 #
 # Example Protocols
 #
-
-EXAMPLES = [
-  ExampleProtocol("""\
+HELLO_WORLD = ExampleProtocol("""\
 {
   "namespace": "com.acme",
   "protocol": "HelloWorld",
@@ -60,7 +58,9 @@ EXAMPLES = [
     }
   }
 }
-    """, True),
+    """, True)
+EXAMPLES = [
+  HELLO_WORLD,
   ExampleProtocol("""\
 {"namespace": "org.apache.avro.test",
  "protocol": "Simple",
@@ -364,6 +364,23 @@ class TestProtocol(unittest.TestCase):
       (num_correct, len(EXAMPLES))
     self.assertEqual(num_correct, len(EXAMPLES), fail_msg)
 
+  def test_inner_namespace_set(self):
+    print ''
+    print 'TEST INNER NAMESPACE'
+    print '==================='
+    print ''
+    proto = protocol.parse(HELLO_WORLD.protocol_string)
+    self.assertEqual(proto.namespace, "com.acme")
+    greeting_type = proto.types_dict['Greeting']
+    self.assertEqual(greeting_type.namespace, 'com.acme')
+
+  def test_inner_namespace_not_rendered(self):
+    proto = protocol.parse(HELLO_WORLD.protocol_string)
+    self.assertEqual('com.acme.Greeting', proto.types[0].fullname)
+    self.assertEqual('Greeting', proto.types[0].name)
+    # but there shouldn't be 'namespace' rendered to json on the inner type
+    self.assertNotIn('namespace', proto.to_json()['types'][0])
+
   def test_valid_cast_to_string_after_parse(self):
     """
     Test that the string generated by an Avro Protocol object


Reply via email to