You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2014/09/19 23:00:51 UTC

svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Author: aconway
Date: Fri Sep 19 21:00:50 2014
New Revision: 1626329

URL: http://svn.apache.org/r1626329
Log:
PROTON-693: Python Url class to wrap C function pni_parse_url

It was pointed out that pni_parse_url is an internal function and the interface
is not suitable for public API.

Rewrote the URL parser as a proper swigable C API pn_url_*. This gets rid of the
need for previous swig insanity and is cleaner all round.

Internally still uses the pni_parse_url parser, we can clean that up later.

Added:
    qpid/proton/trunk/proton-c/include/proton/url.h
    qpid/proton/trunk/proton-c/src/url.c
Modified:
    qpid/proton/trunk/proton-c/CMakeLists.txt
    qpid/proton/trunk/proton-c/bindings/perl/perl.i
    qpid/proton/trunk/proton-c/bindings/php/php.i
    qpid/proton/trunk/proton-c/bindings/python/cproton.i
    qpid/proton/trunk/proton-c/bindings/python/proton.py
    qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
    qpid/proton/trunk/proton-c/include/proton/cproton.i
    qpid/proton/trunk/tests/python/proton_tests/url.py

Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
+++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19 21:00:50 2014
@@ -270,6 +270,7 @@ set (qpid-proton-core
   src/object/iterator.c
 
   src/util.c
+  src/url.c
   src/error.c
   src/buffer.c
   src/parser.c

Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
+++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19 21:00:50 2014
@@ -8,6 +8,7 @@
 #include <proton/messenger.h>
 #include <proton/ssl.h>
 #include <proton/driver_extras.h>
+#include <proton/url.h>
 %}
 
 %include <cstring.i>

Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
+++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19 21:00:50 2014
@@ -29,6 +29,7 @@
 %header %{
 /* Include the headers needed by the code in this wrapper file */
 #include <proton/types.h>
+#include <proton/url.h>
 #include <proton/message.h>
 #include <proton/driver.h>
 #include <proton/driver_extras.h>

Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/python/cproton.i (original)
+++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri Sep 19 21:00:50 2014
@@ -23,6 +23,7 @@
 #include <winsock2.h>
 #endif
 #include <proton/engine.h>
+#include <proton/url.h>
 #include <proton/message.h>
 #include <proton/sasl.h>
 #include <proton/driver.h>
@@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
   }
 %}
 
-
-/**
-   pni_parse_url(char* url, char **scheme, char **user, char **pass, char **host, char **port, char **path)
-   The following type maps convert this into a python function that taks a URL string argument
-   and returns a list of strings [scheme, user, pass, host, port, path]
-   This probably could be done more neatly.
-*/
-
-// Typemap to copy the url string as it will be modified by parse_url
-%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char *url (int res, char *t = 0, size_t n = 0, int alloc = 0) {
-  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
-  if (!SWIG_IsOK(res)) {
-    %argument_fail(res, "char *url", $symname, $argnum);
-  }
-  $1 = %new_array(n, $*1_ltype);
-  memcpy($1,t,sizeof(char)*n);
-  if (alloc == SWIG_NEWOBJ) %delete_array(t);
-  $1[n-1] = 0;
-}
-%typemap(freearg,match="in") char *url "free($1);";
-%typemap(argout) char *url "";
-
-// Typemap for char** return strings. Don't free them.
-%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0) "$1 = &temp;";
-%typemap(freearg,match="in") char **OUTSTR "";
-%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char **OUTSTR {
-    %append_output(SWIG_FromCharPtr(*$1));
-}
-
-// Typemap to initialize result as empty list
-%typemap(out) void "$result = PyList_New(0);";
-
-
-%apply char** OUTSTR {char **scheme, char **user, char **pass, char **host, char **port, char **path};
-void pni_parse_url(char* url, char **scheme, char **user, char **pass, char **host, char **port, char **path);
-%ignore pni_parse_url;
-
 %include "proton/cproton.i"

Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
+++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri Sep 19 21:00:50 2014
@@ -3657,114 +3657,98 @@ __all__ = [
 
 
 class Url(object):
-    """
-    Simple URL parser/constructor, handles URLs of the form:
+  """
+  Simple URL parser/constructor, handles URLs of the form:
 
-      <scheme>://<user>:<password>@<host>:<port>/<path>
+    <scheme>://<user>:<password>@<host>:<port>/<path>
 
-    All components can be None if not specifeid in the URL string.
+  All components can be None if not specifeid in the URL string.
 
-    The port can be specified as a service name, e.g. 'amqp' in the
-    URL string but Url.port always gives the integer value.
+  The port can be specified as a service name, e.g. 'amqp' in the
+  URL string but Url.port always gives the integer value.
+
+  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
+  @ivar user: Username
+  @ivar password: Password
+  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
+  @ivar port: Integer port.
+  @ivar host_port: Returns host:port
+  """
+
+  AMQPS = "amqps"
+  AMQP = "amqp"
+
+  class Port(int):
+    """An integer port number that can be constructed from a service name string"""
+
+    def __new__(cls, value):
+      port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
+      setattr(port, 'name', str(value))
+      return port
+
+    def __eq__(self, x): return str(self) == x or int(self) == x
+    def __ne__(self, x): return not self == x
+    def __str__(self): return str(self.name)
+
+    @staticmethod
+    def port_int(value):
+      """Convert service, an integer or a service name, into an integer port number."""
+      try:
+        return int(value)
+      except ValueError:
+        try:
+          return socket.getservbyname(value)
+        except socket.error:
+          raise ValueError("Not a valid port number or service name: '%s'" % value)
 
-    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
-    @ivar user: Username
-    @ivar password: Password
-    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
-    @ivar port: Integer port.
-    @ivar host_port: Returns host:port
+  def __init__(self, url=None, **kwargs):
+    """
+    @param url: URL string to parse.
+    @param kwargs: scheme, user, password, host, port, path.
+      If specified, replaces corresponding part in url string.
     """
+    if url:
+      self._url = pn_url_parse(str(url))
+      if not self._url: raise ValueError("Invalid URL '%s'" % url)
+    else:
+      self._url = pn_url()
+    for k in kwargs:            # Let kwargs override values parsed from url
+      getattr(self, k)          # Check for invalid kwargs
+      setattr(self, k, kwargs[k])
+
+  class PartDescriptor(object):
+    def __init__(self, part):
+      self.getter = globals()["pn_url_%s" % part]
+      self.setter = globals()["pn_url_set_%s" % part]
+    def __get__(self, obj, type=None): return self.getter(obj._url)
+    def __set__(self, obj, value): return self.setter(obj._url, str(value))
+
+  scheme = PartDescriptor('scheme')
+  username = PartDescriptor('username')
+  password = PartDescriptor('password')
+  host = PartDescriptor('host')
+  path = PartDescriptor('path')
+
+  @property
+  def port(self):
+    portstr = pn_url_port(self._url)
+    return portstr and Url.Port(portstr)
+
+  @port.setter
+  def port(self, value):
+    if value is None: pn_url_set_port(self._url, None)
+    else: pn_url_set_port(self._url, str(Url.Port(value)))
 
-    AMQPS = "amqps"
-    AMQP = "amqp"
+  def __str__(self): return pn_url_str(self._url)
 
-    class Port(int):
-      """An integer port number that can also have an associated service name string"""
+  def __repr__(self): return "Url(%r)" % str(self)
 
-      def __new__(cls, value):
-        port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
-        setattr(port, 'name', str(value))
-        return port
-
-      def __eq__(self, x): return str(self) == x or int(self) == x
-      def __ne__(self, x): return not self == x
-      def __str__(self): return str(self.name)
-
-      @staticmethod
-      def port_int(value):
-        """Convert service, an integer or a service name, into an integer port number."""
-        try:
-          return int(value)
-        except ValueError:
-          try:
-            return socket.getservbyname(value)
-          except socket.error:
-            raise ValueError("Not a valid port number or service name: '%s'" % value)
-
-    def __init__(self, url=None, **kwargs):
-        """
-        @param url: String or Url instance to parse or copy.
-        @param kwargs: URL fields: scheme, user, password, host, port, path.
-            If specified, replaces corresponding component in url.
-        """
-
-        fields = ['scheme', 'user', 'password', 'host', 'port', 'path']
-
-        for f in fields: setattr(self, f, None)
-        for k in kwargs: getattr(self, k) # Check for invalid kwargs
-
-        if isinstance(url, Url): # Copy from another Url instance.
-            self.__dict__.update(url.__dict__)
-        elif url is not None:   # Parse from url
-            parts = pni_parse_url(str(url))
-            if not filter(None, parts): raise ValueError("Invalid AMQP URL: '%s'" % url)
-            self.scheme, self.user, self.password, self.host, port, self.path = parts
-            if not self.host: self.host = None
-            self.port = port and self.Port(port)
-
-        # Let kwargs override values previously set from url
-        for field in fields:
-            setattr(self, field, kwargs.get(field, getattr(self, field)))
-
-    def __repr__(self):
-        return "Url(%r)" % str(self)
-
-    def __str__(self):
-        s = ""
-        if self.scheme:
-            s += "%s://" % self.scheme
-        if self.user:
-            s += self.user
-        if self.password:
-            s += ":%s" % self.password
-        if self.user or self.password:
-            s += '@'
-        if self.host and ':' in self.host:
-            s += "[%s]" % self.host
-        elif self.host:
-            s += self.host
-        if self.port:
-            s += ":%s" % self.port
-        if self.path:
-            s += "/%s" % self.path
-        return s
-
-    def __eq__(self, url):
-        return \
-            self.scheme == url.scheme and \
-            self.user == url.user and self.password == url.password and \
-            self.host == url.host and self.port == url.port and \
-            self.path == url.path
-
-    def __ne__(self, url):
-        return not self.__eq__(url)
-
-    def defaults(self):
-        """
-        Fill in missing values with defaults
-        @return: self
-        """
-        self.scheme = self.scheme or self.AMQP
-        self.host = self.host or '0.0.0.0'
-        self.port = self.port or self.Port(self.scheme)
-        return self
+  def defaults(self):
+    """
+    Fill in missing values (scheme, host or port) with defaults
+    @return: self
+    """
+    self.scheme = self.scheme or self.AMQP
+    self.host = self.host or '0.0.0.0'
+    self.port = self.port or self.Port(self.scheme)
+    return self

Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
+++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19 21:00:50 2014
@@ -26,8 +26,8 @@
 #include <proton/messenger.h>
 #include <proton/ssl.h>
 #include <proton/driver_extras.h>
-
 #include <proton/types.h>
+#include <proton/url.h>
 
 #include <uuid/uuid.h>
 %}

Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/include/proton/cproton.i (original)
+++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri Sep 19 21:00:50 2014
@@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
   pn_delivery_t *pn_cast_pn_delivery(void *x) { return (pn_delivery_t *) x; }
   pn_transport_t *pn_cast_pn_transport(void *x) { return (pn_transport_t *) x; }
 %}
+
+%include "proton/url.h"
+

Added: qpid/proton/trunk/proton-c/include/proton/url.h
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
==============================================================================
--- qpid/proton/trunk/proton-c/include/proton/url.h (added)
+++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19 21:00:50 2014
@@ -0,0 +1,83 @@
+#ifndef PROTON_URL_H
+#define PROTON_URL_H
+/*
+ * 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.
+ */
+
+#include <proton/import_export.h>
+
+/** @file
+ * URL API for parsing URLs.
+ *
+ * @defgroup url URL
+ * @{
+ */
+
+/** A parsed URL */
+typedef struct pn_url_t pn_url_t;
+
+/** Create an empty URL */
+PN_EXTERN pn_url_t *pn_url(void);
+
+/** Parse a string URL as a pn_url_t.
+ *@param[in] url A URL string.
+ *@return The parsed pn_url_t or NULL if url is not a valid URL string.
+ */
+PN_EXTERN pn_url_t *pn_url_parse(const char *url);
+
+/** Free a URL */
+PN_EXTERN void pn_url_free(pn_url_t *url);
+
+/** Clear the contents of the URL. */
+PN_EXTERN void pn_url_clear(pn_url_t *url);
+
+/** Return the string form of a URL. Owned by the pn_url_t.*/
+PN_EXTERN const char *pn_url_str(pn_url_t *url);
+
+/**
+ *@name Getters for parts of the URL.
+ *
+ *Values belong to the URL. May return NULL if the value is not set.
+ *
+ *@{
+ */
+PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
+PN_EXTERN const char *pn_url_username(pn_url_t *url);
+PN_EXTERN const char *pn_url_password(pn_url_t *url);
+PN_EXTERN const char *pn_url_host(pn_url_t *url);
+PN_EXTERN const char *pn_url_port(pn_url_t *url);
+PN_EXTERN const char *pn_url_path(pn_url_t *url);
+///@}
+
+/**
+ *@name Setters for parts of the URL.
+ *
+ *Values are copied. Value can be NULL to indicate the part is not set.
+ *
+ *@{
+ */
+PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme);
+PN_EXTERN void pn_url_set_username(pn_url_t *url, const char *username);
+PN_EXTERN void pn_url_set_password(pn_url_t *url, const char *password);
+PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host);
+PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port);
+PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path);
+///@}
+
+///@}
+#endif

Added: qpid/proton/trunk/proton-c/src/url.c
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
==============================================================================
--- qpid/proton/trunk/proton-c/src/url.c (added)
+++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50 2014
@@ -0,0 +1,127 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <proton/url.h>
+#include <proton/util.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+static char* copy(const char* str) {
+    if (str ==  NULL) return NULL;
+    char *str2 = (char*)malloc(strlen(str));
+    if (str2) strcpy(str2, str);
+    return str2;
+}
+
+struct pn_url_t {
+    char *scheme;
+    char *username;
+    char *password;
+    char *host;
+    char *port;
+    char *path;
+    char *str;
+};
+
+PN_EXTERN pn_url_t *pn_url() {
+    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
+    memset(url, 0, sizeof(*url));
+    return url;
+}
+
+/** Parse a string URL as a pn_url_t.
+ *@param[in] url A URL string.
+ *@return The parsed pn_url_t or NULL if url is not a valid URL string.
+ */
+PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
+    if (!str || !*str)          /* Empty string or NULL is illegal. */
+        return NULL;
+
+    pn_url_t *url = pn_url();
+    char *str2 = copy(str);         /* FIXME aconway 2014-09-19: clean up */
+    pni_parse_url(str2, &url->scheme, &url->username, &url->password, &url->host, &url->port, &url->path);
+    url->scheme = copy(url->scheme);
+    url->username = copy(url->username);
+    url->password = copy(url->password);
+    url->host = (url->host && !*url->host) ? NULL : copy(url->host);
+    url->port = copy(url->port);
+    url->path = copy(url->path);
+    return url;
+}
+
+/** Free a URL */
+PN_EXTERN void pn_url_free(pn_url_t *url) {
+    pn_url_clear(url);
+    free(url);
+}
+
+/** Clear the contents of the URL. */
+PN_EXTERN void pn_url_clear(pn_url_t *url) {
+    pn_url_set_username(url, NULL);
+    pn_url_set_password(url, NULL);
+    pn_url_set_host(url, NULL);
+    pn_url_set_port(url, NULL);
+    pn_url_set_path(url, NULL);
+    free(url->str); url->str = NULL;
+}
+
+static inline int len(const char *str) { return str ? strlen(str) : 0; }
+
+/** Return the string form of a URL. */
+PN_EXTERN const char *pn_url_str(pn_url_t *url) {
+    int size = len(url->scheme) + len(url->username) + len(url->password)
+        + len(url->host) + len(url->port) + len(url->path)
+        + len("s://u:p@[h]:p/p");
+    free(url->str);
+    url->str = (char*)malloc(size);
+    if (!url->str) return NULL;
+
+    int i = 0;
+    if (url->scheme) i += snprintf(url->str+i, size-i, "%s://", url->scheme);
+    if (url->username) i += snprintf(url->str+i, size-i, "%s", url->username);
+    if (url->password) i += snprintf(url->str+i, size-i, ":%s", url->password);
+    if (url->username || url->password) i += snprintf(url->str+i, size-i, "@");
+    if (url->host) {
+        if (strchr(url->host, ':')) i += snprintf(url->str+i, size-i, "[%s]", url->host);
+        else i += snprintf(url->str+i, size-i, "%s", url->host);
+    }
+    if (url->port) i += snprintf(url->str+i, size-i, ":%s", url->port);
+    if (url->path) i += snprintf(url->str+i, size-i, "/%s", url->path);
+    return url->str;
+}
+
+PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return url->scheme; }
+PN_EXTERN const char *pn_url_username(pn_url_t *url) { return url->username; }
+PN_EXTERN const char *pn_url_password(pn_url_t *url) { return url->password; }
+PN_EXTERN const char *pn_url_host(pn_url_t *url) { return url->host; }
+PN_EXTERN const char *pn_url_port(pn_url_t *url) { return url->port; }
+PN_EXTERN const char *pn_url_path(pn_url_t *url) { return url->path; }
+
+#define SET(part) free(url->part); url->part = copy(part)
+PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme) { SET(scheme); }
+PN_EXTERN void pn_url_set_username(pn_url_t *url, const char *username) { SET(username); }
+PN_EXTERN void pn_url_set_password(pn_url_t *url, const char *password) { SET(password); }
+PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host) { SET(host); }
+PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port) { SET(port); }
+PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path) { SET(path); }
+
+

Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
==============================================================================
--- qpid/proton/trunk/tests/python/proton_tests/url.py (original)
+++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep 19 21:00:50 2014
@@ -28,9 +28,9 @@ class UrlTest(common.Test):
     def assertNotEqual(self, a, b):
         assert a != b, "%s == %s" % (a, b)
 
-    def assertUrl(self, u, scheme, user, password, host, port, path):
-        self.assertEqual((u.scheme, u.user, u.password, u.host, u.port, u.path),
-                         (scheme, user, password, host, port, path))
+    def assertUrl(self, u, scheme, username, password, host, port, path):
+        self.assertEqual((u.scheme, u.username, u.password, u.host, u.port, u.path),
+                         (scheme, username, password, host, port, path))
 
     def testUrl(self):
         url = Url('amqp://me:secret@myhost:1234/foobar')
@@ -40,7 +40,7 @@ class UrlTest(common.Test):
 
     def testDefaults(self):
         # Check that we allow None for scheme, port
-        url = Url(user='me', password='secret', host='myhost', path='foobar')
+        url = Url(username='me', password='secret', host='myhost', path='foobar')
         self.assertEqual(str(url), "me:secret@myhost/foobar")
         self.assertUrl(url, None, 'me', 'secret', 'myhost', None, 'foobar')
 
@@ -97,21 +97,19 @@ class UrlTest(common.Test):
     def testMissing(self):
         self.assertUrl(Url(), None, None, None, None, None, None)
         self.assertUrl(Url('amqp://'), 'amqp', None, None, None, None, None)
-        self.assertUrl(Url('user@'), None, 'user', None, None, None, None)
+        self.assertUrl(Url('username@'), None, 'username', None, None, None, None)
         self.assertUrl(Url(':pass@'), None, '', 'pass', None, None, None)
         self.assertUrl(Url('host'), None, None, None, 'host', None, None)
         self.assertUrl(Url(':1234'), None, None, None, None, 1234, None)
         self.assertUrl(Url('/path'), None, None, None, None, None, 'path')
 
-        for s in ['amqp://', 'user@', ':pass@', ':1234', '/path']:
+        for s in ['amqp://', 'username@', ':pass@', ':1234', '/path']:
             self.assertEqual(s, str(Url(s)))
 
         for s, full in [
                 ('amqp://', 'amqp://0.0.0.0:amqp'),
-                ('user@', 'amqp://user@0.0.0.0:amqp'),
+                ('username@', 'amqp://username@0.0.0.0:amqp'),
                 (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
                 (':1234', 'amqp://0.0.0.0:1234'),
                 ('/path', 'amqp://0.0.0.0:amqp/path')]:
             self.assertEqual(str(Url(s).defaults()), full)
-
-        self.assertRaises(ValueError, Url, '')



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Alan Conway <ac...@redhat.com>.
On Thu, 2014-09-25 at 19:20 +0100, Robbie Gemmell wrote:
> Failing in a different way now, the overall run of the python tests bombs
> out. I see the same thing locally, where it was working when I made the
> commit immediately before yours :)

------------------------------------------------------------------------
r1627621 | aconway | 2014-09-25 15:40:22 -0400 (Thu, 25 Sep 2014) | 5
lines

NO-JIRA: Fix URL test to not explode under jython.

Turns out the proton test harness blows up when run under jython if you
"import
socket" in a test module. Works fine under real python. Go figure.

------------------------------------------------------------------------

> 
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/683/console
> 
> Running org.apache.qpid.proton.JythonTest
> Sep 25, 2014 6:03:44 PM org.apache.qpid.proton.JythonTest test
> INFO: About to call Jython test script:
> '/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test'
> with '/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python'
> added to Jython path
> Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 7.714
> sec <<< FAILURE!
> test(org.apache.qpid.proton.JythonTest)  Time elapsed: 7.675 sec  <<< FAILURE!
> java.lang.AssertionError: Caught PyException on invocation number 2:
> Traceback (most recent call last):
>   File "/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test",
> line 597, in <module>
>     h.scan(m)
>   File "/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test",
> line 587, in scan
>     if not (child in self.scanned or child in objects):
> TypeError: object of type 'object' has no len()
>  with message: null
> 	at org.junit.Assert.fail(Assert.java:93)
> 	at org.apache.qpid.proton.JythonTest.runTestOnce(JythonTest.java:120)
> 	at org.apache.qpid.proton.JythonTest.test(JythonTest.java:95)
> 
> 
> On 25 September 2014 18:59, Alan Conway <ac...@redhat.com> wrote:
> 
> > On Thu, 2014-09-25 at 15:59 +0100, Robbie Gemmell wrote:
> > > On 25 September 2014 15:00, Alan Conway <ac...@redhat.com> wrote:
> > >
> > > > On Wed, 2014-09-24 at 12:19 +0100, Robbie Gemmell wrote:
> > > > > The tests are now running again, but a couple of the URL tests still
> > seem
> > > > > to be failing on the CI job:
> > > > >
> > > >
> > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/
> > > > >
> > > >
> > > > They are all failing with:
> > > >  Not a valid port number or service name: 'amqps'
> > > >
> > > > Could this be a configuration problem on the CI machine, i.e. missing
> > an
> > > > 'amqps' entry in /etc/services? Can I get access to the CI machine to
> > > > poke around and see what's up?
> > > >
> > >
> > > Almost certainly no, only the core maintainers are allowed shell access
> > as
> > > far as I've seen. You can ask on builds@apache.org for those with
> > access to
> > > check things out and report back and see what happens.
> > >
> > > I think the CI instances will be running Ubuntu 12.04 or 14.04 LTS. For
> > > giggles, I dug out an ooooold Ubuntu VM with Java 6 on it and tried the
> > > tests, which failed, and it indeed has no amqp[s] entry in /etc/services
> > > file so that could well be it.
> >
> > Thanks for checking that out! I have hacked the tests to skip tests for
> > 'amqps' if it is not recognized. Poke me if there are still failures.
> >
> > ------------------------------------------------------------------------
> > r1627577 | aconway | 2014-09-25 13:59:17 -0400 (Thu, 25 Sep 2014) | 5
> > lines
> >
> > NO-JIRA: Fix URL test to skip 'amqps' tests if 'amqps' is not recognized
> > as a service name.
> >
> > On some older Ubuntu with Java 6, 'amqps' is not recognized as a service
> > name so
> > skip those tests in that case.
> >
> > ------------------------------------------------------------------------
> >
> > > >
> > > > The URL code uses socket.getservbyname() to look up service names. Is
> > > > there a more portable way to do it?
> > > >
> > >
> > > No idea I'm afraid.
> > >
> > >
> > > >
> > > > Cheers,
> > > > Alan.
> > > >
> > > > > As mentioned in my other post about a timeline for dropping Java6
> > > > support,
> > > > > they seem to work on Java8 (havent tried Java7).
> > > > >
> > > > > Robbie
> > > > >
> > > > > On 22 September 2014 21:14, Alan Conway <ac...@redhat.com> wrote:
> > > > >
> > > > > > My bad, didn't run the java tests. Will fix ASAP and then give
> > myself a
> > > > > > flogging.
> > > > > >
> > > > > > On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> > > > > > > This seems to have broken the Java test runs:
> > > > > > >
> > > > > > >
> > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > On 19 September 2014 22:00, <ac...@apache.org> wrote:
> > > > > > >
> > > > > > > > Author: aconway
> > > > > > > > Date: Fri Sep 19 21:00:50 2014
> > > > > > > > New Revision: 1626329
> > > > > > > >
> > > > > > > > URL: http://svn.apache.org/r1626329
> > > > > > > > Log:
> > > > > > > > PROTON-693: Python Url class to wrap C function pni_parse_url
> > > > > > > >
> > > > > > > > It was pointed out that pni_parse_url is an internal function
> > and
> > > > the
> > > > > > > > interface
> > > > > > > > is not suitable for public API.
> > > > > > > >
> > > > > > > > Rewrote the URL parser as a proper swigable C API pn_url_*.
> > This
> > > > gets
> > > > > > rid
> > > > > > > > of the
> > > > > > > > need for previous swig insanity and is cleaner all round.
> > > > > > > >
> > > > > > > > Internally still uses the pni_parse_url parser, we can clean
> > that
> > > > up
> > > > > > later.
> > > > > > > >
> > > > > > > > Added:
> > > > > > > >     qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > > >     qpid/proton/trunk/proton-c/src/url.c
> > > > > > > > Modified:
> > > > > > > >     qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > > >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > > >     qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19
> > 21:00:50
> > > > 2014
> > > > > > > > @@ -270,6 +270,7 @@ set (qpid-proton-core
> > > > > > > >    src/object/iterator.c
> > > > > > > >
> > > > > > > >    src/util.c
> > > > > > > > +  src/url.c
> > > > > > > >    src/error.c
> > > > > > > >    src/buffer.c
> > > > > > > >    src/parser.c
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19
> > > > 21:00:50
> > > > > > > > 2014
> > > > > > > > @@ -8,6 +8,7 @@
> > > > > > > >  #include <proton/messenger.h>
> > > > > > > >  #include <proton/ssl.h>
> > > > > > > >  #include <proton/driver_extras.h>
> > > > > > > > +#include <proton/url.h>
> > > > > > > >  %}
> > > > > > > >
> > > > > > > >  %include <cstring.i>
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19
> > > > 21:00:50
> > > > > > 2014
> > > > > > > > @@ -29,6 +29,7 @@
> > > > > > > >  %header %{
> > > > > > > >  /* Include the headers needed by the code in this wrapper
> > file */
> > > > > > > >  #include <proton/types.h>
> > > > > > > > +#include <proton/url.h>
> > > > > > > >  #include <proton/message.h>
> > > > > > > >  #include <proton/driver.h>
> > > > > > > >  #include <proton/driver_extras.h>
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri
> > Sep 19
> > > > > > > > 21:00:50 2014
> > > > > > > > @@ -23,6 +23,7 @@
> > > > > > > >  #include <winsock2.h>
> > > > > > > >  #endif
> > > > > > > >  #include <proton/engine.h>
> > > > > > > > +#include <proton/url.h>
> > > > > > > >  #include <proton/message.h>
> > > > > > > >  #include <proton/sasl.h>
> > > > > > > >  #include <proton/driver.h>
> > > > > > > > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> > > > > > > >    }
> > > > > > > >  %}
> > > > > > > >
> > > > > > > > -
> > > > > > > > -/**
> > > > > > > > -   pni_parse_url(char* url, char **scheme, char **user, char
> > > > **pass,
> > > > > > char
> > > > > > > > **host, char **port, char **path)
> > > > > > > > -   The following type maps convert this into a python function
> > > > that
> > > > > > taks
> > > > > > > > a URL string argument
> > > > > > > > -   and returns a list of strings [scheme, user, pass, host,
> > port,
> > > > > > path]
> > > > > > > > -   This probably could be done more neatly.
> > > > > > > > -*/
> > > > > > > > -
> > > > > > > > -// Typemap to copy the url string as it will be modified by
> > > > parse_url
> > > > > > > > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char
> > *url
> > > > (int
> > > > > > > > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > > > > > > > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > > > > > > > -  if (!SWIG_IsOK(res)) {
> > > > > > > > -    %argument_fail(res, "char *url", $symname, $argnum);
> > > > > > > > -  }
> > > > > > > > -  $1 = %new_array(n, $*1_ltype);
> > > > > > > > -  memcpy($1,t,sizeof(char)*n);
> > > > > > > > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > > > > > > > -  $1[n-1] = 0;
> > > > > > > > -}
> > > > > > > > -%typemap(freearg,match="in") char *url "free($1);";
> > > > > > > > -%typemap(argout) char *url "";
> > > > > > > > -
> > > > > > > > -// Typemap for char** return strings. Don't free them.
> > > > > > > > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0)
> > "$1 =
> > > > > > &temp;";
> > > > > > > > -%typemap(freearg,match="in") char **OUTSTR "";
> > > > > > > > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char
> > > > **OUTSTR {
> > > > > > > > -    %append_output(SWIG_FromCharPtr(*$1));
> > > > > > > > -}
> > > > > > > > -
> > > > > > > > -// Typemap to initialize result as empty list
> > > > > > > > -%typemap(out) void "$result = PyList_New(0);";
> > > > > > > > -
> > > > > > > > -
> > > > > > > > -%apply char** OUTSTR {char **scheme, char **user, char **pass,
> > > > char
> > > > > > > > **host, char **port, char **path};
> > > > > > > > -void pni_parse_url(char* url, char **scheme, char **user, char
> > > > **pass,
> > > > > > > > char **host, char **port, char **path);
> > > > > > > > -%ignore pni_parse_url;
> > > > > > > > -
> > > > > > > >  %include "proton/cproton.i"
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/python/proton.py
> > (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri
> > Sep 19
> > > > > > > > 21:00:50 2014
> > > > > > > > @@ -3657,114 +3657,98 @@ __all__ = [
> > > > > > > >
> > > > > > > >
> > > > > > > >  class Url(object):
> > > > > > > > -    """
> > > > > > > > -    Simple URL parser/constructor, handles URLs of the form:
> > > > > > > > +  """
> > > > > > > > +  Simple URL parser/constructor, handles URLs of the form:
> > > > > > > >
> > > > > > > > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > > > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > > >
> > > > > > > > -    All components can be None if not specifeid in the URL
> > string.
> > > > > > > > +  All components can be None if not specifeid in the URL
> > string.
> > > > > > > >
> > > > > > > > -    The port can be specified as a service name, e.g. 'amqp'
> > in
> > > > the
> > > > > > > > -    URL string but Url.port always gives the integer value.
> > > > > > > > +  The port can be specified as a service name, e.g. 'amqp' in
> > the
> > > > > > > > +  URL string but Url.port always gives the integer value.
> > > > > > > > +
> > > > > > > > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > > > +  @ivar user: Username
> > > > > > > > +  @ivar password: Password
> > > > > > > > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > > > +  @ivar port: Integer port.
> > > > > > > > +  @ivar host_port: Returns host:port
> > > > > > > > +  """
> > > > > > > > +
> > > > > > > > +  AMQPS = "amqps"
> > > > > > > > +  AMQP = "amqp"
> > > > > > > > +
> > > > > > > > +  class Port(int):
> > > > > > > > +    """An integer port number that can be constructed from a
> > > > service
> > > > > > name
> > > > > > > > string"""
> > > > > > > > +
> > > > > > > > +    def __new__(cls, value):
> > > > > > > > +      port = super(Url.Port, cls).__new__(cls,
> > > > cls.port_int(value))
> > > > > > > > +      setattr(port, 'name', str(value))
> > > > > > > > +      return port
> > > > > > > > +
> > > > > > > > +    def __eq__(self, x): return str(self) == x or int(self)
> > == x
> > > > > > > > +    def __ne__(self, x): return not self == x
> > > > > > > > +    def __str__(self): return str(self.name)
> > > > > > > > +
> > > > > > > > +    @staticmethod
> > > > > > > > +    def port_int(value):
> > > > > > > > +      """Convert service, an integer or a service name, into
> > an
> > > > > > integer
> > > > > > > > port number."""
> > > > > > > > +      try:
> > > > > > > > +        return int(value)
> > > > > > > > +      except ValueError:
> > > > > > > > +        try:
> > > > > > > > +          return socket.getservbyname(value)
> > > > > > > > +        except socket.error:
> > > > > > > > +          raise ValueError("Not a valid port number or service
> > > > name:
> > > > > > > > '%s'" % value)
> > > > > > > >
> > > > > > > > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > > > -    @ivar user: Username
> > > > > > > > -    @ivar password: Password
> > > > > > > > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > > > -    @ivar port: Integer port.
> > > > > > > > -    @ivar host_port: Returns host:port
> > > > > > > > +  def __init__(self, url=None, **kwargs):
> > > > > > > > +    """
> > > > > > > > +    @param url: URL string to parse.
> > > > > > > > +    @param kwargs: scheme, user, password, host, port, path.
> > > > > > > > +      If specified, replaces corresponding part in url string.
> > > > > > > >      """
> > > > > > > > +    if url:
> > > > > > > > +      self._url = pn_url_parse(str(url))
> > > > > > > > +      if not self._url: raise ValueError("Invalid URL '%s'" %
> > url)
> > > > > > > > +    else:
> > > > > > > > +      self._url = pn_url()
> > > > > > > > +    for k in kwargs:            # Let kwargs override values
> > > > parsed
> > > > > > from
> > > > > > > > url
> > > > > > > > +      getattr(self, k)          # Check for invalid kwargs
> > > > > > > > +      setattr(self, k, kwargs[k])
> > > > > > > > +
> > > > > > > > +  class PartDescriptor(object):
> > > > > > > > +    def __init__(self, part):
> > > > > > > > +      self.getter = globals()["pn_url_%s" % part]
> > > > > > > > +      self.setter = globals()["pn_url_set_%s" % part]
> > > > > > > > +    def __get__(self, obj, type=None): return
> > > > self.getter(obj._url)
> > > > > > > > +    def __set__(self, obj, value): return
> > self.setter(obj._url,
> > > > > > > > str(value))
> > > > > > > > +
> > > > > > > > +  scheme = PartDescriptor('scheme')
> > > > > > > > +  username = PartDescriptor('username')
> > > > > > > > +  password = PartDescriptor('password')
> > > > > > > > +  host = PartDescriptor('host')
> > > > > > > > +  path = PartDescriptor('path')
> > > > > > > > +
> > > > > > > > +  @property
> > > > > > > > +  def port(self):
> > > > > > > > +    portstr = pn_url_port(self._url)
> > > > > > > > +    return portstr and Url.Port(portstr)
> > > > > > > > +
> > > > > > > > +  @port.setter
> > > > > > > > +  def port(self, value):
> > > > > > > > +    if value is None: pn_url_set_port(self._url, None)
> > > > > > > > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> > > > > > > >
> > > > > > > > -    AMQPS = "amqps"
> > > > > > > > -    AMQP = "amqp"
> > > > > > > > +  def __str__(self): return pn_url_str(self._url)
> > > > > > > >
> > > > > > > > -    class Port(int):
> > > > > > > > -      """An integer port number that can also have an
> > associated
> > > > > > service
> > > > > > > > name string"""
> > > > > > > > +  def __repr__(self): return "Url(%r)" % str(self)
> > > > > > > >
> > > > > > > > -      def __new__(cls, value):
> > > > > > > > -        port = super(Url.Port, cls).__new__(cls,
> > > > cls.port_int(value))
> > > > > > > > -        setattr(port, 'name', str(value))
> > > > > > > > -        return port
> > > > > > > > -
> > > > > > > > -      def __eq__(self, x): return str(self) == x or int(self)
> > == x
> > > > > > > > -      def __ne__(self, x): return not self == x
> > > > > > > > -      def __str__(self): return str(self.name)
> > > > > > > > -
> > > > > > > > -      @staticmethod
> > > > > > > > -      def port_int(value):
> > > > > > > > -        """Convert service, an integer or a service name,
> > into an
> > > > > > integer
> > > > > > > > port number."""
> > > > > > > > -        try:
> > > > > > > > -          return int(value)
> > > > > > > > -        except ValueError:
> > > > > > > > -          try:
> > > > > > > > -            return socket.getservbyname(value)
> > > > > > > > -          except socket.error:
> > > > > > > > -            raise ValueError("Not a valid port number or
> > service
> > > > name:
> > > > > > > > '%s'" % value)
> > > > > > > > -
> > > > > > > > -    def __init__(self, url=None, **kwargs):
> > > > > > > > -        """
> > > > > > > > -        @param url: String or Url instance to parse or copy.
> > > > > > > > -        @param kwargs: URL fields: scheme, user, password,
> > host,
> > > > port,
> > > > > > > > path.
> > > > > > > > -            If specified, replaces corresponding component in
> > url.
> > > > > > > > -        """
> > > > > > > > -
> > > > > > > > -        fields = ['scheme', 'user', 'password', 'host',
> > 'port',
> > > > > > 'path']
> > > > > > > > -
> > > > > > > > -        for f in fields: setattr(self, f, None)
> > > > > > > > -        for k in kwargs: getattr(self, k) # Check for invalid
> > > > kwargs
> > > > > > > > -
> > > > > > > > -        if isinstance(url, Url): # Copy from another Url
> > instance.
> > > > > > > > -            self.__dict__.update(url.__dict__)
> > > > > > > > -        elif url is not None:   # Parse from url
> > > > > > > > -            parts = pni_parse_url(str(url))
> > > > > > > > -            if not filter(None, parts): raise
> > ValueError("Invalid
> > > > AMQP
> > > > > > > > URL: '%s'" % url)
> > > > > > > > -            self.scheme, self.user, self.password, self.host,
> > > > port,
> > > > > > > > self.path = parts
> > > > > > > > -            if not self.host: self.host = None
> > > > > > > > -            self.port = port and self.Port(port)
> > > > > > > > -
> > > > > > > > -        # Let kwargs override values previously set from url
> > > > > > > > -        for field in fields:
> > > > > > > > -            setattr(self, field, kwargs.get(field,
> > getattr(self,
> > > > > > field)))
> > > > > > > > -
> > > > > > > > -    def __repr__(self):
> > > > > > > > -        return "Url(%r)" % str(self)
> > > > > > > > -
> > > > > > > > -    def __str__(self):
> > > > > > > > -        s = ""
> > > > > > > > -        if self.scheme:
> > > > > > > > -            s += "%s://" % self.scheme
> > > > > > > > -        if self.user:
> > > > > > > > -            s += self.user
> > > > > > > > -        if self.password:
> > > > > > > > -            s += ":%s" % self.password
> > > > > > > > -        if self.user or self.password:
> > > > > > > > -            s += '@'
> > > > > > > > -        if self.host and ':' in self.host:
> > > > > > > > -            s += "[%s]" % self.host
> > > > > > > > -        elif self.host:
> > > > > > > > -            s += self.host
> > > > > > > > -        if self.port:
> > > > > > > > -            s += ":%s" % self.port
> > > > > > > > -        if self.path:
> > > > > > > > -            s += "/%s" % self.path
> > > > > > > > -        return s
> > > > > > > > -
> > > > > > > > -    def __eq__(self, url):
> > > > > > > > -        return \
> > > > > > > > -            self.scheme == url.scheme and \
> > > > > > > > -            self.user == url.user and self.password ==
> > > > url.password
> > > > > > and \
> > > > > > > > -            self.host == url.host and self.port == url.port
> > and \
> > > > > > > > -            self.path == url.path
> > > > > > > > -
> > > > > > > > -    def __ne__(self, url):
> > > > > > > > -        return not self.__eq__(url)
> > > > > > > > -
> > > > > > > > -    def defaults(self):
> > > > > > > > -        """
> > > > > > > > -        Fill in missing values with defaults
> > > > > > > > -        @return: self
> > > > > > > > -        """
> > > > > > > > -        self.scheme = self.scheme or self.AMQP
> > > > > > > > -        self.host = self.host or '0.0.0.0'
> > > > > > > > -        self.port = self.port or self.Port(self.scheme)
> > > > > > > > -        return self
> > > > > > > > +  def defaults(self):
> > > > > > > > +    """
> > > > > > > > +    Fill in missing values (scheme, host or port) with
> > defaults
> > > > > > > > +    @return: self
> > > > > > > > +    """
> > > > > > > > +    self.scheme = self.scheme or self.AMQP
> > > > > > > > +    self.host = self.host or '0.0.0.0'
> > > > > > > > +    self.port = self.port or self.Port(self.scheme)
> > > > > > > > +    return self
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19
> > > > 21:00:50
> > > > > > > > 2014
> > > > > > > > @@ -26,8 +26,8 @@
> > > > > > > >  #include <proton/messenger.h>
> > > > > > > >  #include <proton/ssl.h>
> > > > > > > >  #include <proton/driver_extras.h>
> > > > > > > > -
> > > > > > > >  #include <proton/types.h>
> > > > > > > > +#include <proton/url.h>
> > > > > > > >
> > > > > > > >  #include <uuid/uuid.h>
> > > > > > > >  %}
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/include/proton/cproton.i
> > (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri
> > Sep 19
> > > > > > > > 21:00:50 2014
> > > > > > > > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> > > > > > > >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return
> > > > (pn_delivery_t
> > > > > > *)
> > > > > > > > x; }
> > > > > > > >    pn_transport_t *pn_cast_pn_transport(void *x) { return
> > > > > > (pn_transport_t
> > > > > > > > *) x; }
> > > > > > > >  %}
> > > > > > > > +
> > > > > > > > +%include "proton/url.h"
> > > > > > > > +
> > > > > > > >
> > > > > > > > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > > > > > > > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19
> > > > 21:00:50
> > > > > > > > 2014
> > > > > > > > @@ -0,0 +1,83 @@
> > > > > > > > +#ifndef PROTON_URL_H
> > > > > > > > +#define PROTON_URL_H
> > > > > > > > +/*
> > > > > > > > + * 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.
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +#include <proton/import_export.h>
> > > > > > > > +
> > > > > > > > +/** @file
> > > > > > > > + * URL API for parsing URLs.
> > > > > > > > + *
> > > > > > > > + * @defgroup url URL
> > > > > > > > + * @{
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +/** A parsed URL */
> > > > > > > > +typedef struct pn_url_t pn_url_t;
> > > > > > > > +
> > > > > > > > +/** Create an empty URL */
> > > > > > > > +PN_EXTERN pn_url_t *pn_url(void);
> > > > > > > > +
> > > > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > > > + *@param[in] url A URL string.
> > > > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid
> > URL
> > > > > > string.
> > > > > > > > + */
> > > > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > > > > > > > +
> > > > > > > > +/** Free a URL */
> > > > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > > > > > > > +
> > > > > > > > +/** Clear the contents of the URL. */
> > > > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > > > > > > > +
> > > > > > > > +/** Return the string form of a URL. Owned by the pn_url_t.*/
> > > > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + *@name Getters for parts of the URL.
> > > > > > > > + *
> > > > > > > > + *Values belong to the URL. May return NULL if the value is
> > not
> > > > set.
> > > > > > > > + *
> > > > > > > > + *@{
> > > > > > > > + */
> > > > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > > > > > > > +///@}
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + *@name Setters for parts of the URL.
> > > > > > > > + *
> > > > > > > > + *Values are copied. Value can be NULL to indicate the part
> > is not
> > > > > > set.
> > > > > > > > + *
> > > > > > > > + *@{
> > > > > > > > + */
> > > > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > > > *scheme);
> > > > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > > > *username);
> > > > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > > > *password);
> > > > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char
> > *host);
> > > > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char
> > *port);
> > > > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char
> > *path);
> > > > > > > > +///@}
> > > > > > > > +
> > > > > > > > +///@}
> > > > > > > > +#endif
> > > > > > > >
> > > > > > > > Added: qpid/proton/trunk/proton-c/src/url.c
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > > > > > > > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50
> > 2014
> > > > > > > > @@ -0,0 +1,127 @@
> > > > > > > > +/*
> > > > > > > > + *
> > > > > > > > + * 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.
> > > > > > > > + *
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +#include <proton/url.h>
> > > > > > > > +#include <proton/util.h>
> > > > > > > > +#include <stdlib.h>
> > > > > > > > +#include <string.h>
> > > > > > > > +#include <stdio.h>
> > > > > > > > +
> > > > > > > > +static char* copy(const char* str) {
> > > > > > > > +    if (str ==  NULL) return NULL;
> > > > > > > > +    char *str2 = (char*)malloc(strlen(str));
> > > > > > > > +    if (str2) strcpy(str2, str);
> > > > > > > > +    return str2;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +struct pn_url_t {
> > > > > > > > +    char *scheme;
> > > > > > > > +    char *username;
> > > > > > > > +    char *password;
> > > > > > > > +    char *host;
> > > > > > > > +    char *port;
> > > > > > > > +    char *path;
> > > > > > > > +    char *str;
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +PN_EXTERN pn_url_t *pn_url() {
> > > > > > > > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > > > > > > > +    memset(url, 0, sizeof(*url));
> > > > > > > > +    return url;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > > > + *@param[in] url A URL string.
> > > > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid
> > URL
> > > > > > string.
> > > > > > > > + */
> > > > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > > > > > > > +    if (!str || !*str)          /* Empty string or NULL is
> > > > illegal. */
> > > > > > > > +        return NULL;
> > > > > > > > +
> > > > > > > > +    pn_url_t *url = pn_url();
> > > > > > > > +    char *str2 = copy(str);         /* FIXME aconway
> > 2014-09-19:
> > > > > > clean up
> > > > > > > > */
> > > > > > > > +    pni_parse_url(str2, &url->scheme, &url->username,
> > > > &url->password,
> > > > > > > > &url->host, &url->port, &url->path);
> > > > > > > > +    url->scheme = copy(url->scheme);
> > > > > > > > +    url->username = copy(url->username);
> > > > > > > > +    url->password = copy(url->password);
> > > > > > > > +    url->host = (url->host && !*url->host) ? NULL :
> > > > copy(url->host);
> > > > > > > > +    url->port = copy(url->port);
> > > > > > > > +    url->path = copy(url->path);
> > > > > > > > +    return url;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +/** Free a URL */
> > > > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > > > > > > > +    pn_url_clear(url);
> > > > > > > > +    free(url);
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +/** Clear the contents of the URL. */
> > > > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > > > > > > > +    pn_url_set_username(url, NULL);
> > > > > > > > +    pn_url_set_password(url, NULL);
> > > > > > > > +    pn_url_set_host(url, NULL);
> > > > > > > > +    pn_url_set_port(url, NULL);
> > > > > > > > +    pn_url_set_path(url, NULL);
> > > > > > > > +    free(url->str); url->str = NULL;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +static inline int len(const char *str) { return str ?
> > strlen(str)
> > > > :
> > > > > > 0; }
> > > > > > > > +
> > > > > > > > +/** Return the string form of a URL. */
> > > > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > > > > > > > +    int size = len(url->scheme) + len(url->username) +
> > > > > > len(url->password)
> > > > > > > > +        + len(url->host) + len(url->port) + len(url->path)
> > > > > > > > +        + len("s://u:p@[h]:p/p");
> > > > > > > > +    free(url->str);
> > > > > > > > +    url->str = (char*)malloc(size);
> > > > > > > > +    if (!url->str) return NULL;
> > > > > > > > +
> > > > > > > > +    int i = 0;
> > > > > > > > +    if (url->scheme) i += snprintf(url->str+i, size-i,
> > "%s://",
> > > > > > > > url->scheme);
> > > > > > > > +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> > > > > > > > url->username);
> > > > > > > > +    if (url->password) i += snprintf(url->str+i, size-i,
> > ":%s",
> > > > > > > > url->password);
> > > > > > > > +    if (url->username || url->password) i +=
> > snprintf(url->str+i,
> > > > > > size-i,
> > > > > > > > "@");
> > > > > > > > +    if (url->host) {
> > > > > > > > +        if (strchr(url->host, ':')) i += snprintf(url->str+i,
> > > > size-i,
> > > > > > > > "[%s]", url->host);
> > > > > > > > +        else i += snprintf(url->str+i, size-i, "%s",
> > url->host);
> > > > > > > > +    }
> > > > > > > > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
> > > > > > url->port);
> > > > > > > > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
> > > > > > url->path);
> > > > > > > > +    return url->str;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
> > > > > > url->scheme; }
> > > > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> > > > > > > > url->username; }
> > > > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> > > > > > > > url->password; }
> > > > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return
> > > > url->host; }
> > > > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return
> > > > url->port; }
> > > > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return
> > > > url->path; }
> > > > > > > > +
> > > > > > > > +#define SET(part) free(url->part); url->part = copy(part)
> > > > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > > > *scheme) {
> > > > > > > > SET(scheme); }
> > > > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > > > *username) {
> > > > > > > > SET(username); }
> > > > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > > > *password) {
> > > > > > > > SET(password); }
> > > > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char
> > *host) {
> > > > > > > > SET(host); }
> > > > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char
> > *port) {
> > > > > > > > SET(port); }
> > > > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char
> > *path) {
> > > > > > > > SET(path); }
> > > > > > > > +
> > > > > > > > +
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/tests/python/proton_tests/url.py
> > (original)
> > > > > > > > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep
> > 19
> > > > > > 21:00:50
> > > > > > > > 2014
> > > > > > > > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> > > > > > > >      def assertNotEqual(self, a, b):
> > > > > > > >          assert a != b, "%s == %s" % (a, b)
> > > > > > > >
> > > > > > > > -    def assertUrl(self, u, scheme, user, password, host, port,
> > > > path):
> > > > > > > > -        self.assertEqual((u.scheme, u.user, u.password,
> > u.host,
> > > > > > u.port,
> > > > > > > > u.path),
> > > > > > > > -                         (scheme, user, password, host, port,
> > > > path))
> > > > > > > > +    def assertUrl(self, u, scheme, username, password, host,
> > port,
> > > > > > path):
> > > > > > > > +        self.assertEqual((u.scheme, u.username, u.password,
> > > > u.host,
> > > > > > > > u.port, u.path),
> > > > > > > > +                         (scheme, username, password, host,
> > port,
> > > > > > path))
> > > > > > > >
> > > > > > > >      def testUrl(self):
> > > > > > > >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > > > > > > > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> > > > > > > >
> > > > > > > >      def testDefaults(self):
> > > > > > > >          # Check that we allow None for scheme, port
> > > > > > > > -        url = Url(user='me', password='secret', host='myhost',
> > > > > > > > path='foobar')
> > > > > > > > +        url = Url(username='me', password='secret',
> > host='myhost',
> > > > > > > > path='foobar')
> > > > > > > >          self.assertEqual(str(url), "me:secret@myhost/foobar")
> > > > > > > >          self.assertUrl(url, None, 'me', 'secret', 'myhost',
> > None,
> > > > > > > > 'foobar')
> > > > > > > >
> > > > > > > > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> > > > > > > >      def testMissing(self):
> > > > > > > >          self.assertUrl(Url(), None, None, None, None, None,
> > None)
> > > > > > > >          self.assertUrl(Url('amqp://'), 'amqp', None, None,
> > None,
> > > > None,
> > > > > > > > None)
> > > > > > > > -        self.assertUrl(Url('user@'), None, 'user', None,
> > None,
> > > > None,
> > > > > > > > None)
> > > > > > > > +        self.assertUrl(Url('username@'), None, 'username',
> > None,
> > > > > > None,
> > > > > > > > None, None)
> > > > > > > >          self.assertUrl(Url(':pass@'), None, '', 'pass', None,
> > > > None,
> > > > > > None)
> > > > > > > >          self.assertUrl(Url('host'), None, None, None, 'host',
> > > > None,
> > > > > > None)
> > > > > > > >          self.assertUrl(Url(':1234'), None, None, None, None,
> > 1234,
> > > > > > None)
> > > > > > > >          self.assertUrl(Url('/path'), None, None, None, None,
> > None,
> > > > > > 'path')
> > > > > > > >
> > > > > > > > -        for s in ['amqp://', 'user@', ':pass@', ':1234',
> > > > '/path']:
> > > > > > > > +        for s in ['amqp://', 'username@', ':pass@', ':1234',
> > > > > > '/path']:
> > > > > > > >              self.assertEqual(s, str(Url(s)))
> > > > > > > >
> > > > > > > >          for s, full in [
> > > > > > > >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > > > > > > > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > > > > > > > +                ('username@', 'amqp://username@0.0.0.0:
> > amqp'),
> > > > > > > >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> > > > > > > >                  (':1234', 'amqp://0.0.0.0:1234'),
> > > > > > > >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> > > > > > > >              self.assertEqual(str(Url(s).defaults()), full)
> > > > > > > > -
> > > > > > > > -        self.assertRaises(ValueError, Url, '')
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > ---------------------------------------------------------------------
> > > > > > > > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > > > > > > > For additional commands, e-mail: commits-help@qpid.apache.org
> > > > > > > >
> > > > > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > >
> > ---------------------------------------------------------------------
> > > > > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > > > > For additional commands, e-mail: dev-help@qpid.apache.org
> > > > > >
> > > > > >
> > > >
> > > >
> > > >
> > > > ---------------------------------------------------------------------
> > > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > > For additional commands, e-mail: dev-help@qpid.apache.org
> > > >
> > > >
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > For additional commands, e-mail: dev-help@qpid.apache.org
> >
> >



Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Clebert Suconic <cs...@redhat.com>.
This is also failing for me when I run the entire mvn install (after a mvn clean).. it's not just on the CI for me



On Sep 25, 2014, at 2:20 PM, Robbie Gemmell <ro...@gmail.com> wrote:

> Failing in a different way now, the overall run of the python tests bombs
> out. I see the same thing locally, where it was working when I made the
> commit immediately before yours :)
> 
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/683/console
> 
> Running org.apache.qpid.proton.JythonTest
> Sep 25, 2014 6:03:44 PM org.apache.qpid.proton.JythonTest test
> INFO: About to call Jython test script:
> '/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test'
> with '/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python'
> added to Jython path
> Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 7.714
> sec <<< FAILURE!
> test(org.apache.qpid.proton.JythonTest)  Time elapsed: 7.675 sec  <<< FAILURE!
> java.lang.AssertionError: Caught PyException on invocation number 2:
> Traceback (most recent call last):
>  File "/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test",
> line 597, in <module>
>    h.scan(m)
>  File "/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test",
> line 587, in scan
>    if not (child in self.scanned or child in objects):
> TypeError: object of type 'object' has no len()
> with message: null
> 	at org.junit.Assert.fail(Assert.java:93)
> 	at org.apache.qpid.proton.JythonTest.runTestOnce(JythonTest.java:120)
> 	at org.apache.qpid.proton.JythonTest.test(JythonTest.java:95)
> 
> 
> On 25 September 2014 18:59, Alan Conway <ac...@redhat.com> wrote:
> 
>> On Thu, 2014-09-25 at 15:59 +0100, Robbie Gemmell wrote:
>>> On 25 September 2014 15:00, Alan Conway <ac...@redhat.com> wrote:
>>> 
>>>> On Wed, 2014-09-24 at 12:19 +0100, Robbie Gemmell wrote:
>>>>> The tests are now running again, but a couple of the URL tests still
>> seem
>>>>> to be failing on the CI job:
>>>>> 
>>>> 
>> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/
>>>>> 
>>>> 
>>>> They are all failing with:
>>>> Not a valid port number or service name: 'amqps'
>>>> 
>>>> Could this be a configuration problem on the CI machine, i.e. missing
>> an
>>>> 'amqps' entry in /etc/services? Can I get access to the CI machine to
>>>> poke around and see what's up?
>>>> 
>>> 
>>> Almost certainly no, only the core maintainers are allowed shell access
>> as
>>> far as I've seen. You can ask on builds@apache.org for those with
>> access to
>>> check things out and report back and see what happens.
>>> 
>>> I think the CI instances will be running Ubuntu 12.04 or 14.04 LTS. For
>>> giggles, I dug out an ooooold Ubuntu VM with Java 6 on it and tried the
>>> tests, which failed, and it indeed has no amqp[s] entry in /etc/services
>>> file so that could well be it.
>> 
>> Thanks for checking that out! I have hacked the tests to skip tests for
>> 'amqps' if it is not recognized. Poke me if there are still failures.
>> 
>> ------------------------------------------------------------------------
>> r1627577 | aconway | 2014-09-25 13:59:17 -0400 (Thu, 25 Sep 2014) | 5
>> lines
>> 
>> NO-JIRA: Fix URL test to skip 'amqps' tests if 'amqps' is not recognized
>> as a service name.
>> 
>> On some older Ubuntu with Java 6, 'amqps' is not recognized as a service
>> name so
>> skip those tests in that case.
>> 
>> ------------------------------------------------------------------------
>> 
>>>> 
>>>> The URL code uses socket.getservbyname() to look up service names. Is
>>>> there a more portable way to do it?
>>>> 
>>> 
>>> No idea I'm afraid.
>>> 
>>> 
>>>> 
>>>> Cheers,
>>>> Alan.
>>>> 
>>>>> As mentioned in my other post about a timeline for dropping Java6
>>>> support,
>>>>> they seem to work on Java8 (havent tried Java7).
>>>>> 
>>>>> Robbie
>>>>> 
>>>>> On 22 September 2014 21:14, Alan Conway <ac...@redhat.com> wrote:
>>>>> 
>>>>>> My bad, didn't run the java tests. Will fix ASAP and then give
>> myself a
>>>>>> flogging.
>>>>>> 
>>>>>> On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
>>>>>>> This seems to have broken the Java test runs:
>>>>>>> 
>>>>>>> 
>> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> On 19 September 2014 22:00, <ac...@apache.org> wrote:
>>>>>>> 
>>>>>>>> Author: aconway
>>>>>>>> Date: Fri Sep 19 21:00:50 2014
>>>>>>>> New Revision: 1626329
>>>>>>>> 
>>>>>>>> URL: http://svn.apache.org/r1626329
>>>>>>>> Log:
>>>>>>>> PROTON-693: Python Url class to wrap C function pni_parse_url
>>>>>>>> 
>>>>>>>> It was pointed out that pni_parse_url is an internal function
>> and
>>>> the
>>>>>>>> interface
>>>>>>>> is not suitable for public API.
>>>>>>>> 
>>>>>>>> Rewrote the URL parser as a proper swigable C API pn_url_*.
>> This
>>>> gets
>>>>>> rid
>>>>>>>> of the
>>>>>>>> need for previous swig insanity and is cleaner all round.
>>>>>>>> 
>>>>>>>> Internally still uses the pni_parse_url parser, we can clean
>> that
>>>> up
>>>>>> later.
>>>>>>>> 
>>>>>>>> Added:
>>>>>>>>    qpid/proton/trunk/proton-c/include/proton/url.h
>>>>>>>>    qpid/proton/trunk/proton-c/src/url.c
>>>>>>>> Modified:
>>>>>>>>    qpid/proton/trunk/proton-c/CMakeLists.txt
>>>>>>>>    qpid/proton/trunk/proton-c/bindings/perl/perl.i
>>>>>>>>    qpid/proton/trunk/proton-c/bindings/php/php.i
>>>>>>>>    qpid/proton/trunk/proton-c/bindings/python/cproton.i
>>>>>>>>    qpid/proton/trunk/proton-c/bindings/python/proton.py
>>>>>>>>    qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
>>>>>>>>    qpid/proton/trunk/proton-c/include/proton/cproton.i
>>>>>>>>    qpid/proton/trunk/tests/python/proton_tests/url.py
>>>>>>>> 
>>>>>>>> Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
>>>>>>>> +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19
>> 21:00:50
>>>> 2014
>>>>>>>> @@ -270,6 +270,7 @@ set (qpid-proton-core
>>>>>>>>   src/object/iterator.c
>>>>>>>> 
>>>>>>>>   src/util.c
>>>>>>>> +  src/url.c
>>>>>>>>   src/error.c
>>>>>>>>   src/buffer.c
>>>>>>>>   src/parser.c
>>>>>>>> 
>>>>>>>> Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
>>>>>>>> +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19
>>>> 21:00:50
>>>>>>>> 2014
>>>>>>>> @@ -8,6 +8,7 @@
>>>>>>>> #include <proton/messenger.h>
>>>>>>>> #include <proton/ssl.h>
>>>>>>>> #include <proton/driver_extras.h>
>>>>>>>> +#include <proton/url.h>
>>>>>>>> %}
>>>>>>>> 
>>>>>>>> %include <cstring.i>
>>>>>>>> 
>>>>>>>> Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
>>>>>>>> +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19
>>>> 21:00:50
>>>>>> 2014
>>>>>>>> @@ -29,6 +29,7 @@
>>>>>>>> %header %{
>>>>>>>> /* Include the headers needed by the code in this wrapper
>> file */
>>>>>>>> #include <proton/types.h>
>>>>>>>> +#include <proton/url.h>
>>>>>>>> #include <proton/message.h>
>>>>>>>> #include <proton/driver.h>
>>>>>>>> #include <proton/driver_extras.h>
>>>>>>>> 
>>>>>>>> Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/bindings/python/cproton.i
>> (original)
>>>>>>>> +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri
>> Sep 19
>>>>>>>> 21:00:50 2014
>>>>>>>> @@ -23,6 +23,7 @@
>>>>>>>> #include <winsock2.h>
>>>>>>>> #endif
>>>>>>>> #include <proton/engine.h>
>>>>>>>> +#include <proton/url.h>
>>>>>>>> #include <proton/message.h>
>>>>>>>> #include <proton/sasl.h>
>>>>>>>> #include <proton/driver.h>
>>>>>>>> @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
>>>>>>>>   }
>>>>>>>> %}
>>>>>>>> 
>>>>>>>> -
>>>>>>>> -/**
>>>>>>>> -   pni_parse_url(char* url, char **scheme, char **user, char
>>>> **pass,
>>>>>> char
>>>>>>>> **host, char **port, char **path)
>>>>>>>> -   The following type maps convert this into a python function
>>>> that
>>>>>> taks
>>>>>>>> a URL string argument
>>>>>>>> -   and returns a list of strings [scheme, user, pass, host,
>> port,
>>>>>> path]
>>>>>>>> -   This probably could be done more neatly.
>>>>>>>> -*/
>>>>>>>> -
>>>>>>>> -// Typemap to copy the url string as it will be modified by
>>>> parse_url
>>>>>>>> -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char
>> *url
>>>> (int
>>>>>>>> res, char *t = 0, size_t n = 0, int alloc = 0) {
>>>>>>>> -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
>>>>>>>> -  if (!SWIG_IsOK(res)) {
>>>>>>>> -    %argument_fail(res, "char *url", $symname, $argnum);
>>>>>>>> -  }
>>>>>>>> -  $1 = %new_array(n, $*1_ltype);
>>>>>>>> -  memcpy($1,t,sizeof(char)*n);
>>>>>>>> -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
>>>>>>>> -  $1[n-1] = 0;
>>>>>>>> -}
>>>>>>>> -%typemap(freearg,match="in") char *url "free($1);";
>>>>>>>> -%typemap(argout) char *url "";
>>>>>>>> -
>>>>>>>> -// Typemap for char** return strings. Don't free them.
>>>>>>>> -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0)
>> "$1 =
>>>>>> &temp;";
>>>>>>>> -%typemap(freearg,match="in") char **OUTSTR "";
>>>>>>>> -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char
>>>> **OUTSTR {
>>>>>>>> -    %append_output(SWIG_FromCharPtr(*$1));
>>>>>>>> -}
>>>>>>>> -
>>>>>>>> -// Typemap to initialize result as empty list
>>>>>>>> -%typemap(out) void "$result = PyList_New(0);";
>>>>>>>> -
>>>>>>>> -
>>>>>>>> -%apply char** OUTSTR {char **scheme, char **user, char **pass,
>>>> char
>>>>>>>> **host, char **port, char **path};
>>>>>>>> -void pni_parse_url(char* url, char **scheme, char **user, char
>>>> **pass,
>>>>>>>> char **host, char **port, char **path);
>>>>>>>> -%ignore pni_parse_url;
>>>>>>>> -
>>>>>>>> %include "proton/cproton.i"
>>>>>>>> 
>>>>>>>> Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/bindings/python/proton.py
>> (original)
>>>>>>>> +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri
>> Sep 19
>>>>>>>> 21:00:50 2014
>>>>>>>> @@ -3657,114 +3657,98 @@ __all__ = [
>>>>>>>> 
>>>>>>>> 
>>>>>>>> class Url(object):
>>>>>>>> -    """
>>>>>>>> -    Simple URL parser/constructor, handles URLs of the form:
>>>>>>>> +  """
>>>>>>>> +  Simple URL parser/constructor, handles URLs of the form:
>>>>>>>> 
>>>>>>>> -      <scheme>://<user>:<password>@<host>:<port>/<path>
>>>>>>>> +    <scheme>://<user>:<password>@<host>:<port>/<path>
>>>>>>>> 
>>>>>>>> -    All components can be None if not specifeid in the URL
>> string.
>>>>>>>> +  All components can be None if not specifeid in the URL
>> string.
>>>>>>>> 
>>>>>>>> -    The port can be specified as a service name, e.g. 'amqp'
>> in
>>>> the
>>>>>>>> -    URL string but Url.port always gives the integer value.
>>>>>>>> +  The port can be specified as a service name, e.g. 'amqp' in
>> the
>>>>>>>> +  URL string but Url.port always gives the integer value.
>>>>>>>> +
>>>>>>>> +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
>>>>>>>> +  @ivar user: Username
>>>>>>>> +  @ivar password: Password
>>>>>>>> +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
>>>>>>>> +  @ivar port: Integer port.
>>>>>>>> +  @ivar host_port: Returns host:port
>>>>>>>> +  """
>>>>>>>> +
>>>>>>>> +  AMQPS = "amqps"
>>>>>>>> +  AMQP = "amqp"
>>>>>>>> +
>>>>>>>> +  class Port(int):
>>>>>>>> +    """An integer port number that can be constructed from a
>>>> service
>>>>>> name
>>>>>>>> string"""
>>>>>>>> +
>>>>>>>> +    def __new__(cls, value):
>>>>>>>> +      port = super(Url.Port, cls).__new__(cls,
>>>> cls.port_int(value))
>>>>>>>> +      setattr(port, 'name', str(value))
>>>>>>>> +      return port
>>>>>>>> +
>>>>>>>> +    def __eq__(self, x): return str(self) == x or int(self)
>> == x
>>>>>>>> +    def __ne__(self, x): return not self == x
>>>>>>>> +    def __str__(self): return str(self.name)
>>>>>>>> +
>>>>>>>> +    @staticmethod
>>>>>>>> +    def port_int(value):
>>>>>>>> +      """Convert service, an integer or a service name, into
>> an
>>>>>> integer
>>>>>>>> port number."""
>>>>>>>> +      try:
>>>>>>>> +        return int(value)
>>>>>>>> +      except ValueError:
>>>>>>>> +        try:
>>>>>>>> +          return socket.getservbyname(value)
>>>>>>>> +        except socket.error:
>>>>>>>> +          raise ValueError("Not a valid port number or service
>>>> name:
>>>>>>>> '%s'" % value)
>>>>>>>> 
>>>>>>>> -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
>>>>>>>> -    @ivar user: Username
>>>>>>>> -    @ivar password: Password
>>>>>>>> -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
>>>>>>>> -    @ivar port: Integer port.
>>>>>>>> -    @ivar host_port: Returns host:port
>>>>>>>> +  def __init__(self, url=None, **kwargs):
>>>>>>>> +    """
>>>>>>>> +    @param url: URL string to parse.
>>>>>>>> +    @param kwargs: scheme, user, password, host, port, path.
>>>>>>>> +      If specified, replaces corresponding part in url string.
>>>>>>>>     """
>>>>>>>> +    if url:
>>>>>>>> +      self._url = pn_url_parse(str(url))
>>>>>>>> +      if not self._url: raise ValueError("Invalid URL '%s'" %
>> url)
>>>>>>>> +    else:
>>>>>>>> +      self._url = pn_url()
>>>>>>>> +    for k in kwargs:            # Let kwargs override values
>>>> parsed
>>>>>> from
>>>>>>>> url
>>>>>>>> +      getattr(self, k)          # Check for invalid kwargs
>>>>>>>> +      setattr(self, k, kwargs[k])
>>>>>>>> +
>>>>>>>> +  class PartDescriptor(object):
>>>>>>>> +    def __init__(self, part):
>>>>>>>> +      self.getter = globals()["pn_url_%s" % part]
>>>>>>>> +      self.setter = globals()["pn_url_set_%s" % part]
>>>>>>>> +    def __get__(self, obj, type=None): return
>>>> self.getter(obj._url)
>>>>>>>> +    def __set__(self, obj, value): return
>> self.setter(obj._url,
>>>>>>>> str(value))
>>>>>>>> +
>>>>>>>> +  scheme = PartDescriptor('scheme')
>>>>>>>> +  username = PartDescriptor('username')
>>>>>>>> +  password = PartDescriptor('password')
>>>>>>>> +  host = PartDescriptor('host')
>>>>>>>> +  path = PartDescriptor('path')
>>>>>>>> +
>>>>>>>> +  @property
>>>>>>>> +  def port(self):
>>>>>>>> +    portstr = pn_url_port(self._url)
>>>>>>>> +    return portstr and Url.Port(portstr)
>>>>>>>> +
>>>>>>>> +  @port.setter
>>>>>>>> +  def port(self, value):
>>>>>>>> +    if value is None: pn_url_set_port(self._url, None)
>>>>>>>> +    else: pn_url_set_port(self._url, str(Url.Port(value)))
>>>>>>>> 
>>>>>>>> -    AMQPS = "amqps"
>>>>>>>> -    AMQP = "amqp"
>>>>>>>> +  def __str__(self): return pn_url_str(self._url)
>>>>>>>> 
>>>>>>>> -    class Port(int):
>>>>>>>> -      """An integer port number that can also have an
>> associated
>>>>>> service
>>>>>>>> name string"""
>>>>>>>> +  def __repr__(self): return "Url(%r)" % str(self)
>>>>>>>> 
>>>>>>>> -      def __new__(cls, value):
>>>>>>>> -        port = super(Url.Port, cls).__new__(cls,
>>>> cls.port_int(value))
>>>>>>>> -        setattr(port, 'name', str(value))
>>>>>>>> -        return port
>>>>>>>> -
>>>>>>>> -      def __eq__(self, x): return str(self) == x or int(self)
>> == x
>>>>>>>> -      def __ne__(self, x): return not self == x
>>>>>>>> -      def __str__(self): return str(self.name)
>>>>>>>> -
>>>>>>>> -      @staticmethod
>>>>>>>> -      def port_int(value):
>>>>>>>> -        """Convert service, an integer or a service name,
>> into an
>>>>>> integer
>>>>>>>> port number."""
>>>>>>>> -        try:
>>>>>>>> -          return int(value)
>>>>>>>> -        except ValueError:
>>>>>>>> -          try:
>>>>>>>> -            return socket.getservbyname(value)
>>>>>>>> -          except socket.error:
>>>>>>>> -            raise ValueError("Not a valid port number or
>> service
>>>> name:
>>>>>>>> '%s'" % value)
>>>>>>>> -
>>>>>>>> -    def __init__(self, url=None, **kwargs):
>>>>>>>> -        """
>>>>>>>> -        @param url: String or Url instance to parse or copy.
>>>>>>>> -        @param kwargs: URL fields: scheme, user, password,
>> host,
>>>> port,
>>>>>>>> path.
>>>>>>>> -            If specified, replaces corresponding component in
>> url.
>>>>>>>> -        """
>>>>>>>> -
>>>>>>>> -        fields = ['scheme', 'user', 'password', 'host',
>> 'port',
>>>>>> 'path']
>>>>>>>> -
>>>>>>>> -        for f in fields: setattr(self, f, None)
>>>>>>>> -        for k in kwargs: getattr(self, k) # Check for invalid
>>>> kwargs
>>>>>>>> -
>>>>>>>> -        if isinstance(url, Url): # Copy from another Url
>> instance.
>>>>>>>> -            self.__dict__.update(url.__dict__)
>>>>>>>> -        elif url is not None:   # Parse from url
>>>>>>>> -            parts = pni_parse_url(str(url))
>>>>>>>> -            if not filter(None, parts): raise
>> ValueError("Invalid
>>>> AMQP
>>>>>>>> URL: '%s'" % url)
>>>>>>>> -            self.scheme, self.user, self.password, self.host,
>>>> port,
>>>>>>>> self.path = parts
>>>>>>>> -            if not self.host: self.host = None
>>>>>>>> -            self.port = port and self.Port(port)
>>>>>>>> -
>>>>>>>> -        # Let kwargs override values previously set from url
>>>>>>>> -        for field in fields:
>>>>>>>> -            setattr(self, field, kwargs.get(field,
>> getattr(self,
>>>>>> field)))
>>>>>>>> -
>>>>>>>> -    def __repr__(self):
>>>>>>>> -        return "Url(%r)" % str(self)
>>>>>>>> -
>>>>>>>> -    def __str__(self):
>>>>>>>> -        s = ""
>>>>>>>> -        if self.scheme:
>>>>>>>> -            s += "%s://" % self.scheme
>>>>>>>> -        if self.user:
>>>>>>>> -            s += self.user
>>>>>>>> -        if self.password:
>>>>>>>> -            s += ":%s" % self.password
>>>>>>>> -        if self.user or self.password:
>>>>>>>> -            s += '@'
>>>>>>>> -        if self.host and ':' in self.host:
>>>>>>>> -            s += "[%s]" % self.host
>>>>>>>> -        elif self.host:
>>>>>>>> -            s += self.host
>>>>>>>> -        if self.port:
>>>>>>>> -            s += ":%s" % self.port
>>>>>>>> -        if self.path:
>>>>>>>> -            s += "/%s" % self.path
>>>>>>>> -        return s
>>>>>>>> -
>>>>>>>> -    def __eq__(self, url):
>>>>>>>> -        return \
>>>>>>>> -            self.scheme == url.scheme and \
>>>>>>>> -            self.user == url.user and self.password ==
>>>> url.password
>>>>>> and \
>>>>>>>> -            self.host == url.host and self.port == url.port
>> and \
>>>>>>>> -            self.path == url.path
>>>>>>>> -
>>>>>>>> -    def __ne__(self, url):
>>>>>>>> -        return not self.__eq__(url)
>>>>>>>> -
>>>>>>>> -    def defaults(self):
>>>>>>>> -        """
>>>>>>>> -        Fill in missing values with defaults
>>>>>>>> -        @return: self
>>>>>>>> -        """
>>>>>>>> -        self.scheme = self.scheme or self.AMQP
>>>>>>>> -        self.host = self.host or '0.0.0.0'
>>>>>>>> -        self.port = self.port or self.Port(self.scheme)
>>>>>>>> -        return self
>>>>>>>> +  def defaults(self):
>>>>>>>> +    """
>>>>>>>> +    Fill in missing values (scheme, host or port) with
>> defaults
>>>>>>>> +    @return: self
>>>>>>>> +    """
>>>>>>>> +    self.scheme = self.scheme or self.AMQP
>>>>>>>> +    self.host = self.host or '0.0.0.0'
>>>>>>>> +    self.port = self.port or self.Port(self.scheme)
>>>>>>>> +    return self
>>>>>>>> 
>>>>>>>> Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
>>>>>>>> +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19
>>>> 21:00:50
>>>>>>>> 2014
>>>>>>>> @@ -26,8 +26,8 @@
>>>>>>>> #include <proton/messenger.h>
>>>>>>>> #include <proton/ssl.h>
>>>>>>>> #include <proton/driver_extras.h>
>>>>>>>> -
>>>>>>>> #include <proton/types.h>
>>>>>>>> +#include <proton/url.h>
>>>>>>>> 
>>>>>>>> #include <uuid/uuid.h>
>>>>>>>> %}
>>>>>>>> 
>>>>>>>> Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/include/proton/cproton.i
>> (original)
>>>>>>>> +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri
>> Sep 19
>>>>>>>> 21:00:50 2014
>>>>>>>> @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
>>>>>>>>   pn_delivery_t *pn_cast_pn_delivery(void *x) { return
>>>> (pn_delivery_t
>>>>>> *)
>>>>>>>> x; }
>>>>>>>>   pn_transport_t *pn_cast_pn_transport(void *x) { return
>>>>>> (pn_transport_t
>>>>>>>> *) x; }
>>>>>>>> %}
>>>>>>>> +
>>>>>>>> +%include "proton/url.h"
>>>>>>>> +
>>>>>>>> 
>>>>>>>> Added: qpid/proton/trunk/proton-c/include/proton/url.h
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
>>>>>>>> +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19
>>>> 21:00:50
>>>>>>>> 2014
>>>>>>>> @@ -0,0 +1,83 @@
>>>>>>>> +#ifndef PROTON_URL_H
>>>>>>>> +#define PROTON_URL_H
>>>>>>>> +/*
>>>>>>>> + * 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.
>>>>>>>> + */
>>>>>>>> +
>>>>>>>> +#include <proton/import_export.h>
>>>>>>>> +
>>>>>>>> +/** @file
>>>>>>>> + * URL API for parsing URLs.
>>>>>>>> + *
>>>>>>>> + * @defgroup url URL
>>>>>>>> + * @{
>>>>>>>> + */
>>>>>>>> +
>>>>>>>> +/** A parsed URL */
>>>>>>>> +typedef struct pn_url_t pn_url_t;
>>>>>>>> +
>>>>>>>> +/** Create an empty URL */
>>>>>>>> +PN_EXTERN pn_url_t *pn_url(void);
>>>>>>>> +
>>>>>>>> +/** Parse a string URL as a pn_url_t.
>>>>>>>> + *@param[in] url A URL string.
>>>>>>>> + *@return The parsed pn_url_t or NULL if url is not a valid
>> URL
>>>>>> string.
>>>>>>>> + */
>>>>>>>> +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
>>>>>>>> +
>>>>>>>> +/** Free a URL */
>>>>>>>> +PN_EXTERN void pn_url_free(pn_url_t *url);
>>>>>>>> +
>>>>>>>> +/** Clear the contents of the URL. */
>>>>>>>> +PN_EXTERN void pn_url_clear(pn_url_t *url);
>>>>>>>> +
>>>>>>>> +/** Return the string form of a URL. Owned by the pn_url_t.*/
>>>>>>>> +PN_EXTERN const char *pn_url_str(pn_url_t *url);
>>>>>>>> +
>>>>>>>> +/**
>>>>>>>> + *@name Getters for parts of the URL.
>>>>>>>> + *
>>>>>>>> + *Values belong to the URL. May return NULL if the value is
>> not
>>>> set.
>>>>>>>> + *
>>>>>>>> + *@{
>>>>>>>> + */
>>>>>>>> +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
>>>>>>>> +PN_EXTERN const char *pn_url_username(pn_url_t *url);
>>>>>>>> +PN_EXTERN const char *pn_url_password(pn_url_t *url);
>>>>>>>> +PN_EXTERN const char *pn_url_host(pn_url_t *url);
>>>>>>>> +PN_EXTERN const char *pn_url_port(pn_url_t *url);
>>>>>>>> +PN_EXTERN const char *pn_url_path(pn_url_t *url);
>>>>>>>> +///@}
>>>>>>>> +
>>>>>>>> +/**
>>>>>>>> + *@name Setters for parts of the URL.
>>>>>>>> + *
>>>>>>>> + *Values are copied. Value can be NULL to indicate the part
>> is not
>>>>>> set.
>>>>>>>> + *
>>>>>>>> + *@{
>>>>>>>> + */
>>>>>>>> +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
>>>> *scheme);
>>>>>>>> +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
>>>>>> *username);
>>>>>>>> +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
>>>>>> *password);
>>>>>>>> +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char
>> *host);
>>>>>>>> +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char
>> *port);
>>>>>>>> +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char
>> *path);
>>>>>>>> +///@}
>>>>>>>> +
>>>>>>>> +///@}
>>>>>>>> +#endif
>>>>>>>> 
>>>>>>>> Added: qpid/proton/trunk/proton-c/src/url.c
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/src/url.c (added)
>>>>>>>> +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50
>> 2014
>>>>>>>> @@ -0,0 +1,127 @@
>>>>>>>> +/*
>>>>>>>> + *
>>>>>>>> + * 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.
>>>>>>>> + *
>>>>>>>> + */
>>>>>>>> +
>>>>>>>> +#include <proton/url.h>
>>>>>>>> +#include <proton/util.h>
>>>>>>>> +#include <stdlib.h>
>>>>>>>> +#include <string.h>
>>>>>>>> +#include <stdio.h>
>>>>>>>> +
>>>>>>>> +static char* copy(const char* str) {
>>>>>>>> +    if (str ==  NULL) return NULL;
>>>>>>>> +    char *str2 = (char*)malloc(strlen(str));
>>>>>>>> +    if (str2) strcpy(str2, str);
>>>>>>>> +    return str2;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +struct pn_url_t {
>>>>>>>> +    char *scheme;
>>>>>>>> +    char *username;
>>>>>>>> +    char *password;
>>>>>>>> +    char *host;
>>>>>>>> +    char *port;
>>>>>>>> +    char *path;
>>>>>>>> +    char *str;
>>>>>>>> +};
>>>>>>>> +
>>>>>>>> +PN_EXTERN pn_url_t *pn_url() {
>>>>>>>> +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
>>>>>>>> +    memset(url, 0, sizeof(*url));
>>>>>>>> +    return url;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +/** Parse a string URL as a pn_url_t.
>>>>>>>> + *@param[in] url A URL string.
>>>>>>>> + *@return The parsed pn_url_t or NULL if url is not a valid
>> URL
>>>>>> string.
>>>>>>>> + */
>>>>>>>> +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
>>>>>>>> +    if (!str || !*str)          /* Empty string or NULL is
>>>> illegal. */
>>>>>>>> +        return NULL;
>>>>>>>> +
>>>>>>>> +    pn_url_t *url = pn_url();
>>>>>>>> +    char *str2 = copy(str);         /* FIXME aconway
>> 2014-09-19:
>>>>>> clean up
>>>>>>>> */
>>>>>>>> +    pni_parse_url(str2, &url->scheme, &url->username,
>>>> &url->password,
>>>>>>>> &url->host, &url->port, &url->path);
>>>>>>>> +    url->scheme = copy(url->scheme);
>>>>>>>> +    url->username = copy(url->username);
>>>>>>>> +    url->password = copy(url->password);
>>>>>>>> +    url->host = (url->host && !*url->host) ? NULL :
>>>> copy(url->host);
>>>>>>>> +    url->port = copy(url->port);
>>>>>>>> +    url->path = copy(url->path);
>>>>>>>> +    return url;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +/** Free a URL */
>>>>>>>> +PN_EXTERN void pn_url_free(pn_url_t *url) {
>>>>>>>> +    pn_url_clear(url);
>>>>>>>> +    free(url);
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +/** Clear the contents of the URL. */
>>>>>>>> +PN_EXTERN void pn_url_clear(pn_url_t *url) {
>>>>>>>> +    pn_url_set_username(url, NULL);
>>>>>>>> +    pn_url_set_password(url, NULL);
>>>>>>>> +    pn_url_set_host(url, NULL);
>>>>>>>> +    pn_url_set_port(url, NULL);
>>>>>>>> +    pn_url_set_path(url, NULL);
>>>>>>>> +    free(url->str); url->str = NULL;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +static inline int len(const char *str) { return str ?
>> strlen(str)
>>>> :
>>>>>> 0; }
>>>>>>>> +
>>>>>>>> +/** Return the string form of a URL. */
>>>>>>>> +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
>>>>>>>> +    int size = len(url->scheme) + len(url->username) +
>>>>>> len(url->password)
>>>>>>>> +        + len(url->host) + len(url->port) + len(url->path)
>>>>>>>> +        + len("s://u:p@[h]:p/p");
>>>>>>>> +    free(url->str);
>>>>>>>> +    url->str = (char*)malloc(size);
>>>>>>>> +    if (!url->str) return NULL;
>>>>>>>> +
>>>>>>>> +    int i = 0;
>>>>>>>> +    if (url->scheme) i += snprintf(url->str+i, size-i,
>> "%s://",
>>>>>>>> url->scheme);
>>>>>>>> +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
>>>>>>>> url->username);
>>>>>>>> +    if (url->password) i += snprintf(url->str+i, size-i,
>> ":%s",
>>>>>>>> url->password);
>>>>>>>> +    if (url->username || url->password) i +=
>> snprintf(url->str+i,
>>>>>> size-i,
>>>>>>>> "@");
>>>>>>>> +    if (url->host) {
>>>>>>>> +        if (strchr(url->host, ':')) i += snprintf(url->str+i,
>>>> size-i,
>>>>>>>> "[%s]", url->host);
>>>>>>>> +        else i += snprintf(url->str+i, size-i, "%s",
>> url->host);
>>>>>>>> +    }
>>>>>>>> +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
>>>>>> url->port);
>>>>>>>> +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
>>>>>> url->path);
>>>>>>>> +    return url->str;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
>>>>>> url->scheme; }
>>>>>>>> +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
>>>>>>>> url->username; }
>>>>>>>> +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
>>>>>>>> url->password; }
>>>>>>>> +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return
>>>> url->host; }
>>>>>>>> +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return
>>>> url->port; }
>>>>>>>> +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return
>>>> url->path; }
>>>>>>>> +
>>>>>>>> +#define SET(part) free(url->part); url->part = copy(part)
>>>>>>>> +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
>>>> *scheme) {
>>>>>>>> SET(scheme); }
>>>>>>>> +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
>>>>>> *username) {
>>>>>>>> SET(username); }
>>>>>>>> +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
>>>>>> *password) {
>>>>>>>> SET(password); }
>>>>>>>> +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char
>> *host) {
>>>>>>>> SET(host); }
>>>>>>>> +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char
>> *port) {
>>>>>>>> SET(port); }
>>>>>>>> +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char
>> *path) {
>>>>>>>> SET(path); }
>>>>>>>> +
>>>>>>>> +
>>>>>>>> 
>>>>>>>> Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/tests/python/proton_tests/url.py
>> (original)
>>>>>>>> +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep
>> 19
>>>>>> 21:00:50
>>>>>>>> 2014
>>>>>>>> @@ -28,9 +28,9 @@ class UrlTest(common.Test):
>>>>>>>>     def assertNotEqual(self, a, b):
>>>>>>>>         assert a != b, "%s == %s" % (a, b)
>>>>>>>> 
>>>>>>>> -    def assertUrl(self, u, scheme, user, password, host, port,
>>>> path):
>>>>>>>> -        self.assertEqual((u.scheme, u.user, u.password,
>> u.host,
>>>>>> u.port,
>>>>>>>> u.path),
>>>>>>>> -                         (scheme, user, password, host, port,
>>>> path))
>>>>>>>> +    def assertUrl(self, u, scheme, username, password, host,
>> port,
>>>>>> path):
>>>>>>>> +        self.assertEqual((u.scheme, u.username, u.password,
>>>> u.host,
>>>>>>>> u.port, u.path),
>>>>>>>> +                         (scheme, username, password, host,
>> port,
>>>>>> path))
>>>>>>>> 
>>>>>>>>     def testUrl(self):
>>>>>>>>         url = Url('amqp://me:secret@myhost:1234/foobar')
>>>>>>>> @@ -40,7 +40,7 @@ class UrlTest(common.Test):
>>>>>>>> 
>>>>>>>>     def testDefaults(self):
>>>>>>>>         # Check that we allow None for scheme, port
>>>>>>>> -        url = Url(user='me', password='secret', host='myhost',
>>>>>>>> path='foobar')
>>>>>>>> +        url = Url(username='me', password='secret',
>> host='myhost',
>>>>>>>> path='foobar')
>>>>>>>>         self.assertEqual(str(url), "me:secret@myhost/foobar")
>>>>>>>>         self.assertUrl(url, None, 'me', 'secret', 'myhost',
>> None,
>>>>>>>> 'foobar')
>>>>>>>> 
>>>>>>>> @@ -97,21 +97,19 @@ class UrlTest(common.Test):
>>>>>>>>     def testMissing(self):
>>>>>>>>         self.assertUrl(Url(), None, None, None, None, None,
>> None)
>>>>>>>>         self.assertUrl(Url('amqp://'), 'amqp', None, None,
>> None,
>>>> None,
>>>>>>>> None)
>>>>>>>> -        self.assertUrl(Url('user@'), None, 'user', None,
>> None,
>>>> None,
>>>>>>>> None)
>>>>>>>> +        self.assertUrl(Url('username@'), None, 'username',
>> None,
>>>>>> None,
>>>>>>>> None, None)
>>>>>>>>         self.assertUrl(Url(':pass@'), None, '', 'pass', None,
>>>> None,
>>>>>> None)
>>>>>>>>         self.assertUrl(Url('host'), None, None, None, 'host',
>>>> None,
>>>>>> None)
>>>>>>>>         self.assertUrl(Url(':1234'), None, None, None, None,
>> 1234,
>>>>>> None)
>>>>>>>>         self.assertUrl(Url('/path'), None, None, None, None,
>> None,
>>>>>> 'path')
>>>>>>>> 
>>>>>>>> -        for s in ['amqp://', 'user@', ':pass@', ':1234',
>>>> '/path']:
>>>>>>>> +        for s in ['amqp://', 'username@', ':pass@', ':1234',
>>>>>> '/path']:
>>>>>>>>             self.assertEqual(s, str(Url(s)))
>>>>>>>> 
>>>>>>>>         for s, full in [
>>>>>>>>                 ('amqp://', 'amqp://0.0.0.0:amqp'),
>>>>>>>> -                ('user@', 'amqp://user@0.0.0.0:amqp'),
>>>>>>>> +                ('username@', 'amqp://username@0.0.0.0:
>> amqp'),
>>>>>>>>                 (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
>>>>>>>>                 (':1234', 'amqp://0.0.0.0:1234'),
>>>>>>>>                 ('/path', 'amqp://0.0.0.0:amqp/path')]:
>>>>>>>>             self.assertEqual(str(Url(s).defaults()), full)
>>>>>>>> -
>>>>>>>> -        self.assertRaises(ValueError, Url, '')
>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>> ---------------------------------------------------------------------
>>>>>>>> To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
>>>>>>>> For additional commands, e-mail: commits-help@qpid.apache.org
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 
>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
>>>>>> For additional commands, e-mail: dev-help@qpid.apache.org
>>>>>> 
>>>>>> 
>>>> 
>>>> 
>>>> 
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
>>>> For additional commands, e-mail: dev-help@qpid.apache.org
>>>> 
>>>> 
>> 
>> 
>> 
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
>> For additional commands, e-mail: dev-help@qpid.apache.org
>> 
>> 


Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Clebert Suconic <cs...@redhat.com>.
This is also failing for me when I run the entire mvn install (after a mvn clean).. it's not just on the CI for me



On Sep 25, 2014, at 2:20 PM, Robbie Gemmell <ro...@gmail.com> wrote:

> Failing in a different way now, the overall run of the python tests bombs
> out. I see the same thing locally, where it was working when I made the
> commit immediately before yours :)
> 
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/683/console
> 
> Running org.apache.qpid.proton.JythonTest
> Sep 25, 2014 6:03:44 PM org.apache.qpid.proton.JythonTest test
> INFO: About to call Jython test script:
> '/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test'
> with '/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python'
> added to Jython path
> Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 7.714
> sec <<< FAILURE!
> test(org.apache.qpid.proton.JythonTest)  Time elapsed: 7.675 sec  <<< FAILURE!
> java.lang.AssertionError: Caught PyException on invocation number 2:
> Traceback (most recent call last):
>  File "/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test",
> line 597, in <module>
>    h.scan(m)
>  File "/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test",
> line 587, in scan
>    if not (child in self.scanned or child in objects):
> TypeError: object of type 'object' has no len()
> with message: null
> 	at org.junit.Assert.fail(Assert.java:93)
> 	at org.apache.qpid.proton.JythonTest.runTestOnce(JythonTest.java:120)
> 	at org.apache.qpid.proton.JythonTest.test(JythonTest.java:95)
> 
> 
> On 25 September 2014 18:59, Alan Conway <ac...@redhat.com> wrote:
> 
>> On Thu, 2014-09-25 at 15:59 +0100, Robbie Gemmell wrote:
>>> On 25 September 2014 15:00, Alan Conway <ac...@redhat.com> wrote:
>>> 
>>>> On Wed, 2014-09-24 at 12:19 +0100, Robbie Gemmell wrote:
>>>>> The tests are now running again, but a couple of the URL tests still
>> seem
>>>>> to be failing on the CI job:
>>>>> 
>>>> 
>> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/
>>>>> 
>>>> 
>>>> They are all failing with:
>>>> Not a valid port number or service name: 'amqps'
>>>> 
>>>> Could this be a configuration problem on the CI machine, i.e. missing
>> an
>>>> 'amqps' entry in /etc/services? Can I get access to the CI machine to
>>>> poke around and see what's up?
>>>> 
>>> 
>>> Almost certainly no, only the core maintainers are allowed shell access
>> as
>>> far as I've seen. You can ask on builds@apache.org for those with
>> access to
>>> check things out and report back and see what happens.
>>> 
>>> I think the CI instances will be running Ubuntu 12.04 or 14.04 LTS. For
>>> giggles, I dug out an ooooold Ubuntu VM with Java 6 on it and tried the
>>> tests, which failed, and it indeed has no amqp[s] entry in /etc/services
>>> file so that could well be it.
>> 
>> Thanks for checking that out! I have hacked the tests to skip tests for
>> 'amqps' if it is not recognized. Poke me if there are still failures.
>> 
>> ------------------------------------------------------------------------
>> r1627577 | aconway | 2014-09-25 13:59:17 -0400 (Thu, 25 Sep 2014) | 5
>> lines
>> 
>> NO-JIRA: Fix URL test to skip 'amqps' tests if 'amqps' is not recognized
>> as a service name.
>> 
>> On some older Ubuntu with Java 6, 'amqps' is not recognized as a service
>> name so
>> skip those tests in that case.
>> 
>> ------------------------------------------------------------------------
>> 
>>>> 
>>>> The URL code uses socket.getservbyname() to look up service names. Is
>>>> there a more portable way to do it?
>>>> 
>>> 
>>> No idea I'm afraid.
>>> 
>>> 
>>>> 
>>>> Cheers,
>>>> Alan.
>>>> 
>>>>> As mentioned in my other post about a timeline for dropping Java6
>>>> support,
>>>>> they seem to work on Java8 (havent tried Java7).
>>>>> 
>>>>> Robbie
>>>>> 
>>>>> On 22 September 2014 21:14, Alan Conway <ac...@redhat.com> wrote:
>>>>> 
>>>>>> My bad, didn't run the java tests. Will fix ASAP and then give
>> myself a
>>>>>> flogging.
>>>>>> 
>>>>>> On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
>>>>>>> This seems to have broken the Java test runs:
>>>>>>> 
>>>>>>> 
>> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
>>>>>>> 
>>>>>>> 
>>>>>>> 
>>>>>>> On 19 September 2014 22:00, <ac...@apache.org> wrote:
>>>>>>> 
>>>>>>>> Author: aconway
>>>>>>>> Date: Fri Sep 19 21:00:50 2014
>>>>>>>> New Revision: 1626329
>>>>>>>> 
>>>>>>>> URL: http://svn.apache.org/r1626329
>>>>>>>> Log:
>>>>>>>> PROTON-693: Python Url class to wrap C function pni_parse_url
>>>>>>>> 
>>>>>>>> It was pointed out that pni_parse_url is an internal function
>> and
>>>> the
>>>>>>>> interface
>>>>>>>> is not suitable for public API.
>>>>>>>> 
>>>>>>>> Rewrote the URL parser as a proper swigable C API pn_url_*.
>> This
>>>> gets
>>>>>> rid
>>>>>>>> of the
>>>>>>>> need for previous swig insanity and is cleaner all round.
>>>>>>>> 
>>>>>>>> Internally still uses the pni_parse_url parser, we can clean
>> that
>>>> up
>>>>>> later.
>>>>>>>> 
>>>>>>>> Added:
>>>>>>>>    qpid/proton/trunk/proton-c/include/proton/url.h
>>>>>>>>    qpid/proton/trunk/proton-c/src/url.c
>>>>>>>> Modified:
>>>>>>>>    qpid/proton/trunk/proton-c/CMakeLists.txt
>>>>>>>>    qpid/proton/trunk/proton-c/bindings/perl/perl.i
>>>>>>>>    qpid/proton/trunk/proton-c/bindings/php/php.i
>>>>>>>>    qpid/proton/trunk/proton-c/bindings/python/cproton.i
>>>>>>>>    qpid/proton/trunk/proton-c/bindings/python/proton.py
>>>>>>>>    qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
>>>>>>>>    qpid/proton/trunk/proton-c/include/proton/cproton.i
>>>>>>>>    qpid/proton/trunk/tests/python/proton_tests/url.py
>>>>>>>> 
>>>>>>>> Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
>>>>>>>> +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19
>> 21:00:50
>>>> 2014
>>>>>>>> @@ -270,6 +270,7 @@ set (qpid-proton-core
>>>>>>>>   src/object/iterator.c
>>>>>>>> 
>>>>>>>>   src/util.c
>>>>>>>> +  src/url.c
>>>>>>>>   src/error.c
>>>>>>>>   src/buffer.c
>>>>>>>>   src/parser.c
>>>>>>>> 
>>>>>>>> Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
>>>>>>>> +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19
>>>> 21:00:50
>>>>>>>> 2014
>>>>>>>> @@ -8,6 +8,7 @@
>>>>>>>> #include <proton/messenger.h>
>>>>>>>> #include <proton/ssl.h>
>>>>>>>> #include <proton/driver_extras.h>
>>>>>>>> +#include <proton/url.h>
>>>>>>>> %}
>>>>>>>> 
>>>>>>>> %include <cstring.i>
>>>>>>>> 
>>>>>>>> Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
>>>>>>>> +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19
>>>> 21:00:50
>>>>>> 2014
>>>>>>>> @@ -29,6 +29,7 @@
>>>>>>>> %header %{
>>>>>>>> /* Include the headers needed by the code in this wrapper
>> file */
>>>>>>>> #include <proton/types.h>
>>>>>>>> +#include <proton/url.h>
>>>>>>>> #include <proton/message.h>
>>>>>>>> #include <proton/driver.h>
>>>>>>>> #include <proton/driver_extras.h>
>>>>>>>> 
>>>>>>>> Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/bindings/python/cproton.i
>> (original)
>>>>>>>> +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri
>> Sep 19
>>>>>>>> 21:00:50 2014
>>>>>>>> @@ -23,6 +23,7 @@
>>>>>>>> #include <winsock2.h>
>>>>>>>> #endif
>>>>>>>> #include <proton/engine.h>
>>>>>>>> +#include <proton/url.h>
>>>>>>>> #include <proton/message.h>
>>>>>>>> #include <proton/sasl.h>
>>>>>>>> #include <proton/driver.h>
>>>>>>>> @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
>>>>>>>>   }
>>>>>>>> %}
>>>>>>>> 
>>>>>>>> -
>>>>>>>> -/**
>>>>>>>> -   pni_parse_url(char* url, char **scheme, char **user, char
>>>> **pass,
>>>>>> char
>>>>>>>> **host, char **port, char **path)
>>>>>>>> -   The following type maps convert this into a python function
>>>> that
>>>>>> taks
>>>>>>>> a URL string argument
>>>>>>>> -   and returns a list of strings [scheme, user, pass, host,
>> port,
>>>>>> path]
>>>>>>>> -   This probably could be done more neatly.
>>>>>>>> -*/
>>>>>>>> -
>>>>>>>> -// Typemap to copy the url string as it will be modified by
>>>> parse_url
>>>>>>>> -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char
>> *url
>>>> (int
>>>>>>>> res, char *t = 0, size_t n = 0, int alloc = 0) {
>>>>>>>> -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
>>>>>>>> -  if (!SWIG_IsOK(res)) {
>>>>>>>> -    %argument_fail(res, "char *url", $symname, $argnum);
>>>>>>>> -  }
>>>>>>>> -  $1 = %new_array(n, $*1_ltype);
>>>>>>>> -  memcpy($1,t,sizeof(char)*n);
>>>>>>>> -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
>>>>>>>> -  $1[n-1] = 0;
>>>>>>>> -}
>>>>>>>> -%typemap(freearg,match="in") char *url "free($1);";
>>>>>>>> -%typemap(argout) char *url "";
>>>>>>>> -
>>>>>>>> -// Typemap for char** return strings. Don't free them.
>>>>>>>> -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0)
>> "$1 =
>>>>>> &temp;";
>>>>>>>> -%typemap(freearg,match="in") char **OUTSTR "";
>>>>>>>> -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char
>>>> **OUTSTR {
>>>>>>>> -    %append_output(SWIG_FromCharPtr(*$1));
>>>>>>>> -}
>>>>>>>> -
>>>>>>>> -// Typemap to initialize result as empty list
>>>>>>>> -%typemap(out) void "$result = PyList_New(0);";
>>>>>>>> -
>>>>>>>> -
>>>>>>>> -%apply char** OUTSTR {char **scheme, char **user, char **pass,
>>>> char
>>>>>>>> **host, char **port, char **path};
>>>>>>>> -void pni_parse_url(char* url, char **scheme, char **user, char
>>>> **pass,
>>>>>>>> char **host, char **port, char **path);
>>>>>>>> -%ignore pni_parse_url;
>>>>>>>> -
>>>>>>>> %include "proton/cproton.i"
>>>>>>>> 
>>>>>>>> Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/bindings/python/proton.py
>> (original)
>>>>>>>> +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri
>> Sep 19
>>>>>>>> 21:00:50 2014
>>>>>>>> @@ -3657,114 +3657,98 @@ __all__ = [
>>>>>>>> 
>>>>>>>> 
>>>>>>>> class Url(object):
>>>>>>>> -    """
>>>>>>>> -    Simple URL parser/constructor, handles URLs of the form:
>>>>>>>> +  """
>>>>>>>> +  Simple URL parser/constructor, handles URLs of the form:
>>>>>>>> 
>>>>>>>> -      <scheme>://<user>:<password>@<host>:<port>/<path>
>>>>>>>> +    <scheme>://<user>:<password>@<host>:<port>/<path>
>>>>>>>> 
>>>>>>>> -    All components can be None if not specifeid in the URL
>> string.
>>>>>>>> +  All components can be None if not specifeid in the URL
>> string.
>>>>>>>> 
>>>>>>>> -    The port can be specified as a service name, e.g. 'amqp'
>> in
>>>> the
>>>>>>>> -    URL string but Url.port always gives the integer value.
>>>>>>>> +  The port can be specified as a service name, e.g. 'amqp' in
>> the
>>>>>>>> +  URL string but Url.port always gives the integer value.
>>>>>>>> +
>>>>>>>> +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
>>>>>>>> +  @ivar user: Username
>>>>>>>> +  @ivar password: Password
>>>>>>>> +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
>>>>>>>> +  @ivar port: Integer port.
>>>>>>>> +  @ivar host_port: Returns host:port
>>>>>>>> +  """
>>>>>>>> +
>>>>>>>> +  AMQPS = "amqps"
>>>>>>>> +  AMQP = "amqp"
>>>>>>>> +
>>>>>>>> +  class Port(int):
>>>>>>>> +    """An integer port number that can be constructed from a
>>>> service
>>>>>> name
>>>>>>>> string"""
>>>>>>>> +
>>>>>>>> +    def __new__(cls, value):
>>>>>>>> +      port = super(Url.Port, cls).__new__(cls,
>>>> cls.port_int(value))
>>>>>>>> +      setattr(port, 'name', str(value))
>>>>>>>> +      return port
>>>>>>>> +
>>>>>>>> +    def __eq__(self, x): return str(self) == x or int(self)
>> == x
>>>>>>>> +    def __ne__(self, x): return not self == x
>>>>>>>> +    def __str__(self): return str(self.name)
>>>>>>>> +
>>>>>>>> +    @staticmethod
>>>>>>>> +    def port_int(value):
>>>>>>>> +      """Convert service, an integer or a service name, into
>> an
>>>>>> integer
>>>>>>>> port number."""
>>>>>>>> +      try:
>>>>>>>> +        return int(value)
>>>>>>>> +      except ValueError:
>>>>>>>> +        try:
>>>>>>>> +          return socket.getservbyname(value)
>>>>>>>> +        except socket.error:
>>>>>>>> +          raise ValueError("Not a valid port number or service
>>>> name:
>>>>>>>> '%s'" % value)
>>>>>>>> 
>>>>>>>> -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
>>>>>>>> -    @ivar user: Username
>>>>>>>> -    @ivar password: Password
>>>>>>>> -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
>>>>>>>> -    @ivar port: Integer port.
>>>>>>>> -    @ivar host_port: Returns host:port
>>>>>>>> +  def __init__(self, url=None, **kwargs):
>>>>>>>> +    """
>>>>>>>> +    @param url: URL string to parse.
>>>>>>>> +    @param kwargs: scheme, user, password, host, port, path.
>>>>>>>> +      If specified, replaces corresponding part in url string.
>>>>>>>>     """
>>>>>>>> +    if url:
>>>>>>>> +      self._url = pn_url_parse(str(url))
>>>>>>>> +      if not self._url: raise ValueError("Invalid URL '%s'" %
>> url)
>>>>>>>> +    else:
>>>>>>>> +      self._url = pn_url()
>>>>>>>> +    for k in kwargs:            # Let kwargs override values
>>>> parsed
>>>>>> from
>>>>>>>> url
>>>>>>>> +      getattr(self, k)          # Check for invalid kwargs
>>>>>>>> +      setattr(self, k, kwargs[k])
>>>>>>>> +
>>>>>>>> +  class PartDescriptor(object):
>>>>>>>> +    def __init__(self, part):
>>>>>>>> +      self.getter = globals()["pn_url_%s" % part]
>>>>>>>> +      self.setter = globals()["pn_url_set_%s" % part]
>>>>>>>> +    def __get__(self, obj, type=None): return
>>>> self.getter(obj._url)
>>>>>>>> +    def __set__(self, obj, value): return
>> self.setter(obj._url,
>>>>>>>> str(value))
>>>>>>>> +
>>>>>>>> +  scheme = PartDescriptor('scheme')
>>>>>>>> +  username = PartDescriptor('username')
>>>>>>>> +  password = PartDescriptor('password')
>>>>>>>> +  host = PartDescriptor('host')
>>>>>>>> +  path = PartDescriptor('path')
>>>>>>>> +
>>>>>>>> +  @property
>>>>>>>> +  def port(self):
>>>>>>>> +    portstr = pn_url_port(self._url)
>>>>>>>> +    return portstr and Url.Port(portstr)
>>>>>>>> +
>>>>>>>> +  @port.setter
>>>>>>>> +  def port(self, value):
>>>>>>>> +    if value is None: pn_url_set_port(self._url, None)
>>>>>>>> +    else: pn_url_set_port(self._url, str(Url.Port(value)))
>>>>>>>> 
>>>>>>>> -    AMQPS = "amqps"
>>>>>>>> -    AMQP = "amqp"
>>>>>>>> +  def __str__(self): return pn_url_str(self._url)
>>>>>>>> 
>>>>>>>> -    class Port(int):
>>>>>>>> -      """An integer port number that can also have an
>> associated
>>>>>> service
>>>>>>>> name string"""
>>>>>>>> +  def __repr__(self): return "Url(%r)" % str(self)
>>>>>>>> 
>>>>>>>> -      def __new__(cls, value):
>>>>>>>> -        port = super(Url.Port, cls).__new__(cls,
>>>> cls.port_int(value))
>>>>>>>> -        setattr(port, 'name', str(value))
>>>>>>>> -        return port
>>>>>>>> -
>>>>>>>> -      def __eq__(self, x): return str(self) == x or int(self)
>> == x
>>>>>>>> -      def __ne__(self, x): return not self == x
>>>>>>>> -      def __str__(self): return str(self.name)
>>>>>>>> -
>>>>>>>> -      @staticmethod
>>>>>>>> -      def port_int(value):
>>>>>>>> -        """Convert service, an integer or a service name,
>> into an
>>>>>> integer
>>>>>>>> port number."""
>>>>>>>> -        try:
>>>>>>>> -          return int(value)
>>>>>>>> -        except ValueError:
>>>>>>>> -          try:
>>>>>>>> -            return socket.getservbyname(value)
>>>>>>>> -          except socket.error:
>>>>>>>> -            raise ValueError("Not a valid port number or
>> service
>>>> name:
>>>>>>>> '%s'" % value)
>>>>>>>> -
>>>>>>>> -    def __init__(self, url=None, **kwargs):
>>>>>>>> -        """
>>>>>>>> -        @param url: String or Url instance to parse or copy.
>>>>>>>> -        @param kwargs: URL fields: scheme, user, password,
>> host,
>>>> port,
>>>>>>>> path.
>>>>>>>> -            If specified, replaces corresponding component in
>> url.
>>>>>>>> -        """
>>>>>>>> -
>>>>>>>> -        fields = ['scheme', 'user', 'password', 'host',
>> 'port',
>>>>>> 'path']
>>>>>>>> -
>>>>>>>> -        for f in fields: setattr(self, f, None)
>>>>>>>> -        for k in kwargs: getattr(self, k) # Check for invalid
>>>> kwargs
>>>>>>>> -
>>>>>>>> -        if isinstance(url, Url): # Copy from another Url
>> instance.
>>>>>>>> -            self.__dict__.update(url.__dict__)
>>>>>>>> -        elif url is not None:   # Parse from url
>>>>>>>> -            parts = pni_parse_url(str(url))
>>>>>>>> -            if not filter(None, parts): raise
>> ValueError("Invalid
>>>> AMQP
>>>>>>>> URL: '%s'" % url)
>>>>>>>> -            self.scheme, self.user, self.password, self.host,
>>>> port,
>>>>>>>> self.path = parts
>>>>>>>> -            if not self.host: self.host = None
>>>>>>>> -            self.port = port and self.Port(port)
>>>>>>>> -
>>>>>>>> -        # Let kwargs override values previously set from url
>>>>>>>> -        for field in fields:
>>>>>>>> -            setattr(self, field, kwargs.get(field,
>> getattr(self,
>>>>>> field)))
>>>>>>>> -
>>>>>>>> -    def __repr__(self):
>>>>>>>> -        return "Url(%r)" % str(self)
>>>>>>>> -
>>>>>>>> -    def __str__(self):
>>>>>>>> -        s = ""
>>>>>>>> -        if self.scheme:
>>>>>>>> -            s += "%s://" % self.scheme
>>>>>>>> -        if self.user:
>>>>>>>> -            s += self.user
>>>>>>>> -        if self.password:
>>>>>>>> -            s += ":%s" % self.password
>>>>>>>> -        if self.user or self.password:
>>>>>>>> -            s += '@'
>>>>>>>> -        if self.host and ':' in self.host:
>>>>>>>> -            s += "[%s]" % self.host
>>>>>>>> -        elif self.host:
>>>>>>>> -            s += self.host
>>>>>>>> -        if self.port:
>>>>>>>> -            s += ":%s" % self.port
>>>>>>>> -        if self.path:
>>>>>>>> -            s += "/%s" % self.path
>>>>>>>> -        return s
>>>>>>>> -
>>>>>>>> -    def __eq__(self, url):
>>>>>>>> -        return \
>>>>>>>> -            self.scheme == url.scheme and \
>>>>>>>> -            self.user == url.user and self.password ==
>>>> url.password
>>>>>> and \
>>>>>>>> -            self.host == url.host and self.port == url.port
>> and \
>>>>>>>> -            self.path == url.path
>>>>>>>> -
>>>>>>>> -    def __ne__(self, url):
>>>>>>>> -        return not self.__eq__(url)
>>>>>>>> -
>>>>>>>> -    def defaults(self):
>>>>>>>> -        """
>>>>>>>> -        Fill in missing values with defaults
>>>>>>>> -        @return: self
>>>>>>>> -        """
>>>>>>>> -        self.scheme = self.scheme or self.AMQP
>>>>>>>> -        self.host = self.host or '0.0.0.0'
>>>>>>>> -        self.port = self.port or self.Port(self.scheme)
>>>>>>>> -        return self
>>>>>>>> +  def defaults(self):
>>>>>>>> +    """
>>>>>>>> +    Fill in missing values (scheme, host or port) with
>> defaults
>>>>>>>> +    @return: self
>>>>>>>> +    """
>>>>>>>> +    self.scheme = self.scheme or self.AMQP
>>>>>>>> +    self.host = self.host or '0.0.0.0'
>>>>>>>> +    self.port = self.port or self.Port(self.scheme)
>>>>>>>> +    return self
>>>>>>>> 
>>>>>>>> Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
>>>>>>>> +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19
>>>> 21:00:50
>>>>>>>> 2014
>>>>>>>> @@ -26,8 +26,8 @@
>>>>>>>> #include <proton/messenger.h>
>>>>>>>> #include <proton/ssl.h>
>>>>>>>> #include <proton/driver_extras.h>
>>>>>>>> -
>>>>>>>> #include <proton/types.h>
>>>>>>>> +#include <proton/url.h>
>>>>>>>> 
>>>>>>>> #include <uuid/uuid.h>
>>>>>>>> %}
>>>>>>>> 
>>>>>>>> Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/include/proton/cproton.i
>> (original)
>>>>>>>> +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri
>> Sep 19
>>>>>>>> 21:00:50 2014
>>>>>>>> @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
>>>>>>>>   pn_delivery_t *pn_cast_pn_delivery(void *x) { return
>>>> (pn_delivery_t
>>>>>> *)
>>>>>>>> x; }
>>>>>>>>   pn_transport_t *pn_cast_pn_transport(void *x) { return
>>>>>> (pn_transport_t
>>>>>>>> *) x; }
>>>>>>>> %}
>>>>>>>> +
>>>>>>>> +%include "proton/url.h"
>>>>>>>> +
>>>>>>>> 
>>>>>>>> Added: qpid/proton/trunk/proton-c/include/proton/url.h
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
>>>>>>>> +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19
>>>> 21:00:50
>>>>>>>> 2014
>>>>>>>> @@ -0,0 +1,83 @@
>>>>>>>> +#ifndef PROTON_URL_H
>>>>>>>> +#define PROTON_URL_H
>>>>>>>> +/*
>>>>>>>> + * 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.
>>>>>>>> + */
>>>>>>>> +
>>>>>>>> +#include <proton/import_export.h>
>>>>>>>> +
>>>>>>>> +/** @file
>>>>>>>> + * URL API for parsing URLs.
>>>>>>>> + *
>>>>>>>> + * @defgroup url URL
>>>>>>>> + * @{
>>>>>>>> + */
>>>>>>>> +
>>>>>>>> +/** A parsed URL */
>>>>>>>> +typedef struct pn_url_t pn_url_t;
>>>>>>>> +
>>>>>>>> +/** Create an empty URL */
>>>>>>>> +PN_EXTERN pn_url_t *pn_url(void);
>>>>>>>> +
>>>>>>>> +/** Parse a string URL as a pn_url_t.
>>>>>>>> + *@param[in] url A URL string.
>>>>>>>> + *@return The parsed pn_url_t or NULL if url is not a valid
>> URL
>>>>>> string.
>>>>>>>> + */
>>>>>>>> +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
>>>>>>>> +
>>>>>>>> +/** Free a URL */
>>>>>>>> +PN_EXTERN void pn_url_free(pn_url_t *url);
>>>>>>>> +
>>>>>>>> +/** Clear the contents of the URL. */
>>>>>>>> +PN_EXTERN void pn_url_clear(pn_url_t *url);
>>>>>>>> +
>>>>>>>> +/** Return the string form of a URL. Owned by the pn_url_t.*/
>>>>>>>> +PN_EXTERN const char *pn_url_str(pn_url_t *url);
>>>>>>>> +
>>>>>>>> +/**
>>>>>>>> + *@name Getters for parts of the URL.
>>>>>>>> + *
>>>>>>>> + *Values belong to the URL. May return NULL if the value is
>> not
>>>> set.
>>>>>>>> + *
>>>>>>>> + *@{
>>>>>>>> + */
>>>>>>>> +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
>>>>>>>> +PN_EXTERN const char *pn_url_username(pn_url_t *url);
>>>>>>>> +PN_EXTERN const char *pn_url_password(pn_url_t *url);
>>>>>>>> +PN_EXTERN const char *pn_url_host(pn_url_t *url);
>>>>>>>> +PN_EXTERN const char *pn_url_port(pn_url_t *url);
>>>>>>>> +PN_EXTERN const char *pn_url_path(pn_url_t *url);
>>>>>>>> +///@}
>>>>>>>> +
>>>>>>>> +/**
>>>>>>>> + *@name Setters for parts of the URL.
>>>>>>>> + *
>>>>>>>> + *Values are copied. Value can be NULL to indicate the part
>> is not
>>>>>> set.
>>>>>>>> + *
>>>>>>>> + *@{
>>>>>>>> + */
>>>>>>>> +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
>>>> *scheme);
>>>>>>>> +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
>>>>>> *username);
>>>>>>>> +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
>>>>>> *password);
>>>>>>>> +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char
>> *host);
>>>>>>>> +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char
>> *port);
>>>>>>>> +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char
>> *path);
>>>>>>>> +///@}
>>>>>>>> +
>>>>>>>> +///@}
>>>>>>>> +#endif
>>>>>>>> 
>>>>>>>> Added: qpid/proton/trunk/proton-c/src/url.c
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/proton-c/src/url.c (added)
>>>>>>>> +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50
>> 2014
>>>>>>>> @@ -0,0 +1,127 @@
>>>>>>>> +/*
>>>>>>>> + *
>>>>>>>> + * 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.
>>>>>>>> + *
>>>>>>>> + */
>>>>>>>> +
>>>>>>>> +#include <proton/url.h>
>>>>>>>> +#include <proton/util.h>
>>>>>>>> +#include <stdlib.h>
>>>>>>>> +#include <string.h>
>>>>>>>> +#include <stdio.h>
>>>>>>>> +
>>>>>>>> +static char* copy(const char* str) {
>>>>>>>> +    if (str ==  NULL) return NULL;
>>>>>>>> +    char *str2 = (char*)malloc(strlen(str));
>>>>>>>> +    if (str2) strcpy(str2, str);
>>>>>>>> +    return str2;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +struct pn_url_t {
>>>>>>>> +    char *scheme;
>>>>>>>> +    char *username;
>>>>>>>> +    char *password;
>>>>>>>> +    char *host;
>>>>>>>> +    char *port;
>>>>>>>> +    char *path;
>>>>>>>> +    char *str;
>>>>>>>> +};
>>>>>>>> +
>>>>>>>> +PN_EXTERN pn_url_t *pn_url() {
>>>>>>>> +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
>>>>>>>> +    memset(url, 0, sizeof(*url));
>>>>>>>> +    return url;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +/** Parse a string URL as a pn_url_t.
>>>>>>>> + *@param[in] url A URL string.
>>>>>>>> + *@return The parsed pn_url_t or NULL if url is not a valid
>> URL
>>>>>> string.
>>>>>>>> + */
>>>>>>>> +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
>>>>>>>> +    if (!str || !*str)          /* Empty string or NULL is
>>>> illegal. */
>>>>>>>> +        return NULL;
>>>>>>>> +
>>>>>>>> +    pn_url_t *url = pn_url();
>>>>>>>> +    char *str2 = copy(str);         /* FIXME aconway
>> 2014-09-19:
>>>>>> clean up
>>>>>>>> */
>>>>>>>> +    pni_parse_url(str2, &url->scheme, &url->username,
>>>> &url->password,
>>>>>>>> &url->host, &url->port, &url->path);
>>>>>>>> +    url->scheme = copy(url->scheme);
>>>>>>>> +    url->username = copy(url->username);
>>>>>>>> +    url->password = copy(url->password);
>>>>>>>> +    url->host = (url->host && !*url->host) ? NULL :
>>>> copy(url->host);
>>>>>>>> +    url->port = copy(url->port);
>>>>>>>> +    url->path = copy(url->path);
>>>>>>>> +    return url;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +/** Free a URL */
>>>>>>>> +PN_EXTERN void pn_url_free(pn_url_t *url) {
>>>>>>>> +    pn_url_clear(url);
>>>>>>>> +    free(url);
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +/** Clear the contents of the URL. */
>>>>>>>> +PN_EXTERN void pn_url_clear(pn_url_t *url) {
>>>>>>>> +    pn_url_set_username(url, NULL);
>>>>>>>> +    pn_url_set_password(url, NULL);
>>>>>>>> +    pn_url_set_host(url, NULL);
>>>>>>>> +    pn_url_set_port(url, NULL);
>>>>>>>> +    pn_url_set_path(url, NULL);
>>>>>>>> +    free(url->str); url->str = NULL;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +static inline int len(const char *str) { return str ?
>> strlen(str)
>>>> :
>>>>>> 0; }
>>>>>>>> +
>>>>>>>> +/** Return the string form of a URL. */
>>>>>>>> +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
>>>>>>>> +    int size = len(url->scheme) + len(url->username) +
>>>>>> len(url->password)
>>>>>>>> +        + len(url->host) + len(url->port) + len(url->path)
>>>>>>>> +        + len("s://u:p@[h]:p/p");
>>>>>>>> +    free(url->str);
>>>>>>>> +    url->str = (char*)malloc(size);
>>>>>>>> +    if (!url->str) return NULL;
>>>>>>>> +
>>>>>>>> +    int i = 0;
>>>>>>>> +    if (url->scheme) i += snprintf(url->str+i, size-i,
>> "%s://",
>>>>>>>> url->scheme);
>>>>>>>> +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
>>>>>>>> url->username);
>>>>>>>> +    if (url->password) i += snprintf(url->str+i, size-i,
>> ":%s",
>>>>>>>> url->password);
>>>>>>>> +    if (url->username || url->password) i +=
>> snprintf(url->str+i,
>>>>>> size-i,
>>>>>>>> "@");
>>>>>>>> +    if (url->host) {
>>>>>>>> +        if (strchr(url->host, ':')) i += snprintf(url->str+i,
>>>> size-i,
>>>>>>>> "[%s]", url->host);
>>>>>>>> +        else i += snprintf(url->str+i, size-i, "%s",
>> url->host);
>>>>>>>> +    }
>>>>>>>> +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
>>>>>> url->port);
>>>>>>>> +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
>>>>>> url->path);
>>>>>>>> +    return url->str;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>> +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
>>>>>> url->scheme; }
>>>>>>>> +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
>>>>>>>> url->username; }
>>>>>>>> +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
>>>>>>>> url->password; }
>>>>>>>> +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return
>>>> url->host; }
>>>>>>>> +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return
>>>> url->port; }
>>>>>>>> +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return
>>>> url->path; }
>>>>>>>> +
>>>>>>>> +#define SET(part) free(url->part); url->part = copy(part)
>>>>>>>> +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
>>>> *scheme) {
>>>>>>>> SET(scheme); }
>>>>>>>> +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
>>>>>> *username) {
>>>>>>>> SET(username); }
>>>>>>>> +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
>>>>>> *password) {
>>>>>>>> SET(password); }
>>>>>>>> +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char
>> *host) {
>>>>>>>> SET(host); }
>>>>>>>> +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char
>> *port) {
>>>>>>>> SET(port); }
>>>>>>>> +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char
>> *path) {
>>>>>>>> SET(path); }
>>>>>>>> +
>>>>>>>> +
>>>>>>>> 
>>>>>>>> Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
>>>>>>>> URL:
>>>>>>>> 
>>>>>> 
>>>> 
>> http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>> 
>> ==============================================================================
>>>>>>>> --- qpid/proton/trunk/tests/python/proton_tests/url.py
>> (original)
>>>>>>>> +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep
>> 19
>>>>>> 21:00:50
>>>>>>>> 2014
>>>>>>>> @@ -28,9 +28,9 @@ class UrlTest(common.Test):
>>>>>>>>     def assertNotEqual(self, a, b):
>>>>>>>>         assert a != b, "%s == %s" % (a, b)
>>>>>>>> 
>>>>>>>> -    def assertUrl(self, u, scheme, user, password, host, port,
>>>> path):
>>>>>>>> -        self.assertEqual((u.scheme, u.user, u.password,
>> u.host,
>>>>>> u.port,
>>>>>>>> u.path),
>>>>>>>> -                         (scheme, user, password, host, port,
>>>> path))
>>>>>>>> +    def assertUrl(self, u, scheme, username, password, host,
>> port,
>>>>>> path):
>>>>>>>> +        self.assertEqual((u.scheme, u.username, u.password,
>>>> u.host,
>>>>>>>> u.port, u.path),
>>>>>>>> +                         (scheme, username, password, host,
>> port,
>>>>>> path))
>>>>>>>> 
>>>>>>>>     def testUrl(self):
>>>>>>>>         url = Url('amqp://me:secret@myhost:1234/foobar')
>>>>>>>> @@ -40,7 +40,7 @@ class UrlTest(common.Test):
>>>>>>>> 
>>>>>>>>     def testDefaults(self):
>>>>>>>>         # Check that we allow None for scheme, port
>>>>>>>> -        url = Url(user='me', password='secret', host='myhost',
>>>>>>>> path='foobar')
>>>>>>>> +        url = Url(username='me', password='secret',
>> host='myhost',
>>>>>>>> path='foobar')
>>>>>>>>         self.assertEqual(str(url), "me:secret@myhost/foobar")
>>>>>>>>         self.assertUrl(url, None, 'me', 'secret', 'myhost',
>> None,
>>>>>>>> 'foobar')
>>>>>>>> 
>>>>>>>> @@ -97,21 +97,19 @@ class UrlTest(common.Test):
>>>>>>>>     def testMissing(self):
>>>>>>>>         self.assertUrl(Url(), None, None, None, None, None,
>> None)
>>>>>>>>         self.assertUrl(Url('amqp://'), 'amqp', None, None,
>> None,
>>>> None,
>>>>>>>> None)
>>>>>>>> -        self.assertUrl(Url('user@'), None, 'user', None,
>> None,
>>>> None,
>>>>>>>> None)
>>>>>>>> +        self.assertUrl(Url('username@'), None, 'username',
>> None,
>>>>>> None,
>>>>>>>> None, None)
>>>>>>>>         self.assertUrl(Url(':pass@'), None, '', 'pass', None,
>>>> None,
>>>>>> None)
>>>>>>>>         self.assertUrl(Url('host'), None, None, None, 'host',
>>>> None,
>>>>>> None)
>>>>>>>>         self.assertUrl(Url(':1234'), None, None, None, None,
>> 1234,
>>>>>> None)
>>>>>>>>         self.assertUrl(Url('/path'), None, None, None, None,
>> None,
>>>>>> 'path')
>>>>>>>> 
>>>>>>>> -        for s in ['amqp://', 'user@', ':pass@', ':1234',
>>>> '/path']:
>>>>>>>> +        for s in ['amqp://', 'username@', ':pass@', ':1234',
>>>>>> '/path']:
>>>>>>>>             self.assertEqual(s, str(Url(s)))
>>>>>>>> 
>>>>>>>>         for s, full in [
>>>>>>>>                 ('amqp://', 'amqp://0.0.0.0:amqp'),
>>>>>>>> -                ('user@', 'amqp://user@0.0.0.0:amqp'),
>>>>>>>> +                ('username@', 'amqp://username@0.0.0.0:
>> amqp'),
>>>>>>>>                 (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
>>>>>>>>                 (':1234', 'amqp://0.0.0.0:1234'),
>>>>>>>>                 ('/path', 'amqp://0.0.0.0:amqp/path')]:
>>>>>>>>             self.assertEqual(str(Url(s).defaults()), full)
>>>>>>>> -
>>>>>>>> -        self.assertRaises(ValueError, Url, '')
>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>>>>>> 
>>>> ---------------------------------------------------------------------
>>>>>>>> To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
>>>>>>>> For additional commands, e-mail: commits-help@qpid.apache.org
>>>>>>>> 
>>>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 
>>>>>> 
>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
>>>>>> For additional commands, e-mail: dev-help@qpid.apache.org
>>>>>> 
>>>>>> 
>>>> 
>>>> 
>>>> 
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
>>>> For additional commands, e-mail: dev-help@qpid.apache.org
>>>> 
>>>> 
>> 
>> 
>> 
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
>> For additional commands, e-mail: dev-help@qpid.apache.org
>> 
>> 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
For additional commands, e-mail: dev-help@qpid.apache.org


Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Alan Conway <ac...@redhat.com>.
On Thu, 2014-09-25 at 19:20 +0100, Robbie Gemmell wrote:
> Failing in a different way now, the overall run of the python tests bombs
> out. I see the same thing locally, where it was working when I made the
> commit immediately before yours :)

------------------------------------------------------------------------
r1627621 | aconway | 2014-09-25 15:40:22 -0400 (Thu, 25 Sep 2014) | 5
lines

NO-JIRA: Fix URL test to not explode under jython.

Turns out the proton test harness blows up when run under jython if you
"import
socket" in a test module. Works fine under real python. Go figure.

------------------------------------------------------------------------

> 
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/683/console
> 
> Running org.apache.qpid.proton.JythonTest
> Sep 25, 2014 6:03:44 PM org.apache.qpid.proton.JythonTest test
> INFO: About to call Jython test script:
> '/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test'
> with '/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python'
> added to Jython path
> Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 7.714
> sec <<< FAILURE!
> test(org.apache.qpid.proton.JythonTest)  Time elapsed: 7.675 sec  <<< FAILURE!
> java.lang.AssertionError: Caught PyException on invocation number 2:
> Traceback (most recent call last):
>   File "/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test",
> line 597, in <module>
>     h.scan(m)
>   File "/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test",
> line 587, in scan
>     if not (child in self.scanned or child in objects):
> TypeError: object of type 'object' has no len()
>  with message: null
> 	at org.junit.Assert.fail(Assert.java:93)
> 	at org.apache.qpid.proton.JythonTest.runTestOnce(JythonTest.java:120)
> 	at org.apache.qpid.proton.JythonTest.test(JythonTest.java:95)
> 
> 
> On 25 September 2014 18:59, Alan Conway <ac...@redhat.com> wrote:
> 
> > On Thu, 2014-09-25 at 15:59 +0100, Robbie Gemmell wrote:
> > > On 25 September 2014 15:00, Alan Conway <ac...@redhat.com> wrote:
> > >
> > > > On Wed, 2014-09-24 at 12:19 +0100, Robbie Gemmell wrote:
> > > > > The tests are now running again, but a couple of the URL tests still
> > seem
> > > > > to be failing on the CI job:
> > > > >
> > > >
> > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/
> > > > >
> > > >
> > > > They are all failing with:
> > > >  Not a valid port number or service name: 'amqps'
> > > >
> > > > Could this be a configuration problem on the CI machine, i.e. missing
> > an
> > > > 'amqps' entry in /etc/services? Can I get access to the CI machine to
> > > > poke around and see what's up?
> > > >
> > >
> > > Almost certainly no, only the core maintainers are allowed shell access
> > as
> > > far as I've seen. You can ask on builds@apache.org for those with
> > access to
> > > check things out and report back and see what happens.
> > >
> > > I think the CI instances will be running Ubuntu 12.04 or 14.04 LTS. For
> > > giggles, I dug out an ooooold Ubuntu VM with Java 6 on it and tried the
> > > tests, which failed, and it indeed has no amqp[s] entry in /etc/services
> > > file so that could well be it.
> >
> > Thanks for checking that out! I have hacked the tests to skip tests for
> > 'amqps' if it is not recognized. Poke me if there are still failures.
> >
> > ------------------------------------------------------------------------
> > r1627577 | aconway | 2014-09-25 13:59:17 -0400 (Thu, 25 Sep 2014) | 5
> > lines
> >
> > NO-JIRA: Fix URL test to skip 'amqps' tests if 'amqps' is not recognized
> > as a service name.
> >
> > On some older Ubuntu with Java 6, 'amqps' is not recognized as a service
> > name so
> > skip those tests in that case.
> >
> > ------------------------------------------------------------------------
> >
> > > >
> > > > The URL code uses socket.getservbyname() to look up service names. Is
> > > > there a more portable way to do it?
> > > >
> > >
> > > No idea I'm afraid.
> > >
> > >
> > > >
> > > > Cheers,
> > > > Alan.
> > > >
> > > > > As mentioned in my other post about a timeline for dropping Java6
> > > > support,
> > > > > they seem to work on Java8 (havent tried Java7).
> > > > >
> > > > > Robbie
> > > > >
> > > > > On 22 September 2014 21:14, Alan Conway <ac...@redhat.com> wrote:
> > > > >
> > > > > > My bad, didn't run the java tests. Will fix ASAP and then give
> > myself a
> > > > > > flogging.
> > > > > >
> > > > > > On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> > > > > > > This seems to have broken the Java test runs:
> > > > > > >
> > > > > > >
> > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > On 19 September 2014 22:00, <ac...@apache.org> wrote:
> > > > > > >
> > > > > > > > Author: aconway
> > > > > > > > Date: Fri Sep 19 21:00:50 2014
> > > > > > > > New Revision: 1626329
> > > > > > > >
> > > > > > > > URL: http://svn.apache.org/r1626329
> > > > > > > > Log:
> > > > > > > > PROTON-693: Python Url class to wrap C function pni_parse_url
> > > > > > > >
> > > > > > > > It was pointed out that pni_parse_url is an internal function
> > and
> > > > the
> > > > > > > > interface
> > > > > > > > is not suitable for public API.
> > > > > > > >
> > > > > > > > Rewrote the URL parser as a proper swigable C API pn_url_*.
> > This
> > > > gets
> > > > > > rid
> > > > > > > > of the
> > > > > > > > need for previous swig insanity and is cleaner all round.
> > > > > > > >
> > > > > > > > Internally still uses the pni_parse_url parser, we can clean
> > that
> > > > up
> > > > > > later.
> > > > > > > >
> > > > > > > > Added:
> > > > > > > >     qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > > >     qpid/proton/trunk/proton-c/src/url.c
> > > > > > > > Modified:
> > > > > > > >     qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > > >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > > >     qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19
> > 21:00:50
> > > > 2014
> > > > > > > > @@ -270,6 +270,7 @@ set (qpid-proton-core
> > > > > > > >    src/object/iterator.c
> > > > > > > >
> > > > > > > >    src/util.c
> > > > > > > > +  src/url.c
> > > > > > > >    src/error.c
> > > > > > > >    src/buffer.c
> > > > > > > >    src/parser.c
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19
> > > > 21:00:50
> > > > > > > > 2014
> > > > > > > > @@ -8,6 +8,7 @@
> > > > > > > >  #include <proton/messenger.h>
> > > > > > > >  #include <proton/ssl.h>
> > > > > > > >  #include <proton/driver_extras.h>
> > > > > > > > +#include <proton/url.h>
> > > > > > > >  %}
> > > > > > > >
> > > > > > > >  %include <cstring.i>
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19
> > > > 21:00:50
> > > > > > 2014
> > > > > > > > @@ -29,6 +29,7 @@
> > > > > > > >  %header %{
> > > > > > > >  /* Include the headers needed by the code in this wrapper
> > file */
> > > > > > > >  #include <proton/types.h>
> > > > > > > > +#include <proton/url.h>
> > > > > > > >  #include <proton/message.h>
> > > > > > > >  #include <proton/driver.h>
> > > > > > > >  #include <proton/driver_extras.h>
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri
> > Sep 19
> > > > > > > > 21:00:50 2014
> > > > > > > > @@ -23,6 +23,7 @@
> > > > > > > >  #include <winsock2.h>
> > > > > > > >  #endif
> > > > > > > >  #include <proton/engine.h>
> > > > > > > > +#include <proton/url.h>
> > > > > > > >  #include <proton/message.h>
> > > > > > > >  #include <proton/sasl.h>
> > > > > > > >  #include <proton/driver.h>
> > > > > > > > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> > > > > > > >    }
> > > > > > > >  %}
> > > > > > > >
> > > > > > > > -
> > > > > > > > -/**
> > > > > > > > -   pni_parse_url(char* url, char **scheme, char **user, char
> > > > **pass,
> > > > > > char
> > > > > > > > **host, char **port, char **path)
> > > > > > > > -   The following type maps convert this into a python function
> > > > that
> > > > > > taks
> > > > > > > > a URL string argument
> > > > > > > > -   and returns a list of strings [scheme, user, pass, host,
> > port,
> > > > > > path]
> > > > > > > > -   This probably could be done more neatly.
> > > > > > > > -*/
> > > > > > > > -
> > > > > > > > -// Typemap to copy the url string as it will be modified by
> > > > parse_url
> > > > > > > > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char
> > *url
> > > > (int
> > > > > > > > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > > > > > > > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > > > > > > > -  if (!SWIG_IsOK(res)) {
> > > > > > > > -    %argument_fail(res, "char *url", $symname, $argnum);
> > > > > > > > -  }
> > > > > > > > -  $1 = %new_array(n, $*1_ltype);
> > > > > > > > -  memcpy($1,t,sizeof(char)*n);
> > > > > > > > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > > > > > > > -  $1[n-1] = 0;
> > > > > > > > -}
> > > > > > > > -%typemap(freearg,match="in") char *url "free($1);";
> > > > > > > > -%typemap(argout) char *url "";
> > > > > > > > -
> > > > > > > > -// Typemap for char** return strings. Don't free them.
> > > > > > > > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0)
> > "$1 =
> > > > > > &temp;";
> > > > > > > > -%typemap(freearg,match="in") char **OUTSTR "";
> > > > > > > > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char
> > > > **OUTSTR {
> > > > > > > > -    %append_output(SWIG_FromCharPtr(*$1));
> > > > > > > > -}
> > > > > > > > -
> > > > > > > > -// Typemap to initialize result as empty list
> > > > > > > > -%typemap(out) void "$result = PyList_New(0);";
> > > > > > > > -
> > > > > > > > -
> > > > > > > > -%apply char** OUTSTR {char **scheme, char **user, char **pass,
> > > > char
> > > > > > > > **host, char **port, char **path};
> > > > > > > > -void pni_parse_url(char* url, char **scheme, char **user, char
> > > > **pass,
> > > > > > > > char **host, char **port, char **path);
> > > > > > > > -%ignore pni_parse_url;
> > > > > > > > -
> > > > > > > >  %include "proton/cproton.i"
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/python/proton.py
> > (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri
> > Sep 19
> > > > > > > > 21:00:50 2014
> > > > > > > > @@ -3657,114 +3657,98 @@ __all__ = [
> > > > > > > >
> > > > > > > >
> > > > > > > >  class Url(object):
> > > > > > > > -    """
> > > > > > > > -    Simple URL parser/constructor, handles URLs of the form:
> > > > > > > > +  """
> > > > > > > > +  Simple URL parser/constructor, handles URLs of the form:
> > > > > > > >
> > > > > > > > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > > > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > > >
> > > > > > > > -    All components can be None if not specifeid in the URL
> > string.
> > > > > > > > +  All components can be None if not specifeid in the URL
> > string.
> > > > > > > >
> > > > > > > > -    The port can be specified as a service name, e.g. 'amqp'
> > in
> > > > the
> > > > > > > > -    URL string but Url.port always gives the integer value.
> > > > > > > > +  The port can be specified as a service name, e.g. 'amqp' in
> > the
> > > > > > > > +  URL string but Url.port always gives the integer value.
> > > > > > > > +
> > > > > > > > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > > > +  @ivar user: Username
> > > > > > > > +  @ivar password: Password
> > > > > > > > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > > > +  @ivar port: Integer port.
> > > > > > > > +  @ivar host_port: Returns host:port
> > > > > > > > +  """
> > > > > > > > +
> > > > > > > > +  AMQPS = "amqps"
> > > > > > > > +  AMQP = "amqp"
> > > > > > > > +
> > > > > > > > +  class Port(int):
> > > > > > > > +    """An integer port number that can be constructed from a
> > > > service
> > > > > > name
> > > > > > > > string"""
> > > > > > > > +
> > > > > > > > +    def __new__(cls, value):
> > > > > > > > +      port = super(Url.Port, cls).__new__(cls,
> > > > cls.port_int(value))
> > > > > > > > +      setattr(port, 'name', str(value))
> > > > > > > > +      return port
> > > > > > > > +
> > > > > > > > +    def __eq__(self, x): return str(self) == x or int(self)
> > == x
> > > > > > > > +    def __ne__(self, x): return not self == x
> > > > > > > > +    def __str__(self): return str(self.name)
> > > > > > > > +
> > > > > > > > +    @staticmethod
> > > > > > > > +    def port_int(value):
> > > > > > > > +      """Convert service, an integer or a service name, into
> > an
> > > > > > integer
> > > > > > > > port number."""
> > > > > > > > +      try:
> > > > > > > > +        return int(value)
> > > > > > > > +      except ValueError:
> > > > > > > > +        try:
> > > > > > > > +          return socket.getservbyname(value)
> > > > > > > > +        except socket.error:
> > > > > > > > +          raise ValueError("Not a valid port number or service
> > > > name:
> > > > > > > > '%s'" % value)
> > > > > > > >
> > > > > > > > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > > > -    @ivar user: Username
> > > > > > > > -    @ivar password: Password
> > > > > > > > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > > > -    @ivar port: Integer port.
> > > > > > > > -    @ivar host_port: Returns host:port
> > > > > > > > +  def __init__(self, url=None, **kwargs):
> > > > > > > > +    """
> > > > > > > > +    @param url: URL string to parse.
> > > > > > > > +    @param kwargs: scheme, user, password, host, port, path.
> > > > > > > > +      If specified, replaces corresponding part in url string.
> > > > > > > >      """
> > > > > > > > +    if url:
> > > > > > > > +      self._url = pn_url_parse(str(url))
> > > > > > > > +      if not self._url: raise ValueError("Invalid URL '%s'" %
> > url)
> > > > > > > > +    else:
> > > > > > > > +      self._url = pn_url()
> > > > > > > > +    for k in kwargs:            # Let kwargs override values
> > > > parsed
> > > > > > from
> > > > > > > > url
> > > > > > > > +      getattr(self, k)          # Check for invalid kwargs
> > > > > > > > +      setattr(self, k, kwargs[k])
> > > > > > > > +
> > > > > > > > +  class PartDescriptor(object):
> > > > > > > > +    def __init__(self, part):
> > > > > > > > +      self.getter = globals()["pn_url_%s" % part]
> > > > > > > > +      self.setter = globals()["pn_url_set_%s" % part]
> > > > > > > > +    def __get__(self, obj, type=None): return
> > > > self.getter(obj._url)
> > > > > > > > +    def __set__(self, obj, value): return
> > self.setter(obj._url,
> > > > > > > > str(value))
> > > > > > > > +
> > > > > > > > +  scheme = PartDescriptor('scheme')
> > > > > > > > +  username = PartDescriptor('username')
> > > > > > > > +  password = PartDescriptor('password')
> > > > > > > > +  host = PartDescriptor('host')
> > > > > > > > +  path = PartDescriptor('path')
> > > > > > > > +
> > > > > > > > +  @property
> > > > > > > > +  def port(self):
> > > > > > > > +    portstr = pn_url_port(self._url)
> > > > > > > > +    return portstr and Url.Port(portstr)
> > > > > > > > +
> > > > > > > > +  @port.setter
> > > > > > > > +  def port(self, value):
> > > > > > > > +    if value is None: pn_url_set_port(self._url, None)
> > > > > > > > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> > > > > > > >
> > > > > > > > -    AMQPS = "amqps"
> > > > > > > > -    AMQP = "amqp"
> > > > > > > > +  def __str__(self): return pn_url_str(self._url)
> > > > > > > >
> > > > > > > > -    class Port(int):
> > > > > > > > -      """An integer port number that can also have an
> > associated
> > > > > > service
> > > > > > > > name string"""
> > > > > > > > +  def __repr__(self): return "Url(%r)" % str(self)
> > > > > > > >
> > > > > > > > -      def __new__(cls, value):
> > > > > > > > -        port = super(Url.Port, cls).__new__(cls,
> > > > cls.port_int(value))
> > > > > > > > -        setattr(port, 'name', str(value))
> > > > > > > > -        return port
> > > > > > > > -
> > > > > > > > -      def __eq__(self, x): return str(self) == x or int(self)
> > == x
> > > > > > > > -      def __ne__(self, x): return not self == x
> > > > > > > > -      def __str__(self): return str(self.name)
> > > > > > > > -
> > > > > > > > -      @staticmethod
> > > > > > > > -      def port_int(value):
> > > > > > > > -        """Convert service, an integer or a service name,
> > into an
> > > > > > integer
> > > > > > > > port number."""
> > > > > > > > -        try:
> > > > > > > > -          return int(value)
> > > > > > > > -        except ValueError:
> > > > > > > > -          try:
> > > > > > > > -            return socket.getservbyname(value)
> > > > > > > > -          except socket.error:
> > > > > > > > -            raise ValueError("Not a valid port number or
> > service
> > > > name:
> > > > > > > > '%s'" % value)
> > > > > > > > -
> > > > > > > > -    def __init__(self, url=None, **kwargs):
> > > > > > > > -        """
> > > > > > > > -        @param url: String or Url instance to parse or copy.
> > > > > > > > -        @param kwargs: URL fields: scheme, user, password,
> > host,
> > > > port,
> > > > > > > > path.
> > > > > > > > -            If specified, replaces corresponding component in
> > url.
> > > > > > > > -        """
> > > > > > > > -
> > > > > > > > -        fields = ['scheme', 'user', 'password', 'host',
> > 'port',
> > > > > > 'path']
> > > > > > > > -
> > > > > > > > -        for f in fields: setattr(self, f, None)
> > > > > > > > -        for k in kwargs: getattr(self, k) # Check for invalid
> > > > kwargs
> > > > > > > > -
> > > > > > > > -        if isinstance(url, Url): # Copy from another Url
> > instance.
> > > > > > > > -            self.__dict__.update(url.__dict__)
> > > > > > > > -        elif url is not None:   # Parse from url
> > > > > > > > -            parts = pni_parse_url(str(url))
> > > > > > > > -            if not filter(None, parts): raise
> > ValueError("Invalid
> > > > AMQP
> > > > > > > > URL: '%s'" % url)
> > > > > > > > -            self.scheme, self.user, self.password, self.host,
> > > > port,
> > > > > > > > self.path = parts
> > > > > > > > -            if not self.host: self.host = None
> > > > > > > > -            self.port = port and self.Port(port)
> > > > > > > > -
> > > > > > > > -        # Let kwargs override values previously set from url
> > > > > > > > -        for field in fields:
> > > > > > > > -            setattr(self, field, kwargs.get(field,
> > getattr(self,
> > > > > > field)))
> > > > > > > > -
> > > > > > > > -    def __repr__(self):
> > > > > > > > -        return "Url(%r)" % str(self)
> > > > > > > > -
> > > > > > > > -    def __str__(self):
> > > > > > > > -        s = ""
> > > > > > > > -        if self.scheme:
> > > > > > > > -            s += "%s://" % self.scheme
> > > > > > > > -        if self.user:
> > > > > > > > -            s += self.user
> > > > > > > > -        if self.password:
> > > > > > > > -            s += ":%s" % self.password
> > > > > > > > -        if self.user or self.password:
> > > > > > > > -            s += '@'
> > > > > > > > -        if self.host and ':' in self.host:
> > > > > > > > -            s += "[%s]" % self.host
> > > > > > > > -        elif self.host:
> > > > > > > > -            s += self.host
> > > > > > > > -        if self.port:
> > > > > > > > -            s += ":%s" % self.port
> > > > > > > > -        if self.path:
> > > > > > > > -            s += "/%s" % self.path
> > > > > > > > -        return s
> > > > > > > > -
> > > > > > > > -    def __eq__(self, url):
> > > > > > > > -        return \
> > > > > > > > -            self.scheme == url.scheme and \
> > > > > > > > -            self.user == url.user and self.password ==
> > > > url.password
> > > > > > and \
> > > > > > > > -            self.host == url.host and self.port == url.port
> > and \
> > > > > > > > -            self.path == url.path
> > > > > > > > -
> > > > > > > > -    def __ne__(self, url):
> > > > > > > > -        return not self.__eq__(url)
> > > > > > > > -
> > > > > > > > -    def defaults(self):
> > > > > > > > -        """
> > > > > > > > -        Fill in missing values with defaults
> > > > > > > > -        @return: self
> > > > > > > > -        """
> > > > > > > > -        self.scheme = self.scheme or self.AMQP
> > > > > > > > -        self.host = self.host or '0.0.0.0'
> > > > > > > > -        self.port = self.port or self.Port(self.scheme)
> > > > > > > > -        return self
> > > > > > > > +  def defaults(self):
> > > > > > > > +    """
> > > > > > > > +    Fill in missing values (scheme, host or port) with
> > defaults
> > > > > > > > +    @return: self
> > > > > > > > +    """
> > > > > > > > +    self.scheme = self.scheme or self.AMQP
> > > > > > > > +    self.host = self.host or '0.0.0.0'
> > > > > > > > +    self.port = self.port or self.Port(self.scheme)
> > > > > > > > +    return self
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19
> > > > 21:00:50
> > > > > > > > 2014
> > > > > > > > @@ -26,8 +26,8 @@
> > > > > > > >  #include <proton/messenger.h>
> > > > > > > >  #include <proton/ssl.h>
> > > > > > > >  #include <proton/driver_extras.h>
> > > > > > > > -
> > > > > > > >  #include <proton/types.h>
> > > > > > > > +#include <proton/url.h>
> > > > > > > >
> > > > > > > >  #include <uuid/uuid.h>
> > > > > > > >  %}
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/include/proton/cproton.i
> > (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri
> > Sep 19
> > > > > > > > 21:00:50 2014
> > > > > > > > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> > > > > > > >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return
> > > > (pn_delivery_t
> > > > > > *)
> > > > > > > > x; }
> > > > > > > >    pn_transport_t *pn_cast_pn_transport(void *x) { return
> > > > > > (pn_transport_t
> > > > > > > > *) x; }
> > > > > > > >  %}
> > > > > > > > +
> > > > > > > > +%include "proton/url.h"
> > > > > > > > +
> > > > > > > >
> > > > > > > > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > > > > > > > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19
> > > > 21:00:50
> > > > > > > > 2014
> > > > > > > > @@ -0,0 +1,83 @@
> > > > > > > > +#ifndef PROTON_URL_H
> > > > > > > > +#define PROTON_URL_H
> > > > > > > > +/*
> > > > > > > > + * 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.
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +#include <proton/import_export.h>
> > > > > > > > +
> > > > > > > > +/** @file
> > > > > > > > + * URL API for parsing URLs.
> > > > > > > > + *
> > > > > > > > + * @defgroup url URL
> > > > > > > > + * @{
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +/** A parsed URL */
> > > > > > > > +typedef struct pn_url_t pn_url_t;
> > > > > > > > +
> > > > > > > > +/** Create an empty URL */
> > > > > > > > +PN_EXTERN pn_url_t *pn_url(void);
> > > > > > > > +
> > > > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > > > + *@param[in] url A URL string.
> > > > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid
> > URL
> > > > > > string.
> > > > > > > > + */
> > > > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > > > > > > > +
> > > > > > > > +/** Free a URL */
> > > > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > > > > > > > +
> > > > > > > > +/** Clear the contents of the URL. */
> > > > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > > > > > > > +
> > > > > > > > +/** Return the string form of a URL. Owned by the pn_url_t.*/
> > > > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + *@name Getters for parts of the URL.
> > > > > > > > + *
> > > > > > > > + *Values belong to the URL. May return NULL if the value is
> > not
> > > > set.
> > > > > > > > + *
> > > > > > > > + *@{
> > > > > > > > + */
> > > > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > > > > > > > +///@}
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + *@name Setters for parts of the URL.
> > > > > > > > + *
> > > > > > > > + *Values are copied. Value can be NULL to indicate the part
> > is not
> > > > > > set.
> > > > > > > > + *
> > > > > > > > + *@{
> > > > > > > > + */
> > > > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > > > *scheme);
> > > > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > > > *username);
> > > > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > > > *password);
> > > > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char
> > *host);
> > > > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char
> > *port);
> > > > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char
> > *path);
> > > > > > > > +///@}
> > > > > > > > +
> > > > > > > > +///@}
> > > > > > > > +#endif
> > > > > > > >
> > > > > > > > Added: qpid/proton/trunk/proton-c/src/url.c
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > > > > > > > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50
> > 2014
> > > > > > > > @@ -0,0 +1,127 @@
> > > > > > > > +/*
> > > > > > > > + *
> > > > > > > > + * 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.
> > > > > > > > + *
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +#include <proton/url.h>
> > > > > > > > +#include <proton/util.h>
> > > > > > > > +#include <stdlib.h>
> > > > > > > > +#include <string.h>
> > > > > > > > +#include <stdio.h>
> > > > > > > > +
> > > > > > > > +static char* copy(const char* str) {
> > > > > > > > +    if (str ==  NULL) return NULL;
> > > > > > > > +    char *str2 = (char*)malloc(strlen(str));
> > > > > > > > +    if (str2) strcpy(str2, str);
> > > > > > > > +    return str2;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +struct pn_url_t {
> > > > > > > > +    char *scheme;
> > > > > > > > +    char *username;
> > > > > > > > +    char *password;
> > > > > > > > +    char *host;
> > > > > > > > +    char *port;
> > > > > > > > +    char *path;
> > > > > > > > +    char *str;
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +PN_EXTERN pn_url_t *pn_url() {
> > > > > > > > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > > > > > > > +    memset(url, 0, sizeof(*url));
> > > > > > > > +    return url;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > > > + *@param[in] url A URL string.
> > > > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid
> > URL
> > > > > > string.
> > > > > > > > + */
> > > > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > > > > > > > +    if (!str || !*str)          /* Empty string or NULL is
> > > > illegal. */
> > > > > > > > +        return NULL;
> > > > > > > > +
> > > > > > > > +    pn_url_t *url = pn_url();
> > > > > > > > +    char *str2 = copy(str);         /* FIXME aconway
> > 2014-09-19:
> > > > > > clean up
> > > > > > > > */
> > > > > > > > +    pni_parse_url(str2, &url->scheme, &url->username,
> > > > &url->password,
> > > > > > > > &url->host, &url->port, &url->path);
> > > > > > > > +    url->scheme = copy(url->scheme);
> > > > > > > > +    url->username = copy(url->username);
> > > > > > > > +    url->password = copy(url->password);
> > > > > > > > +    url->host = (url->host && !*url->host) ? NULL :
> > > > copy(url->host);
> > > > > > > > +    url->port = copy(url->port);
> > > > > > > > +    url->path = copy(url->path);
> > > > > > > > +    return url;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +/** Free a URL */
> > > > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > > > > > > > +    pn_url_clear(url);
> > > > > > > > +    free(url);
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +/** Clear the contents of the URL. */
> > > > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > > > > > > > +    pn_url_set_username(url, NULL);
> > > > > > > > +    pn_url_set_password(url, NULL);
> > > > > > > > +    pn_url_set_host(url, NULL);
> > > > > > > > +    pn_url_set_port(url, NULL);
> > > > > > > > +    pn_url_set_path(url, NULL);
> > > > > > > > +    free(url->str); url->str = NULL;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +static inline int len(const char *str) { return str ?
> > strlen(str)
> > > > :
> > > > > > 0; }
> > > > > > > > +
> > > > > > > > +/** Return the string form of a URL. */
> > > > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > > > > > > > +    int size = len(url->scheme) + len(url->username) +
> > > > > > len(url->password)
> > > > > > > > +        + len(url->host) + len(url->port) + len(url->path)
> > > > > > > > +        + len("s://u:p@[h]:p/p");
> > > > > > > > +    free(url->str);
> > > > > > > > +    url->str = (char*)malloc(size);
> > > > > > > > +    if (!url->str) return NULL;
> > > > > > > > +
> > > > > > > > +    int i = 0;
> > > > > > > > +    if (url->scheme) i += snprintf(url->str+i, size-i,
> > "%s://",
> > > > > > > > url->scheme);
> > > > > > > > +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> > > > > > > > url->username);
> > > > > > > > +    if (url->password) i += snprintf(url->str+i, size-i,
> > ":%s",
> > > > > > > > url->password);
> > > > > > > > +    if (url->username || url->password) i +=
> > snprintf(url->str+i,
> > > > > > size-i,
> > > > > > > > "@");
> > > > > > > > +    if (url->host) {
> > > > > > > > +        if (strchr(url->host, ':')) i += snprintf(url->str+i,
> > > > size-i,
> > > > > > > > "[%s]", url->host);
> > > > > > > > +        else i += snprintf(url->str+i, size-i, "%s",
> > url->host);
> > > > > > > > +    }
> > > > > > > > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
> > > > > > url->port);
> > > > > > > > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
> > > > > > url->path);
> > > > > > > > +    return url->str;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
> > > > > > url->scheme; }
> > > > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> > > > > > > > url->username; }
> > > > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> > > > > > > > url->password; }
> > > > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return
> > > > url->host; }
> > > > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return
> > > > url->port; }
> > > > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return
> > > > url->path; }
> > > > > > > > +
> > > > > > > > +#define SET(part) free(url->part); url->part = copy(part)
> > > > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > > > *scheme) {
> > > > > > > > SET(scheme); }
> > > > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > > > *username) {
> > > > > > > > SET(username); }
> > > > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > > > *password) {
> > > > > > > > SET(password); }
> > > > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char
> > *host) {
> > > > > > > > SET(host); }
> > > > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char
> > *port) {
> > > > > > > > SET(port); }
> > > > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char
> > *path) {
> > > > > > > > SET(path); }
> > > > > > > > +
> > > > > > > > +
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > > > --- qpid/proton/trunk/tests/python/proton_tests/url.py
> > (original)
> > > > > > > > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep
> > 19
> > > > > > 21:00:50
> > > > > > > > 2014
> > > > > > > > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> > > > > > > >      def assertNotEqual(self, a, b):
> > > > > > > >          assert a != b, "%s == %s" % (a, b)
> > > > > > > >
> > > > > > > > -    def assertUrl(self, u, scheme, user, password, host, port,
> > > > path):
> > > > > > > > -        self.assertEqual((u.scheme, u.user, u.password,
> > u.host,
> > > > > > u.port,
> > > > > > > > u.path),
> > > > > > > > -                         (scheme, user, password, host, port,
> > > > path))
> > > > > > > > +    def assertUrl(self, u, scheme, username, password, host,
> > port,
> > > > > > path):
> > > > > > > > +        self.assertEqual((u.scheme, u.username, u.password,
> > > > u.host,
> > > > > > > > u.port, u.path),
> > > > > > > > +                         (scheme, username, password, host,
> > port,
> > > > > > path))
> > > > > > > >
> > > > > > > >      def testUrl(self):
> > > > > > > >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > > > > > > > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> > > > > > > >
> > > > > > > >      def testDefaults(self):
> > > > > > > >          # Check that we allow None for scheme, port
> > > > > > > > -        url = Url(user='me', password='secret', host='myhost',
> > > > > > > > path='foobar')
> > > > > > > > +        url = Url(username='me', password='secret',
> > host='myhost',
> > > > > > > > path='foobar')
> > > > > > > >          self.assertEqual(str(url), "me:secret@myhost/foobar")
> > > > > > > >          self.assertUrl(url, None, 'me', 'secret', 'myhost',
> > None,
> > > > > > > > 'foobar')
> > > > > > > >
> > > > > > > > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> > > > > > > >      def testMissing(self):
> > > > > > > >          self.assertUrl(Url(), None, None, None, None, None,
> > None)
> > > > > > > >          self.assertUrl(Url('amqp://'), 'amqp', None, None,
> > None,
> > > > None,
> > > > > > > > None)
> > > > > > > > -        self.assertUrl(Url('user@'), None, 'user', None,
> > None,
> > > > None,
> > > > > > > > None)
> > > > > > > > +        self.assertUrl(Url('username@'), None, 'username',
> > None,
> > > > > > None,
> > > > > > > > None, None)
> > > > > > > >          self.assertUrl(Url(':pass@'), None, '', 'pass', None,
> > > > None,
> > > > > > None)
> > > > > > > >          self.assertUrl(Url('host'), None, None, None, 'host',
> > > > None,
> > > > > > None)
> > > > > > > >          self.assertUrl(Url(':1234'), None, None, None, None,
> > 1234,
> > > > > > None)
> > > > > > > >          self.assertUrl(Url('/path'), None, None, None, None,
> > None,
> > > > > > 'path')
> > > > > > > >
> > > > > > > > -        for s in ['amqp://', 'user@', ':pass@', ':1234',
> > > > '/path']:
> > > > > > > > +        for s in ['amqp://', 'username@', ':pass@', ':1234',
> > > > > > '/path']:
> > > > > > > >              self.assertEqual(s, str(Url(s)))
> > > > > > > >
> > > > > > > >          for s, full in [
> > > > > > > >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > > > > > > > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > > > > > > > +                ('username@', 'amqp://username@0.0.0.0:
> > amqp'),
> > > > > > > >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> > > > > > > >                  (':1234', 'amqp://0.0.0.0:1234'),
> > > > > > > >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> > > > > > > >              self.assertEqual(str(Url(s).defaults()), full)
> > > > > > > > -
> > > > > > > > -        self.assertRaises(ValueError, Url, '')
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > ---------------------------------------------------------------------
> > > > > > > > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > > > > > > > For additional commands, e-mail: commits-help@qpid.apache.org
> > > > > > > >
> > > > > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > >
> > ---------------------------------------------------------------------
> > > > > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > > > > For additional commands, e-mail: dev-help@qpid.apache.org
> > > > > >
> > > > > >
> > > >
> > > >
> > > >
> > > > ---------------------------------------------------------------------
> > > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > > For additional commands, e-mail: dev-help@qpid.apache.org
> > > >
> > > >
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > For additional commands, e-mail: dev-help@qpid.apache.org
> >
> >



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
For additional commands, e-mail: dev-help@qpid.apache.org


Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Robbie Gemmell <ro...@gmail.com>.
Failing in a different way now, the overall run of the python tests bombs
out. I see the same thing locally, where it was working when I made the
commit immediately before yours :)

https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/683/console

Running org.apache.qpid.proton.JythonTest
Sep 25, 2014 6:03:44 PM org.apache.qpid.proton.JythonTest test
INFO: About to call Jython test script:
'/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test'
with '/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python'
added to Jython path
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 7.714
sec <<< FAILURE!
test(org.apache.qpid.proton.JythonTest)  Time elapsed: 7.675 sec  <<< FAILURE!
java.lang.AssertionError: Caught PyException on invocation number 2:
Traceback (most recent call last):
  File "/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test",
line 597, in <module>
    h.scan(m)
  File "/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test",
line 587, in scan
    if not (child in self.scanned or child in objects):
TypeError: object of type 'object' has no len()
 with message: null
	at org.junit.Assert.fail(Assert.java:93)
	at org.apache.qpid.proton.JythonTest.runTestOnce(JythonTest.java:120)
	at org.apache.qpid.proton.JythonTest.test(JythonTest.java:95)


On 25 September 2014 18:59, Alan Conway <ac...@redhat.com> wrote:

> On Thu, 2014-09-25 at 15:59 +0100, Robbie Gemmell wrote:
> > On 25 September 2014 15:00, Alan Conway <ac...@redhat.com> wrote:
> >
> > > On Wed, 2014-09-24 at 12:19 +0100, Robbie Gemmell wrote:
> > > > The tests are now running again, but a couple of the URL tests still
> seem
> > > > to be failing on the CI job:
> > > >
> > >
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/
> > > >
> > >
> > > They are all failing with:
> > >  Not a valid port number or service name: 'amqps'
> > >
> > > Could this be a configuration problem on the CI machine, i.e. missing
> an
> > > 'amqps' entry in /etc/services? Can I get access to the CI machine to
> > > poke around and see what's up?
> > >
> >
> > Almost certainly no, only the core maintainers are allowed shell access
> as
> > far as I've seen. You can ask on builds@apache.org for those with
> access to
> > check things out and report back and see what happens.
> >
> > I think the CI instances will be running Ubuntu 12.04 or 14.04 LTS. For
> > giggles, I dug out an ooooold Ubuntu VM with Java 6 on it and tried the
> > tests, which failed, and it indeed has no amqp[s] entry in /etc/services
> > file so that could well be it.
>
> Thanks for checking that out! I have hacked the tests to skip tests for
> 'amqps' if it is not recognized. Poke me if there are still failures.
>
> ------------------------------------------------------------------------
> r1627577 | aconway | 2014-09-25 13:59:17 -0400 (Thu, 25 Sep 2014) | 5
> lines
>
> NO-JIRA: Fix URL test to skip 'amqps' tests if 'amqps' is not recognized
> as a service name.
>
> On some older Ubuntu with Java 6, 'amqps' is not recognized as a service
> name so
> skip those tests in that case.
>
> ------------------------------------------------------------------------
>
> > >
> > > The URL code uses socket.getservbyname() to look up service names. Is
> > > there a more portable way to do it?
> > >
> >
> > No idea I'm afraid.
> >
> >
> > >
> > > Cheers,
> > > Alan.
> > >
> > > > As mentioned in my other post about a timeline for dropping Java6
> > > support,
> > > > they seem to work on Java8 (havent tried Java7).
> > > >
> > > > Robbie
> > > >
> > > > On 22 September 2014 21:14, Alan Conway <ac...@redhat.com> wrote:
> > > >
> > > > > My bad, didn't run the java tests. Will fix ASAP and then give
> myself a
> > > > > flogging.
> > > > >
> > > > > On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> > > > > > This seems to have broken the Java test runs:
> > > > > >
> > > > > >
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> > > > > >
> > > > > >
> > > > > >
> > > > > > On 19 September 2014 22:00, <ac...@apache.org> wrote:
> > > > > >
> > > > > > > Author: aconway
> > > > > > > Date: Fri Sep 19 21:00:50 2014
> > > > > > > New Revision: 1626329
> > > > > > >
> > > > > > > URL: http://svn.apache.org/r1626329
> > > > > > > Log:
> > > > > > > PROTON-693: Python Url class to wrap C function pni_parse_url
> > > > > > >
> > > > > > > It was pointed out that pni_parse_url is an internal function
> and
> > > the
> > > > > > > interface
> > > > > > > is not suitable for public API.
> > > > > > >
> > > > > > > Rewrote the URL parser as a proper swigable C API pn_url_*.
> This
> > > gets
> > > > > rid
> > > > > > > of the
> > > > > > > need for previous swig insanity and is cleaner all round.
> > > > > > >
> > > > > > > Internally still uses the pni_parse_url parser, we can clean
> that
> > > up
> > > > > later.
> > > > > > >
> > > > > > > Added:
> > > > > > >     qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > >     qpid/proton/trunk/proton-c/src/url.c
> > > > > > > Modified:
> > > > > > >     qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > >     qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > >     qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19
> 21:00:50
> > > 2014
> > > > > > > @@ -270,6 +270,7 @@ set (qpid-proton-core
> > > > > > >    src/object/iterator.c
> > > > > > >
> > > > > > >    src/util.c
> > > > > > > +  src/url.c
> > > > > > >    src/error.c
> > > > > > >    src/buffer.c
> > > > > > >    src/parser.c
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19
> > > 21:00:50
> > > > > > > 2014
> > > > > > > @@ -8,6 +8,7 @@
> > > > > > >  #include <proton/messenger.h>
> > > > > > >  #include <proton/ssl.h>
> > > > > > >  #include <proton/driver_extras.h>
> > > > > > > +#include <proton/url.h>
> > > > > > >  %}
> > > > > > >
> > > > > > >  %include <cstring.i>
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19
> > > 21:00:50
> > > > > 2014
> > > > > > > @@ -29,6 +29,7 @@
> > > > > > >  %header %{
> > > > > > >  /* Include the headers needed by the code in this wrapper
> file */
> > > > > > >  #include <proton/types.h>
> > > > > > > +#include <proton/url.h>
> > > > > > >  #include <proton/message.h>
> > > > > > >  #include <proton/driver.h>
> > > > > > >  #include <proton/driver_extras.h>
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i
> (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri
> Sep 19
> > > > > > > 21:00:50 2014
> > > > > > > @@ -23,6 +23,7 @@
> > > > > > >  #include <winsock2.h>
> > > > > > >  #endif
> > > > > > >  #include <proton/engine.h>
> > > > > > > +#include <proton/url.h>
> > > > > > >  #include <proton/message.h>
> > > > > > >  #include <proton/sasl.h>
> > > > > > >  #include <proton/driver.h>
> > > > > > > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> > > > > > >    }
> > > > > > >  %}
> > > > > > >
> > > > > > > -
> > > > > > > -/**
> > > > > > > -   pni_parse_url(char* url, char **scheme, char **user, char
> > > **pass,
> > > > > char
> > > > > > > **host, char **port, char **path)
> > > > > > > -   The following type maps convert this into a python function
> > > that
> > > > > taks
> > > > > > > a URL string argument
> > > > > > > -   and returns a list of strings [scheme, user, pass, host,
> port,
> > > > > path]
> > > > > > > -   This probably could be done more neatly.
> > > > > > > -*/
> > > > > > > -
> > > > > > > -// Typemap to copy the url string as it will be modified by
> > > parse_url
> > > > > > > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char
> *url
> > > (int
> > > > > > > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > > > > > > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > > > > > > -  if (!SWIG_IsOK(res)) {
> > > > > > > -    %argument_fail(res, "char *url", $symname, $argnum);
> > > > > > > -  }
> > > > > > > -  $1 = %new_array(n, $*1_ltype);
> > > > > > > -  memcpy($1,t,sizeof(char)*n);
> > > > > > > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > > > > > > -  $1[n-1] = 0;
> > > > > > > -}
> > > > > > > -%typemap(freearg,match="in") char *url "free($1);";
> > > > > > > -%typemap(argout) char *url "";
> > > > > > > -
> > > > > > > -// Typemap for char** return strings. Don't free them.
> > > > > > > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0)
> "$1 =
> > > > > &temp;";
> > > > > > > -%typemap(freearg,match="in") char **OUTSTR "";
> > > > > > > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char
> > > **OUTSTR {
> > > > > > > -    %append_output(SWIG_FromCharPtr(*$1));
> > > > > > > -}
> > > > > > > -
> > > > > > > -// Typemap to initialize result as empty list
> > > > > > > -%typemap(out) void "$result = PyList_New(0);";
> > > > > > > -
> > > > > > > -
> > > > > > > -%apply char** OUTSTR {char **scheme, char **user, char **pass,
> > > char
> > > > > > > **host, char **port, char **path};
> > > > > > > -void pni_parse_url(char* url, char **scheme, char **user, char
> > > **pass,
> > > > > > > char **host, char **port, char **path);
> > > > > > > -%ignore pni_parse_url;
> > > > > > > -
> > > > > > >  %include "proton/cproton.i"
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/python/proton.py
> (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri
> Sep 19
> > > > > > > 21:00:50 2014
> > > > > > > @@ -3657,114 +3657,98 @@ __all__ = [
> > > > > > >
> > > > > > >
> > > > > > >  class Url(object):
> > > > > > > -    """
> > > > > > > -    Simple URL parser/constructor, handles URLs of the form:
> > > > > > > +  """
> > > > > > > +  Simple URL parser/constructor, handles URLs of the form:
> > > > > > >
> > > > > > > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > >
> > > > > > > -    All components can be None if not specifeid in the URL
> string.
> > > > > > > +  All components can be None if not specifeid in the URL
> string.
> > > > > > >
> > > > > > > -    The port can be specified as a service name, e.g. 'amqp'
> in
> > > the
> > > > > > > -    URL string but Url.port always gives the integer value.
> > > > > > > +  The port can be specified as a service name, e.g. 'amqp' in
> the
> > > > > > > +  URL string but Url.port always gives the integer value.
> > > > > > > +
> > > > > > > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > > +  @ivar user: Username
> > > > > > > +  @ivar password: Password
> > > > > > > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > > +  @ivar port: Integer port.
> > > > > > > +  @ivar host_port: Returns host:port
> > > > > > > +  """
> > > > > > > +
> > > > > > > +  AMQPS = "amqps"
> > > > > > > +  AMQP = "amqp"
> > > > > > > +
> > > > > > > +  class Port(int):
> > > > > > > +    """An integer port number that can be constructed from a
> > > service
> > > > > name
> > > > > > > string"""
> > > > > > > +
> > > > > > > +    def __new__(cls, value):
> > > > > > > +      port = super(Url.Port, cls).__new__(cls,
> > > cls.port_int(value))
> > > > > > > +      setattr(port, 'name', str(value))
> > > > > > > +      return port
> > > > > > > +
> > > > > > > +    def __eq__(self, x): return str(self) == x or int(self)
> == x
> > > > > > > +    def __ne__(self, x): return not self == x
> > > > > > > +    def __str__(self): return str(self.name)
> > > > > > > +
> > > > > > > +    @staticmethod
> > > > > > > +    def port_int(value):
> > > > > > > +      """Convert service, an integer or a service name, into
> an
> > > > > integer
> > > > > > > port number."""
> > > > > > > +      try:
> > > > > > > +        return int(value)
> > > > > > > +      except ValueError:
> > > > > > > +        try:
> > > > > > > +          return socket.getservbyname(value)
> > > > > > > +        except socket.error:
> > > > > > > +          raise ValueError("Not a valid port number or service
> > > name:
> > > > > > > '%s'" % value)
> > > > > > >
> > > > > > > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > > -    @ivar user: Username
> > > > > > > -    @ivar password: Password
> > > > > > > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > > -    @ivar port: Integer port.
> > > > > > > -    @ivar host_port: Returns host:port
> > > > > > > +  def __init__(self, url=None, **kwargs):
> > > > > > > +    """
> > > > > > > +    @param url: URL string to parse.
> > > > > > > +    @param kwargs: scheme, user, password, host, port, path.
> > > > > > > +      If specified, replaces corresponding part in url string.
> > > > > > >      """
> > > > > > > +    if url:
> > > > > > > +      self._url = pn_url_parse(str(url))
> > > > > > > +      if not self._url: raise ValueError("Invalid URL '%s'" %
> url)
> > > > > > > +    else:
> > > > > > > +      self._url = pn_url()
> > > > > > > +    for k in kwargs:            # Let kwargs override values
> > > parsed
> > > > > from
> > > > > > > url
> > > > > > > +      getattr(self, k)          # Check for invalid kwargs
> > > > > > > +      setattr(self, k, kwargs[k])
> > > > > > > +
> > > > > > > +  class PartDescriptor(object):
> > > > > > > +    def __init__(self, part):
> > > > > > > +      self.getter = globals()["pn_url_%s" % part]
> > > > > > > +      self.setter = globals()["pn_url_set_%s" % part]
> > > > > > > +    def __get__(self, obj, type=None): return
> > > self.getter(obj._url)
> > > > > > > +    def __set__(self, obj, value): return
> self.setter(obj._url,
> > > > > > > str(value))
> > > > > > > +
> > > > > > > +  scheme = PartDescriptor('scheme')
> > > > > > > +  username = PartDescriptor('username')
> > > > > > > +  password = PartDescriptor('password')
> > > > > > > +  host = PartDescriptor('host')
> > > > > > > +  path = PartDescriptor('path')
> > > > > > > +
> > > > > > > +  @property
> > > > > > > +  def port(self):
> > > > > > > +    portstr = pn_url_port(self._url)
> > > > > > > +    return portstr and Url.Port(portstr)
> > > > > > > +
> > > > > > > +  @port.setter
> > > > > > > +  def port(self, value):
> > > > > > > +    if value is None: pn_url_set_port(self._url, None)
> > > > > > > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> > > > > > >
> > > > > > > -    AMQPS = "amqps"
> > > > > > > -    AMQP = "amqp"
> > > > > > > +  def __str__(self): return pn_url_str(self._url)
> > > > > > >
> > > > > > > -    class Port(int):
> > > > > > > -      """An integer port number that can also have an
> associated
> > > > > service
> > > > > > > name string"""
> > > > > > > +  def __repr__(self): return "Url(%r)" % str(self)
> > > > > > >
> > > > > > > -      def __new__(cls, value):
> > > > > > > -        port = super(Url.Port, cls).__new__(cls,
> > > cls.port_int(value))
> > > > > > > -        setattr(port, 'name', str(value))
> > > > > > > -        return port
> > > > > > > -
> > > > > > > -      def __eq__(self, x): return str(self) == x or int(self)
> == x
> > > > > > > -      def __ne__(self, x): return not self == x
> > > > > > > -      def __str__(self): return str(self.name)
> > > > > > > -
> > > > > > > -      @staticmethod
> > > > > > > -      def port_int(value):
> > > > > > > -        """Convert service, an integer or a service name,
> into an
> > > > > integer
> > > > > > > port number."""
> > > > > > > -        try:
> > > > > > > -          return int(value)
> > > > > > > -        except ValueError:
> > > > > > > -          try:
> > > > > > > -            return socket.getservbyname(value)
> > > > > > > -          except socket.error:
> > > > > > > -            raise ValueError("Not a valid port number or
> service
> > > name:
> > > > > > > '%s'" % value)
> > > > > > > -
> > > > > > > -    def __init__(self, url=None, **kwargs):
> > > > > > > -        """
> > > > > > > -        @param url: String or Url instance to parse or copy.
> > > > > > > -        @param kwargs: URL fields: scheme, user, password,
> host,
> > > port,
> > > > > > > path.
> > > > > > > -            If specified, replaces corresponding component in
> url.
> > > > > > > -        """
> > > > > > > -
> > > > > > > -        fields = ['scheme', 'user', 'password', 'host',
> 'port',
> > > > > 'path']
> > > > > > > -
> > > > > > > -        for f in fields: setattr(self, f, None)
> > > > > > > -        for k in kwargs: getattr(self, k) # Check for invalid
> > > kwargs
> > > > > > > -
> > > > > > > -        if isinstance(url, Url): # Copy from another Url
> instance.
> > > > > > > -            self.__dict__.update(url.__dict__)
> > > > > > > -        elif url is not None:   # Parse from url
> > > > > > > -            parts = pni_parse_url(str(url))
> > > > > > > -            if not filter(None, parts): raise
> ValueError("Invalid
> > > AMQP
> > > > > > > URL: '%s'" % url)
> > > > > > > -            self.scheme, self.user, self.password, self.host,
> > > port,
> > > > > > > self.path = parts
> > > > > > > -            if not self.host: self.host = None
> > > > > > > -            self.port = port and self.Port(port)
> > > > > > > -
> > > > > > > -        # Let kwargs override values previously set from url
> > > > > > > -        for field in fields:
> > > > > > > -            setattr(self, field, kwargs.get(field,
> getattr(self,
> > > > > field)))
> > > > > > > -
> > > > > > > -    def __repr__(self):
> > > > > > > -        return "Url(%r)" % str(self)
> > > > > > > -
> > > > > > > -    def __str__(self):
> > > > > > > -        s = ""
> > > > > > > -        if self.scheme:
> > > > > > > -            s += "%s://" % self.scheme
> > > > > > > -        if self.user:
> > > > > > > -            s += self.user
> > > > > > > -        if self.password:
> > > > > > > -            s += ":%s" % self.password
> > > > > > > -        if self.user or self.password:
> > > > > > > -            s += '@'
> > > > > > > -        if self.host and ':' in self.host:
> > > > > > > -            s += "[%s]" % self.host
> > > > > > > -        elif self.host:
> > > > > > > -            s += self.host
> > > > > > > -        if self.port:
> > > > > > > -            s += ":%s" % self.port
> > > > > > > -        if self.path:
> > > > > > > -            s += "/%s" % self.path
> > > > > > > -        return s
> > > > > > > -
> > > > > > > -    def __eq__(self, url):
> > > > > > > -        return \
> > > > > > > -            self.scheme == url.scheme and \
> > > > > > > -            self.user == url.user and self.password ==
> > > url.password
> > > > > and \
> > > > > > > -            self.host == url.host and self.port == url.port
> and \
> > > > > > > -            self.path == url.path
> > > > > > > -
> > > > > > > -    def __ne__(self, url):
> > > > > > > -        return not self.__eq__(url)
> > > > > > > -
> > > > > > > -    def defaults(self):
> > > > > > > -        """
> > > > > > > -        Fill in missing values with defaults
> > > > > > > -        @return: self
> > > > > > > -        """
> > > > > > > -        self.scheme = self.scheme or self.AMQP
> > > > > > > -        self.host = self.host or '0.0.0.0'
> > > > > > > -        self.port = self.port or self.Port(self.scheme)
> > > > > > > -        return self
> > > > > > > +  def defaults(self):
> > > > > > > +    """
> > > > > > > +    Fill in missing values (scheme, host or port) with
> defaults
> > > > > > > +    @return: self
> > > > > > > +    """
> > > > > > > +    self.scheme = self.scheme or self.AMQP
> > > > > > > +    self.host = self.host or '0.0.0.0'
> > > > > > > +    self.port = self.port or self.Port(self.scheme)
> > > > > > > +    return self
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19
> > > 21:00:50
> > > > > > > 2014
> > > > > > > @@ -26,8 +26,8 @@
> > > > > > >  #include <proton/messenger.h>
> > > > > > >  #include <proton/ssl.h>
> > > > > > >  #include <proton/driver_extras.h>
> > > > > > > -
> > > > > > >  #include <proton/types.h>
> > > > > > > +#include <proton/url.h>
> > > > > > >
> > > > > > >  #include <uuid/uuid.h>
> > > > > > >  %}
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/include/proton/cproton.i
> (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri
> Sep 19
> > > > > > > 21:00:50 2014
> > > > > > > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> > > > > > >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return
> > > (pn_delivery_t
> > > > > *)
> > > > > > > x; }
> > > > > > >    pn_transport_t *pn_cast_pn_transport(void *x) { return
> > > > > (pn_transport_t
> > > > > > > *) x; }
> > > > > > >  %}
> > > > > > > +
> > > > > > > +%include "proton/url.h"
> > > > > > > +
> > > > > > >
> > > > > > > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > > > > > > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19
> > > 21:00:50
> > > > > > > 2014
> > > > > > > @@ -0,0 +1,83 @@
> > > > > > > +#ifndef PROTON_URL_H
> > > > > > > +#define PROTON_URL_H
> > > > > > > +/*
> > > > > > > + * 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.
> > > > > > > + */
> > > > > > > +
> > > > > > > +#include <proton/import_export.h>
> > > > > > > +
> > > > > > > +/** @file
> > > > > > > + * URL API for parsing URLs.
> > > > > > > + *
> > > > > > > + * @defgroup url URL
> > > > > > > + * @{
> > > > > > > + */
> > > > > > > +
> > > > > > > +/** A parsed URL */
> > > > > > > +typedef struct pn_url_t pn_url_t;
> > > > > > > +
> > > > > > > +/** Create an empty URL */
> > > > > > > +PN_EXTERN pn_url_t *pn_url(void);
> > > > > > > +
> > > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > > + *@param[in] url A URL string.
> > > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid
> URL
> > > > > string.
> > > > > > > + */
> > > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > > > > > > +
> > > > > > > +/** Free a URL */
> > > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > > > > > > +
> > > > > > > +/** Clear the contents of the URL. */
> > > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > > > > > > +
> > > > > > > +/** Return the string form of a URL. Owned by the pn_url_t.*/
> > > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > > > > > > +
> > > > > > > +/**
> > > > > > > + *@name Getters for parts of the URL.
> > > > > > > + *
> > > > > > > + *Values belong to the URL. May return NULL if the value is
> not
> > > set.
> > > > > > > + *
> > > > > > > + *@{
> > > > > > > + */
> > > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > > > > > > +///@}
> > > > > > > +
> > > > > > > +/**
> > > > > > > + *@name Setters for parts of the URL.
> > > > > > > + *
> > > > > > > + *Values are copied. Value can be NULL to indicate the part
> is not
> > > > > set.
> > > > > > > + *
> > > > > > > + *@{
> > > > > > > + */
> > > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > > *scheme);
> > > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > > *username);
> > > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > > *password);
> > > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char
> *host);
> > > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char
> *port);
> > > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char
> *path);
> > > > > > > +///@}
> > > > > > > +
> > > > > > > +///@}
> > > > > > > +#endif
> > > > > > >
> > > > > > > Added: qpid/proton/trunk/proton-c/src/url.c
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > > > > > > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50
> 2014
> > > > > > > @@ -0,0 +1,127 @@
> > > > > > > +/*
> > > > > > > + *
> > > > > > > + * 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.
> > > > > > > + *
> > > > > > > + */
> > > > > > > +
> > > > > > > +#include <proton/url.h>
> > > > > > > +#include <proton/util.h>
> > > > > > > +#include <stdlib.h>
> > > > > > > +#include <string.h>
> > > > > > > +#include <stdio.h>
> > > > > > > +
> > > > > > > +static char* copy(const char* str) {
> > > > > > > +    if (str ==  NULL) return NULL;
> > > > > > > +    char *str2 = (char*)malloc(strlen(str));
> > > > > > > +    if (str2) strcpy(str2, str);
> > > > > > > +    return str2;
> > > > > > > +}
> > > > > > > +
> > > > > > > +struct pn_url_t {
> > > > > > > +    char *scheme;
> > > > > > > +    char *username;
> > > > > > > +    char *password;
> > > > > > > +    char *host;
> > > > > > > +    char *port;
> > > > > > > +    char *path;
> > > > > > > +    char *str;
> > > > > > > +};
> > > > > > > +
> > > > > > > +PN_EXTERN pn_url_t *pn_url() {
> > > > > > > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > > > > > > +    memset(url, 0, sizeof(*url));
> > > > > > > +    return url;
> > > > > > > +}
> > > > > > > +
> > > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > > + *@param[in] url A URL string.
> > > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid
> URL
> > > > > string.
> > > > > > > + */
> > > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > > > > > > +    if (!str || !*str)          /* Empty string or NULL is
> > > illegal. */
> > > > > > > +        return NULL;
> > > > > > > +
> > > > > > > +    pn_url_t *url = pn_url();
> > > > > > > +    char *str2 = copy(str);         /* FIXME aconway
> 2014-09-19:
> > > > > clean up
> > > > > > > */
> > > > > > > +    pni_parse_url(str2, &url->scheme, &url->username,
> > > &url->password,
> > > > > > > &url->host, &url->port, &url->path);
> > > > > > > +    url->scheme = copy(url->scheme);
> > > > > > > +    url->username = copy(url->username);
> > > > > > > +    url->password = copy(url->password);
> > > > > > > +    url->host = (url->host && !*url->host) ? NULL :
> > > copy(url->host);
> > > > > > > +    url->port = copy(url->port);
> > > > > > > +    url->path = copy(url->path);
> > > > > > > +    return url;
> > > > > > > +}
> > > > > > > +
> > > > > > > +/** Free a URL */
> > > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > > > > > > +    pn_url_clear(url);
> > > > > > > +    free(url);
> > > > > > > +}
> > > > > > > +
> > > > > > > +/** Clear the contents of the URL. */
> > > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > > > > > > +    pn_url_set_username(url, NULL);
> > > > > > > +    pn_url_set_password(url, NULL);
> > > > > > > +    pn_url_set_host(url, NULL);
> > > > > > > +    pn_url_set_port(url, NULL);
> > > > > > > +    pn_url_set_path(url, NULL);
> > > > > > > +    free(url->str); url->str = NULL;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static inline int len(const char *str) { return str ?
> strlen(str)
> > > :
> > > > > 0; }
> > > > > > > +
> > > > > > > +/** Return the string form of a URL. */
> > > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > > > > > > +    int size = len(url->scheme) + len(url->username) +
> > > > > len(url->password)
> > > > > > > +        + len(url->host) + len(url->port) + len(url->path)
> > > > > > > +        + len("s://u:p@[h]:p/p");
> > > > > > > +    free(url->str);
> > > > > > > +    url->str = (char*)malloc(size);
> > > > > > > +    if (!url->str) return NULL;
> > > > > > > +
> > > > > > > +    int i = 0;
> > > > > > > +    if (url->scheme) i += snprintf(url->str+i, size-i,
> "%s://",
> > > > > > > url->scheme);
> > > > > > > +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> > > > > > > url->username);
> > > > > > > +    if (url->password) i += snprintf(url->str+i, size-i,
> ":%s",
> > > > > > > url->password);
> > > > > > > +    if (url->username || url->password) i +=
> snprintf(url->str+i,
> > > > > size-i,
> > > > > > > "@");
> > > > > > > +    if (url->host) {
> > > > > > > +        if (strchr(url->host, ':')) i += snprintf(url->str+i,
> > > size-i,
> > > > > > > "[%s]", url->host);
> > > > > > > +        else i += snprintf(url->str+i, size-i, "%s",
> url->host);
> > > > > > > +    }
> > > > > > > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
> > > > > url->port);
> > > > > > > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
> > > > > url->path);
> > > > > > > +    return url->str;
> > > > > > > +}
> > > > > > > +
> > > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
> > > > > url->scheme; }
> > > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> > > > > > > url->username; }
> > > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> > > > > > > url->password; }
> > > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return
> > > url->host; }
> > > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return
> > > url->port; }
> > > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return
> > > url->path; }
> > > > > > > +
> > > > > > > +#define SET(part) free(url->part); url->part = copy(part)
> > > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > > *scheme) {
> > > > > > > SET(scheme); }
> > > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > > *username) {
> > > > > > > SET(username); }
> > > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > > *password) {
> > > > > > > SET(password); }
> > > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char
> *host) {
> > > > > > > SET(host); }
> > > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char
> *port) {
> > > > > > > SET(port); }
> > > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char
> *path) {
> > > > > > > SET(path); }
> > > > > > > +
> > > > > > > +
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/tests/python/proton_tests/url.py
> (original)
> > > > > > > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep
> 19
> > > > > 21:00:50
> > > > > > > 2014
> > > > > > > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> > > > > > >      def assertNotEqual(self, a, b):
> > > > > > >          assert a != b, "%s == %s" % (a, b)
> > > > > > >
> > > > > > > -    def assertUrl(self, u, scheme, user, password, host, port,
> > > path):
> > > > > > > -        self.assertEqual((u.scheme, u.user, u.password,
> u.host,
> > > > > u.port,
> > > > > > > u.path),
> > > > > > > -                         (scheme, user, password, host, port,
> > > path))
> > > > > > > +    def assertUrl(self, u, scheme, username, password, host,
> port,
> > > > > path):
> > > > > > > +        self.assertEqual((u.scheme, u.username, u.password,
> > > u.host,
> > > > > > > u.port, u.path),
> > > > > > > +                         (scheme, username, password, host,
> port,
> > > > > path))
> > > > > > >
> > > > > > >      def testUrl(self):
> > > > > > >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > > > > > > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> > > > > > >
> > > > > > >      def testDefaults(self):
> > > > > > >          # Check that we allow None for scheme, port
> > > > > > > -        url = Url(user='me', password='secret', host='myhost',
> > > > > > > path='foobar')
> > > > > > > +        url = Url(username='me', password='secret',
> host='myhost',
> > > > > > > path='foobar')
> > > > > > >          self.assertEqual(str(url), "me:secret@myhost/foobar")
> > > > > > >          self.assertUrl(url, None, 'me', 'secret', 'myhost',
> None,
> > > > > > > 'foobar')
> > > > > > >
> > > > > > > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> > > > > > >      def testMissing(self):
> > > > > > >          self.assertUrl(Url(), None, None, None, None, None,
> None)
> > > > > > >          self.assertUrl(Url('amqp://'), 'amqp', None, None,
> None,
> > > None,
> > > > > > > None)
> > > > > > > -        self.assertUrl(Url('user@'), None, 'user', None,
> None,
> > > None,
> > > > > > > None)
> > > > > > > +        self.assertUrl(Url('username@'), None, 'username',
> None,
> > > > > None,
> > > > > > > None, None)
> > > > > > >          self.assertUrl(Url(':pass@'), None, '', 'pass', None,
> > > None,
> > > > > None)
> > > > > > >          self.assertUrl(Url('host'), None, None, None, 'host',
> > > None,
> > > > > None)
> > > > > > >          self.assertUrl(Url(':1234'), None, None, None, None,
> 1234,
> > > > > None)
> > > > > > >          self.assertUrl(Url('/path'), None, None, None, None,
> None,
> > > > > 'path')
> > > > > > >
> > > > > > > -        for s in ['amqp://', 'user@', ':pass@', ':1234',
> > > '/path']:
> > > > > > > +        for s in ['amqp://', 'username@', ':pass@', ':1234',
> > > > > '/path']:
> > > > > > >              self.assertEqual(s, str(Url(s)))
> > > > > > >
> > > > > > >          for s, full in [
> > > > > > >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > > > > > > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > > > > > > +                ('username@', 'amqp://username@0.0.0.0:
> amqp'),
> > > > > > >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> > > > > > >                  (':1234', 'amqp://0.0.0.0:1234'),
> > > > > > >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> > > > > > >              self.assertEqual(str(Url(s).defaults()), full)
> > > > > > > -
> > > > > > > -        self.assertRaises(ValueError, Url, '')
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >
> > > ---------------------------------------------------------------------
> > > > > > > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > > > > > > For additional commands, e-mail: commits-help@qpid.apache.org
> > > > > > >
> > > > > > >
> > > > >
> > > > >
> > > > >
> > > > >
> ---------------------------------------------------------------------
> > > > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > > > For additional commands, e-mail: dev-help@qpid.apache.org
> > > > >
> > > > >
> > >
> > >
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > For additional commands, e-mail: dev-help@qpid.apache.org
> > >
> > >
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> For additional commands, e-mail: dev-help@qpid.apache.org
>
>

Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Robbie Gemmell <ro...@gmail.com>.
Failing in a different way now, the overall run of the python tests bombs
out. I see the same thing locally, where it was working when I made the
commit immediately before yours :)

https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/683/console

Running org.apache.qpid.proton.JythonTest
Sep 25, 2014 6:03:44 PM org.apache.qpid.proton.JythonTest test
INFO: About to call Jython test script:
'/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test'
with '/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python'
added to Jython path
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 7.714
sec <<< FAILURE!
test(org.apache.qpid.proton.JythonTest)  Time elapsed: 7.675 sec  <<< FAILURE!
java.lang.AssertionError: Caught PyException on invocation number 2:
Traceback (most recent call last):
  File "/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test",
line 597, in <module>
    h.scan(m)
  File "/home/jenkins/jenkins-slave/workspace/Qpid-proton-j/trunk/tests/python/proton-test",
line 587, in scan
    if not (child in self.scanned or child in objects):
TypeError: object of type 'object' has no len()
 with message: null
	at org.junit.Assert.fail(Assert.java:93)
	at org.apache.qpid.proton.JythonTest.runTestOnce(JythonTest.java:120)
	at org.apache.qpid.proton.JythonTest.test(JythonTest.java:95)


On 25 September 2014 18:59, Alan Conway <ac...@redhat.com> wrote:

> On Thu, 2014-09-25 at 15:59 +0100, Robbie Gemmell wrote:
> > On 25 September 2014 15:00, Alan Conway <ac...@redhat.com> wrote:
> >
> > > On Wed, 2014-09-24 at 12:19 +0100, Robbie Gemmell wrote:
> > > > The tests are now running again, but a couple of the URL tests still
> seem
> > > > to be failing on the CI job:
> > > >
> > >
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/
> > > >
> > >
> > > They are all failing with:
> > >  Not a valid port number or service name: 'amqps'
> > >
> > > Could this be a configuration problem on the CI machine, i.e. missing
> an
> > > 'amqps' entry in /etc/services? Can I get access to the CI machine to
> > > poke around and see what's up?
> > >
> >
> > Almost certainly no, only the core maintainers are allowed shell access
> as
> > far as I've seen. You can ask on builds@apache.org for those with
> access to
> > check things out and report back and see what happens.
> >
> > I think the CI instances will be running Ubuntu 12.04 or 14.04 LTS. For
> > giggles, I dug out an ooooold Ubuntu VM with Java 6 on it and tried the
> > tests, which failed, and it indeed has no amqp[s] entry in /etc/services
> > file so that could well be it.
>
> Thanks for checking that out! I have hacked the tests to skip tests for
> 'amqps' if it is not recognized. Poke me if there are still failures.
>
> ------------------------------------------------------------------------
> r1627577 | aconway | 2014-09-25 13:59:17 -0400 (Thu, 25 Sep 2014) | 5
> lines
>
> NO-JIRA: Fix URL test to skip 'amqps' tests if 'amqps' is not recognized
> as a service name.
>
> On some older Ubuntu with Java 6, 'amqps' is not recognized as a service
> name so
> skip those tests in that case.
>
> ------------------------------------------------------------------------
>
> > >
> > > The URL code uses socket.getservbyname() to look up service names. Is
> > > there a more portable way to do it?
> > >
> >
> > No idea I'm afraid.
> >
> >
> > >
> > > Cheers,
> > > Alan.
> > >
> > > > As mentioned in my other post about a timeline for dropping Java6
> > > support,
> > > > they seem to work on Java8 (havent tried Java7).
> > > >
> > > > Robbie
> > > >
> > > > On 22 September 2014 21:14, Alan Conway <ac...@redhat.com> wrote:
> > > >
> > > > > My bad, didn't run the java tests. Will fix ASAP and then give
> myself a
> > > > > flogging.
> > > > >
> > > > > On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> > > > > > This seems to have broken the Java test runs:
> > > > > >
> > > > > >
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> > > > > >
> > > > > >
> > > > > >
> > > > > > On 19 September 2014 22:00, <ac...@apache.org> wrote:
> > > > > >
> > > > > > > Author: aconway
> > > > > > > Date: Fri Sep 19 21:00:50 2014
> > > > > > > New Revision: 1626329
> > > > > > >
> > > > > > > URL: http://svn.apache.org/r1626329
> > > > > > > Log:
> > > > > > > PROTON-693: Python Url class to wrap C function pni_parse_url
> > > > > > >
> > > > > > > It was pointed out that pni_parse_url is an internal function
> and
> > > the
> > > > > > > interface
> > > > > > > is not suitable for public API.
> > > > > > >
> > > > > > > Rewrote the URL parser as a proper swigable C API pn_url_*.
> This
> > > gets
> > > > > rid
> > > > > > > of the
> > > > > > > need for previous swig insanity and is cleaner all round.
> > > > > > >
> > > > > > > Internally still uses the pni_parse_url parser, we can clean
> that
> > > up
> > > > > later.
> > > > > > >
> > > > > > > Added:
> > > > > > >     qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > >     qpid/proton/trunk/proton-c/src/url.c
> > > > > > > Modified:
> > > > > > >     qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > >     qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > >     qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19
> 21:00:50
> > > 2014
> > > > > > > @@ -270,6 +270,7 @@ set (qpid-proton-core
> > > > > > >    src/object/iterator.c
> > > > > > >
> > > > > > >    src/util.c
> > > > > > > +  src/url.c
> > > > > > >    src/error.c
> > > > > > >    src/buffer.c
> > > > > > >    src/parser.c
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19
> > > 21:00:50
> > > > > > > 2014
> > > > > > > @@ -8,6 +8,7 @@
> > > > > > >  #include <proton/messenger.h>
> > > > > > >  #include <proton/ssl.h>
> > > > > > >  #include <proton/driver_extras.h>
> > > > > > > +#include <proton/url.h>
> > > > > > >  %}
> > > > > > >
> > > > > > >  %include <cstring.i>
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19
> > > 21:00:50
> > > > > 2014
> > > > > > > @@ -29,6 +29,7 @@
> > > > > > >  %header %{
> > > > > > >  /* Include the headers needed by the code in this wrapper
> file */
> > > > > > >  #include <proton/types.h>
> > > > > > > +#include <proton/url.h>
> > > > > > >  #include <proton/message.h>
> > > > > > >  #include <proton/driver.h>
> > > > > > >  #include <proton/driver_extras.h>
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i
> (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri
> Sep 19
> > > > > > > 21:00:50 2014
> > > > > > > @@ -23,6 +23,7 @@
> > > > > > >  #include <winsock2.h>
> > > > > > >  #endif
> > > > > > >  #include <proton/engine.h>
> > > > > > > +#include <proton/url.h>
> > > > > > >  #include <proton/message.h>
> > > > > > >  #include <proton/sasl.h>
> > > > > > >  #include <proton/driver.h>
> > > > > > > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> > > > > > >    }
> > > > > > >  %}
> > > > > > >
> > > > > > > -
> > > > > > > -/**
> > > > > > > -   pni_parse_url(char* url, char **scheme, char **user, char
> > > **pass,
> > > > > char
> > > > > > > **host, char **port, char **path)
> > > > > > > -   The following type maps convert this into a python function
> > > that
> > > > > taks
> > > > > > > a URL string argument
> > > > > > > -   and returns a list of strings [scheme, user, pass, host,
> port,
> > > > > path]
> > > > > > > -   This probably could be done more neatly.
> > > > > > > -*/
> > > > > > > -
> > > > > > > -// Typemap to copy the url string as it will be modified by
> > > parse_url
> > > > > > > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char
> *url
> > > (int
> > > > > > > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > > > > > > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > > > > > > -  if (!SWIG_IsOK(res)) {
> > > > > > > -    %argument_fail(res, "char *url", $symname, $argnum);
> > > > > > > -  }
> > > > > > > -  $1 = %new_array(n, $*1_ltype);
> > > > > > > -  memcpy($1,t,sizeof(char)*n);
> > > > > > > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > > > > > > -  $1[n-1] = 0;
> > > > > > > -}
> > > > > > > -%typemap(freearg,match="in") char *url "free($1);";
> > > > > > > -%typemap(argout) char *url "";
> > > > > > > -
> > > > > > > -// Typemap for char** return strings. Don't free them.
> > > > > > > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0)
> "$1 =
> > > > > &temp;";
> > > > > > > -%typemap(freearg,match="in") char **OUTSTR "";
> > > > > > > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char
> > > **OUTSTR {
> > > > > > > -    %append_output(SWIG_FromCharPtr(*$1));
> > > > > > > -}
> > > > > > > -
> > > > > > > -// Typemap to initialize result as empty list
> > > > > > > -%typemap(out) void "$result = PyList_New(0);";
> > > > > > > -
> > > > > > > -
> > > > > > > -%apply char** OUTSTR {char **scheme, char **user, char **pass,
> > > char
> > > > > > > **host, char **port, char **path};
> > > > > > > -void pni_parse_url(char* url, char **scheme, char **user, char
> > > **pass,
> > > > > > > char **host, char **port, char **path);
> > > > > > > -%ignore pni_parse_url;
> > > > > > > -
> > > > > > >  %include "proton/cproton.i"
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/python/proton.py
> (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri
> Sep 19
> > > > > > > 21:00:50 2014
> > > > > > > @@ -3657,114 +3657,98 @@ __all__ = [
> > > > > > >
> > > > > > >
> > > > > > >  class Url(object):
> > > > > > > -    """
> > > > > > > -    Simple URL parser/constructor, handles URLs of the form:
> > > > > > > +  """
> > > > > > > +  Simple URL parser/constructor, handles URLs of the form:
> > > > > > >
> > > > > > > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > >
> > > > > > > -    All components can be None if not specifeid in the URL
> string.
> > > > > > > +  All components can be None if not specifeid in the URL
> string.
> > > > > > >
> > > > > > > -    The port can be specified as a service name, e.g. 'amqp'
> in
> > > the
> > > > > > > -    URL string but Url.port always gives the integer value.
> > > > > > > +  The port can be specified as a service name, e.g. 'amqp' in
> the
> > > > > > > +  URL string but Url.port always gives the integer value.
> > > > > > > +
> > > > > > > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > > +  @ivar user: Username
> > > > > > > +  @ivar password: Password
> > > > > > > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > > +  @ivar port: Integer port.
> > > > > > > +  @ivar host_port: Returns host:port
> > > > > > > +  """
> > > > > > > +
> > > > > > > +  AMQPS = "amqps"
> > > > > > > +  AMQP = "amqp"
> > > > > > > +
> > > > > > > +  class Port(int):
> > > > > > > +    """An integer port number that can be constructed from a
> > > service
> > > > > name
> > > > > > > string"""
> > > > > > > +
> > > > > > > +    def __new__(cls, value):
> > > > > > > +      port = super(Url.Port, cls).__new__(cls,
> > > cls.port_int(value))
> > > > > > > +      setattr(port, 'name', str(value))
> > > > > > > +      return port
> > > > > > > +
> > > > > > > +    def __eq__(self, x): return str(self) == x or int(self)
> == x
> > > > > > > +    def __ne__(self, x): return not self == x
> > > > > > > +    def __str__(self): return str(self.name)
> > > > > > > +
> > > > > > > +    @staticmethod
> > > > > > > +    def port_int(value):
> > > > > > > +      """Convert service, an integer or a service name, into
> an
> > > > > integer
> > > > > > > port number."""
> > > > > > > +      try:
> > > > > > > +        return int(value)
> > > > > > > +      except ValueError:
> > > > > > > +        try:
> > > > > > > +          return socket.getservbyname(value)
> > > > > > > +        except socket.error:
> > > > > > > +          raise ValueError("Not a valid port number or service
> > > name:
> > > > > > > '%s'" % value)
> > > > > > >
> > > > > > > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > > -    @ivar user: Username
> > > > > > > -    @ivar password: Password
> > > > > > > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > > -    @ivar port: Integer port.
> > > > > > > -    @ivar host_port: Returns host:port
> > > > > > > +  def __init__(self, url=None, **kwargs):
> > > > > > > +    """
> > > > > > > +    @param url: URL string to parse.
> > > > > > > +    @param kwargs: scheme, user, password, host, port, path.
> > > > > > > +      If specified, replaces corresponding part in url string.
> > > > > > >      """
> > > > > > > +    if url:
> > > > > > > +      self._url = pn_url_parse(str(url))
> > > > > > > +      if not self._url: raise ValueError("Invalid URL '%s'" %
> url)
> > > > > > > +    else:
> > > > > > > +      self._url = pn_url()
> > > > > > > +    for k in kwargs:            # Let kwargs override values
> > > parsed
> > > > > from
> > > > > > > url
> > > > > > > +      getattr(self, k)          # Check for invalid kwargs
> > > > > > > +      setattr(self, k, kwargs[k])
> > > > > > > +
> > > > > > > +  class PartDescriptor(object):
> > > > > > > +    def __init__(self, part):
> > > > > > > +      self.getter = globals()["pn_url_%s" % part]
> > > > > > > +      self.setter = globals()["pn_url_set_%s" % part]
> > > > > > > +    def __get__(self, obj, type=None): return
> > > self.getter(obj._url)
> > > > > > > +    def __set__(self, obj, value): return
> self.setter(obj._url,
> > > > > > > str(value))
> > > > > > > +
> > > > > > > +  scheme = PartDescriptor('scheme')
> > > > > > > +  username = PartDescriptor('username')
> > > > > > > +  password = PartDescriptor('password')
> > > > > > > +  host = PartDescriptor('host')
> > > > > > > +  path = PartDescriptor('path')
> > > > > > > +
> > > > > > > +  @property
> > > > > > > +  def port(self):
> > > > > > > +    portstr = pn_url_port(self._url)
> > > > > > > +    return portstr and Url.Port(portstr)
> > > > > > > +
> > > > > > > +  @port.setter
> > > > > > > +  def port(self, value):
> > > > > > > +    if value is None: pn_url_set_port(self._url, None)
> > > > > > > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> > > > > > >
> > > > > > > -    AMQPS = "amqps"
> > > > > > > -    AMQP = "amqp"
> > > > > > > +  def __str__(self): return pn_url_str(self._url)
> > > > > > >
> > > > > > > -    class Port(int):
> > > > > > > -      """An integer port number that can also have an
> associated
> > > > > service
> > > > > > > name string"""
> > > > > > > +  def __repr__(self): return "Url(%r)" % str(self)
> > > > > > >
> > > > > > > -      def __new__(cls, value):
> > > > > > > -        port = super(Url.Port, cls).__new__(cls,
> > > cls.port_int(value))
> > > > > > > -        setattr(port, 'name', str(value))
> > > > > > > -        return port
> > > > > > > -
> > > > > > > -      def __eq__(self, x): return str(self) == x or int(self)
> == x
> > > > > > > -      def __ne__(self, x): return not self == x
> > > > > > > -      def __str__(self): return str(self.name)
> > > > > > > -
> > > > > > > -      @staticmethod
> > > > > > > -      def port_int(value):
> > > > > > > -        """Convert service, an integer or a service name,
> into an
> > > > > integer
> > > > > > > port number."""
> > > > > > > -        try:
> > > > > > > -          return int(value)
> > > > > > > -        except ValueError:
> > > > > > > -          try:
> > > > > > > -            return socket.getservbyname(value)
> > > > > > > -          except socket.error:
> > > > > > > -            raise ValueError("Not a valid port number or
> service
> > > name:
> > > > > > > '%s'" % value)
> > > > > > > -
> > > > > > > -    def __init__(self, url=None, **kwargs):
> > > > > > > -        """
> > > > > > > -        @param url: String or Url instance to parse or copy.
> > > > > > > -        @param kwargs: URL fields: scheme, user, password,
> host,
> > > port,
> > > > > > > path.
> > > > > > > -            If specified, replaces corresponding component in
> url.
> > > > > > > -        """
> > > > > > > -
> > > > > > > -        fields = ['scheme', 'user', 'password', 'host',
> 'port',
> > > > > 'path']
> > > > > > > -
> > > > > > > -        for f in fields: setattr(self, f, None)
> > > > > > > -        for k in kwargs: getattr(self, k) # Check for invalid
> > > kwargs
> > > > > > > -
> > > > > > > -        if isinstance(url, Url): # Copy from another Url
> instance.
> > > > > > > -            self.__dict__.update(url.__dict__)
> > > > > > > -        elif url is not None:   # Parse from url
> > > > > > > -            parts = pni_parse_url(str(url))
> > > > > > > -            if not filter(None, parts): raise
> ValueError("Invalid
> > > AMQP
> > > > > > > URL: '%s'" % url)
> > > > > > > -            self.scheme, self.user, self.password, self.host,
> > > port,
> > > > > > > self.path = parts
> > > > > > > -            if not self.host: self.host = None
> > > > > > > -            self.port = port and self.Port(port)
> > > > > > > -
> > > > > > > -        # Let kwargs override values previously set from url
> > > > > > > -        for field in fields:
> > > > > > > -            setattr(self, field, kwargs.get(field,
> getattr(self,
> > > > > field)))
> > > > > > > -
> > > > > > > -    def __repr__(self):
> > > > > > > -        return "Url(%r)" % str(self)
> > > > > > > -
> > > > > > > -    def __str__(self):
> > > > > > > -        s = ""
> > > > > > > -        if self.scheme:
> > > > > > > -            s += "%s://" % self.scheme
> > > > > > > -        if self.user:
> > > > > > > -            s += self.user
> > > > > > > -        if self.password:
> > > > > > > -            s += ":%s" % self.password
> > > > > > > -        if self.user or self.password:
> > > > > > > -            s += '@'
> > > > > > > -        if self.host and ':' in self.host:
> > > > > > > -            s += "[%s]" % self.host
> > > > > > > -        elif self.host:
> > > > > > > -            s += self.host
> > > > > > > -        if self.port:
> > > > > > > -            s += ":%s" % self.port
> > > > > > > -        if self.path:
> > > > > > > -            s += "/%s" % self.path
> > > > > > > -        return s
> > > > > > > -
> > > > > > > -    def __eq__(self, url):
> > > > > > > -        return \
> > > > > > > -            self.scheme == url.scheme and \
> > > > > > > -            self.user == url.user and self.password ==
> > > url.password
> > > > > and \
> > > > > > > -            self.host == url.host and self.port == url.port
> and \
> > > > > > > -            self.path == url.path
> > > > > > > -
> > > > > > > -    def __ne__(self, url):
> > > > > > > -        return not self.__eq__(url)
> > > > > > > -
> > > > > > > -    def defaults(self):
> > > > > > > -        """
> > > > > > > -        Fill in missing values with defaults
> > > > > > > -        @return: self
> > > > > > > -        """
> > > > > > > -        self.scheme = self.scheme or self.AMQP
> > > > > > > -        self.host = self.host or '0.0.0.0'
> > > > > > > -        self.port = self.port or self.Port(self.scheme)
> > > > > > > -        return self
> > > > > > > +  def defaults(self):
> > > > > > > +    """
> > > > > > > +    Fill in missing values (scheme, host or port) with
> defaults
> > > > > > > +    @return: self
> > > > > > > +    """
> > > > > > > +    self.scheme = self.scheme or self.AMQP
> > > > > > > +    self.host = self.host or '0.0.0.0'
> > > > > > > +    self.port = self.port or self.Port(self.scheme)
> > > > > > > +    return self
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19
> > > 21:00:50
> > > > > > > 2014
> > > > > > > @@ -26,8 +26,8 @@
> > > > > > >  #include <proton/messenger.h>
> > > > > > >  #include <proton/ssl.h>
> > > > > > >  #include <proton/driver_extras.h>
> > > > > > > -
> > > > > > >  #include <proton/types.h>
> > > > > > > +#include <proton/url.h>
> > > > > > >
> > > > > > >  #include <uuid/uuid.h>
> > > > > > >  %}
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/include/proton/cproton.i
> (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri
> Sep 19
> > > > > > > 21:00:50 2014
> > > > > > > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> > > > > > >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return
> > > (pn_delivery_t
> > > > > *)
> > > > > > > x; }
> > > > > > >    pn_transport_t *pn_cast_pn_transport(void *x) { return
> > > > > (pn_transport_t
> > > > > > > *) x; }
> > > > > > >  %}
> > > > > > > +
> > > > > > > +%include "proton/url.h"
> > > > > > > +
> > > > > > >
> > > > > > > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > > > > > > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19
> > > 21:00:50
> > > > > > > 2014
> > > > > > > @@ -0,0 +1,83 @@
> > > > > > > +#ifndef PROTON_URL_H
> > > > > > > +#define PROTON_URL_H
> > > > > > > +/*
> > > > > > > + * 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.
> > > > > > > + */
> > > > > > > +
> > > > > > > +#include <proton/import_export.h>
> > > > > > > +
> > > > > > > +/** @file
> > > > > > > + * URL API for parsing URLs.
> > > > > > > + *
> > > > > > > + * @defgroup url URL
> > > > > > > + * @{
> > > > > > > + */
> > > > > > > +
> > > > > > > +/** A parsed URL */
> > > > > > > +typedef struct pn_url_t pn_url_t;
> > > > > > > +
> > > > > > > +/** Create an empty URL */
> > > > > > > +PN_EXTERN pn_url_t *pn_url(void);
> > > > > > > +
> > > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > > + *@param[in] url A URL string.
> > > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid
> URL
> > > > > string.
> > > > > > > + */
> > > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > > > > > > +
> > > > > > > +/** Free a URL */
> > > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > > > > > > +
> > > > > > > +/** Clear the contents of the URL. */
> > > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > > > > > > +
> > > > > > > +/** Return the string form of a URL. Owned by the pn_url_t.*/
> > > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > > > > > > +
> > > > > > > +/**
> > > > > > > + *@name Getters for parts of the URL.
> > > > > > > + *
> > > > > > > + *Values belong to the URL. May return NULL if the value is
> not
> > > set.
> > > > > > > + *
> > > > > > > + *@{
> > > > > > > + */
> > > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > > > > > > +///@}
> > > > > > > +
> > > > > > > +/**
> > > > > > > + *@name Setters for parts of the URL.
> > > > > > > + *
> > > > > > > + *Values are copied. Value can be NULL to indicate the part
> is not
> > > > > set.
> > > > > > > + *
> > > > > > > + *@{
> > > > > > > + */
> > > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > > *scheme);
> > > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > > *username);
> > > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > > *password);
> > > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char
> *host);
> > > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char
> *port);
> > > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char
> *path);
> > > > > > > +///@}
> > > > > > > +
> > > > > > > +///@}
> > > > > > > +#endif
> > > > > > >
> > > > > > > Added: qpid/proton/trunk/proton-c/src/url.c
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > > > > > > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50
> 2014
> > > > > > > @@ -0,0 +1,127 @@
> > > > > > > +/*
> > > > > > > + *
> > > > > > > + * 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.
> > > > > > > + *
> > > > > > > + */
> > > > > > > +
> > > > > > > +#include <proton/url.h>
> > > > > > > +#include <proton/util.h>
> > > > > > > +#include <stdlib.h>
> > > > > > > +#include <string.h>
> > > > > > > +#include <stdio.h>
> > > > > > > +
> > > > > > > +static char* copy(const char* str) {
> > > > > > > +    if (str ==  NULL) return NULL;
> > > > > > > +    char *str2 = (char*)malloc(strlen(str));
> > > > > > > +    if (str2) strcpy(str2, str);
> > > > > > > +    return str2;
> > > > > > > +}
> > > > > > > +
> > > > > > > +struct pn_url_t {
> > > > > > > +    char *scheme;
> > > > > > > +    char *username;
> > > > > > > +    char *password;
> > > > > > > +    char *host;
> > > > > > > +    char *port;
> > > > > > > +    char *path;
> > > > > > > +    char *str;
> > > > > > > +};
> > > > > > > +
> > > > > > > +PN_EXTERN pn_url_t *pn_url() {
> > > > > > > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > > > > > > +    memset(url, 0, sizeof(*url));
> > > > > > > +    return url;
> > > > > > > +}
> > > > > > > +
> > > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > > + *@param[in] url A URL string.
> > > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid
> URL
> > > > > string.
> > > > > > > + */
> > > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > > > > > > +    if (!str || !*str)          /* Empty string or NULL is
> > > illegal. */
> > > > > > > +        return NULL;
> > > > > > > +
> > > > > > > +    pn_url_t *url = pn_url();
> > > > > > > +    char *str2 = copy(str);         /* FIXME aconway
> 2014-09-19:
> > > > > clean up
> > > > > > > */
> > > > > > > +    pni_parse_url(str2, &url->scheme, &url->username,
> > > &url->password,
> > > > > > > &url->host, &url->port, &url->path);
> > > > > > > +    url->scheme = copy(url->scheme);
> > > > > > > +    url->username = copy(url->username);
> > > > > > > +    url->password = copy(url->password);
> > > > > > > +    url->host = (url->host && !*url->host) ? NULL :
> > > copy(url->host);
> > > > > > > +    url->port = copy(url->port);
> > > > > > > +    url->path = copy(url->path);
> > > > > > > +    return url;
> > > > > > > +}
> > > > > > > +
> > > > > > > +/** Free a URL */
> > > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > > > > > > +    pn_url_clear(url);
> > > > > > > +    free(url);
> > > > > > > +}
> > > > > > > +
> > > > > > > +/** Clear the contents of the URL. */
> > > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > > > > > > +    pn_url_set_username(url, NULL);
> > > > > > > +    pn_url_set_password(url, NULL);
> > > > > > > +    pn_url_set_host(url, NULL);
> > > > > > > +    pn_url_set_port(url, NULL);
> > > > > > > +    pn_url_set_path(url, NULL);
> > > > > > > +    free(url->str); url->str = NULL;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static inline int len(const char *str) { return str ?
> strlen(str)
> > > :
> > > > > 0; }
> > > > > > > +
> > > > > > > +/** Return the string form of a URL. */
> > > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > > > > > > +    int size = len(url->scheme) + len(url->username) +
> > > > > len(url->password)
> > > > > > > +        + len(url->host) + len(url->port) + len(url->path)
> > > > > > > +        + len("s://u:p@[h]:p/p");
> > > > > > > +    free(url->str);
> > > > > > > +    url->str = (char*)malloc(size);
> > > > > > > +    if (!url->str) return NULL;
> > > > > > > +
> > > > > > > +    int i = 0;
> > > > > > > +    if (url->scheme) i += snprintf(url->str+i, size-i,
> "%s://",
> > > > > > > url->scheme);
> > > > > > > +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> > > > > > > url->username);
> > > > > > > +    if (url->password) i += snprintf(url->str+i, size-i,
> ":%s",
> > > > > > > url->password);
> > > > > > > +    if (url->username || url->password) i +=
> snprintf(url->str+i,
> > > > > size-i,
> > > > > > > "@");
> > > > > > > +    if (url->host) {
> > > > > > > +        if (strchr(url->host, ':')) i += snprintf(url->str+i,
> > > size-i,
> > > > > > > "[%s]", url->host);
> > > > > > > +        else i += snprintf(url->str+i, size-i, "%s",
> url->host);
> > > > > > > +    }
> > > > > > > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
> > > > > url->port);
> > > > > > > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
> > > > > url->path);
> > > > > > > +    return url->str;
> > > > > > > +}
> > > > > > > +
> > > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
> > > > > url->scheme; }
> > > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> > > > > > > url->username; }
> > > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> > > > > > > url->password; }
> > > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return
> > > url->host; }
> > > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return
> > > url->port; }
> > > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return
> > > url->path; }
> > > > > > > +
> > > > > > > +#define SET(part) free(url->part); url->part = copy(part)
> > > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > > *scheme) {
> > > > > > > SET(scheme); }
> > > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > > *username) {
> > > > > > > SET(username); }
> > > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > > *password) {
> > > > > > > SET(password); }
> > > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char
> *host) {
> > > > > > > SET(host); }
> > > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char
> *port) {
> > > > > > > SET(port); }
> > > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char
> *path) {
> > > > > > > SET(path); }
> > > > > > > +
> > > > > > > +
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > > URL:
> > > > > > >
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > >
> ==============================================================================
> > > > > > > --- qpid/proton/trunk/tests/python/proton_tests/url.py
> (original)
> > > > > > > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep
> 19
> > > > > 21:00:50
> > > > > > > 2014
> > > > > > > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> > > > > > >      def assertNotEqual(self, a, b):
> > > > > > >          assert a != b, "%s == %s" % (a, b)
> > > > > > >
> > > > > > > -    def assertUrl(self, u, scheme, user, password, host, port,
> > > path):
> > > > > > > -        self.assertEqual((u.scheme, u.user, u.password,
> u.host,
> > > > > u.port,
> > > > > > > u.path),
> > > > > > > -                         (scheme, user, password, host, port,
> > > path))
> > > > > > > +    def assertUrl(self, u, scheme, username, password, host,
> port,
> > > > > path):
> > > > > > > +        self.assertEqual((u.scheme, u.username, u.password,
> > > u.host,
> > > > > > > u.port, u.path),
> > > > > > > +                         (scheme, username, password, host,
> port,
> > > > > path))
> > > > > > >
> > > > > > >      def testUrl(self):
> > > > > > >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > > > > > > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> > > > > > >
> > > > > > >      def testDefaults(self):
> > > > > > >          # Check that we allow None for scheme, port
> > > > > > > -        url = Url(user='me', password='secret', host='myhost',
> > > > > > > path='foobar')
> > > > > > > +        url = Url(username='me', password='secret',
> host='myhost',
> > > > > > > path='foobar')
> > > > > > >          self.assertEqual(str(url), "me:secret@myhost/foobar")
> > > > > > >          self.assertUrl(url, None, 'me', 'secret', 'myhost',
> None,
> > > > > > > 'foobar')
> > > > > > >
> > > > > > > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> > > > > > >      def testMissing(self):
> > > > > > >          self.assertUrl(Url(), None, None, None, None, None,
> None)
> > > > > > >          self.assertUrl(Url('amqp://'), 'amqp', None, None,
> None,
> > > None,
> > > > > > > None)
> > > > > > > -        self.assertUrl(Url('user@'), None, 'user', None,
> None,
> > > None,
> > > > > > > None)
> > > > > > > +        self.assertUrl(Url('username@'), None, 'username',
> None,
> > > > > None,
> > > > > > > None, None)
> > > > > > >          self.assertUrl(Url(':pass@'), None, '', 'pass', None,
> > > None,
> > > > > None)
> > > > > > >          self.assertUrl(Url('host'), None, None, None, 'host',
> > > None,
> > > > > None)
> > > > > > >          self.assertUrl(Url(':1234'), None, None, None, None,
> 1234,
> > > > > None)
> > > > > > >          self.assertUrl(Url('/path'), None, None, None, None,
> None,
> > > > > 'path')
> > > > > > >
> > > > > > > -        for s in ['amqp://', 'user@', ':pass@', ':1234',
> > > '/path']:
> > > > > > > +        for s in ['amqp://', 'username@', ':pass@', ':1234',
> > > > > '/path']:
> > > > > > >              self.assertEqual(s, str(Url(s)))
> > > > > > >
> > > > > > >          for s, full in [
> > > > > > >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > > > > > > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > > > > > > +                ('username@', 'amqp://username@0.0.0.0:
> amqp'),
> > > > > > >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> > > > > > >                  (':1234', 'amqp://0.0.0.0:1234'),
> > > > > > >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> > > > > > >              self.assertEqual(str(Url(s).defaults()), full)
> > > > > > > -
> > > > > > > -        self.assertRaises(ValueError, Url, '')
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >
> > > ---------------------------------------------------------------------
> > > > > > > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > > > > > > For additional commands, e-mail: commits-help@qpid.apache.org
> > > > > > >
> > > > > > >
> > > > >
> > > > >
> > > > >
> > > > >
> ---------------------------------------------------------------------
> > > > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > > > For additional commands, e-mail: dev-help@qpid.apache.org
> > > > >
> > > > >
> > >
> > >
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > For additional commands, e-mail: dev-help@qpid.apache.org
> > >
> > >
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> For additional commands, e-mail: dev-help@qpid.apache.org
>
>

Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Robbie Gemmell <ro...@gmail.com>.
Sorry, I had gone out by the time you mailed. I wasn't clear in my earlier
mail in that the local test I did was just in my normal env using Java8,
not the old one I dug out using Java 6. Installing an old version of Java
is easy enough though. I see you have fixed it and it wasnt related to the
Java version in the end anyway :)

Robbie

On 25 September 2014 19:58, Alan Conway <ac...@redhat.com> wrote:

> Hum, CI is still broken.
>
> https://builds.apache.org/job/Qpid-proton-j/org.apache.qpid
> $proton-tests/683/testReport/org.apache.qpid.proton/JythonTest/test/
>
> Somehow my trivial re-org of the URL tests in python has caused the
> entire Jython test harness to explode in flight. It works fine on my box
> in python and Jython, and it works on CI in regular python - so maybe
> another Java 6 issue? Will I lose my mind if I try to install Java 6 on
> Fedora and get proton to use it?
>
> On Thu, 2014-09-25 at 13:59 -0400, Alan Conway wrote:
> > On Thu, 2014-09-25 at 15:59 +0100, Robbie Gemmell wrote:
> > > On 25 September 2014 15:00, Alan Conway <ac...@redhat.com> wrote:
> > >
> > > > On Wed, 2014-09-24 at 12:19 +0100, Robbie Gemmell wrote:
> > > > > The tests are now running again, but a couple of the URL tests
> still seem
> > > > > to be failing on the CI job:
> > > > >
> > > >
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/
> > > > >
> > > >
> > > > They are all failing with:
> > > >  Not a valid port number or service name: 'amqps'
> > > >
> > > > Could this be a configuration problem on the CI machine, i.e.
> missing an
> > > > 'amqps' entry in /etc/services? Can I get access to the CI machine to
> > > > poke around and see what's up?
> > > >
> > >
> > > Almost certainly no, only the core maintainers are allowed shell
> access as
> > > far as I've seen. You can ask on builds@apache.org for those with
> access to
> > > check things out and report back and see what happens.
> > >
> > > I think the CI instances will be running Ubuntu 12.04 or 14.04 LTS. For
> > > giggles, I dug out an ooooold Ubuntu VM with Java 6 on it and tried the
> > > tests, which failed, and it indeed has no amqp[s] entry in
> /etc/services
> > > file so that could well be it.
> >
> > Thanks for checking that out! I have hacked the tests to skip tests for
> > 'amqps' if it is not recognized. Poke me if there are still failures.
> >
> > ------------------------------------------------------------------------
> > r1627577 | aconway | 2014-09-25 13:59:17 -0400 (Thu, 25 Sep 2014) | 5
> > lines
> >
> > NO-JIRA: Fix URL test to skip 'amqps' tests if 'amqps' is not recognized
> > as a service name.
> >
> > On some older Ubuntu with Java 6, 'amqps' is not recognized as a service
> > name so
> > skip those tests in that case.
> >
> > ------------------------------------------------------------------------
> >
> > > >
> > > > The URL code uses socket.getservbyname() to look up service names. Is
> > > > there a more portable way to do it?
> > > >
> > >
> > > No idea I'm afraid.
> > >
> > >
> > > >
> > > > Cheers,
> > > > Alan.
> > > >
> > > > > As mentioned in my other post about a timeline for dropping Java6
> > > > support,
> > > > > they seem to work on Java8 (havent tried Java7).
> > > > >
> > > > > Robbie
> > > > >
> > > > > On 22 September 2014 21:14, Alan Conway <ac...@redhat.com>
> wrote:
> > > > >
> > > > > > My bad, didn't run the java tests. Will fix ASAP and then give
> myself a
> > > > > > flogging.
> > > > > >
> > > > > > On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> > > > > > > This seems to have broken the Java test runs:
> > > > > > >
> > > > > > >
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > On 19 September 2014 22:00, <ac...@apache.org> wrote:
> > > > > > >
> > > > > > > > Author: aconway
> > > > > > > > Date: Fri Sep 19 21:00:50 2014
> > > > > > > > New Revision: 1626329
> > > > > > > >
> > > > > > > > URL: http://svn.apache.org/r1626329
> > > > > > > > Log:
> > > > > > > > PROTON-693: Python Url class to wrap C function pni_parse_url
> > > > > > > >
> > > > > > > > It was pointed out that pni_parse_url is an internal
> function and
> > > > the
> > > > > > > > interface
> > > > > > > > is not suitable for public API.
> > > > > > > >
> > > > > > > > Rewrote the URL parser as a proper swigable C API pn_url_*.
> This
> > > > gets
> > > > > > rid
> > > > > > > > of the
> > > > > > > > need for previous swig insanity and is cleaner all round.
> > > > > > > >
> > > > > > > > Internally still uses the pni_parse_url parser, we can clean
> that
> > > > up
> > > > > > later.
> > > > > > > >
> > > > > > > > Added:
> > > > > > > >     qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > > >     qpid/proton/trunk/proton-c/src/url.c
> > > > > > > > Modified:
> > > > > > > >     qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > > >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > > >     qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19
> 21:00:50
> > > > 2014
> > > > > > > > @@ -270,6 +270,7 @@ set (qpid-proton-core
> > > > > > > >    src/object/iterator.c
> > > > > > > >
> > > > > > > >    src/util.c
> > > > > > > > +  src/url.c
> > > > > > > >    src/error.c
> > > > > > > >    src/buffer.c
> > > > > > > >    src/parser.c
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i
> (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep
> 19
> > > > 21:00:50
> > > > > > > > 2014
> > > > > > > > @@ -8,6 +8,7 @@
> > > > > > > >  #include <proton/messenger.h>
> > > > > > > >  #include <proton/ssl.h>
> > > > > > > >  #include <proton/driver_extras.h>
> > > > > > > > +#include <proton/url.h>
> > > > > > > >  %}
> > > > > > > >
> > > > > > > >  %include <cstring.i>
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19
> > > > 21:00:50
> > > > > > 2014
> > > > > > > > @@ -29,6 +29,7 @@
> > > > > > > >  %header %{
> > > > > > > >  /* Include the headers needed by the code in this wrapper
> file */
> > > > > > > >  #include <proton/types.h>
> > > > > > > > +#include <proton/url.h>
> > > > > > > >  #include <proton/message.h>
> > > > > > > >  #include <proton/driver.h>
> > > > > > > >  #include <proton/driver_extras.h>
> > > > > > > >
> > > > > > > > Modified:
> qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i
> (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri
> Sep 19
> > > > > > > > 21:00:50 2014
> > > > > > > > @@ -23,6 +23,7 @@
> > > > > > > >  #include <winsock2.h>
> > > > > > > >  #endif
> > > > > > > >  #include <proton/engine.h>
> > > > > > > > +#include <proton/url.h>
> > > > > > > >  #include <proton/message.h>
> > > > > > > >  #include <proton/sasl.h>
> > > > > > > >  #include <proton/driver.h>
> > > > > > > > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> > > > > > > >    }
> > > > > > > >  %}
> > > > > > > >
> > > > > > > > -
> > > > > > > > -/**
> > > > > > > > -   pni_parse_url(char* url, char **scheme, char **user, char
> > > > **pass,
> > > > > > char
> > > > > > > > **host, char **port, char **path)
> > > > > > > > -   The following type maps convert this into a python
> function
> > > > that
> > > > > > taks
> > > > > > > > a URL string argument
> > > > > > > > -   and returns a list of strings [scheme, user, pass, host,
> port,
> > > > > > path]
> > > > > > > > -   This probably could be done more neatly.
> > > > > > > > -*/
> > > > > > > > -
> > > > > > > > -// Typemap to copy the url string as it will be modified by
> > > > parse_url
> > > > > > > > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize")
> char *url
> > > > (int
> > > > > > > > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > > > > > > > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > > > > > > > -  if (!SWIG_IsOK(res)) {
> > > > > > > > -    %argument_fail(res, "char *url", $symname, $argnum);
> > > > > > > > -  }
> > > > > > > > -  $1 = %new_array(n, $*1_ltype);
> > > > > > > > -  memcpy($1,t,sizeof(char)*n);
> > > > > > > > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > > > > > > > -  $1[n-1] = 0;
> > > > > > > > -}
> > > > > > > > -%typemap(freearg,match="in") char *url "free($1);";
> > > > > > > > -%typemap(argout) char *url "";
> > > > > > > > -
> > > > > > > > -// Typemap for char** return strings. Don't free them.
> > > > > > > > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0)
> "$1 =
> > > > > > &temp;";
> > > > > > > > -%typemap(freearg,match="in") char **OUTSTR "";
> > > > > > > > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char
> > > > **OUTSTR {
> > > > > > > > -    %append_output(SWIG_FromCharPtr(*$1));
> > > > > > > > -}
> > > > > > > > -
> > > > > > > > -// Typemap to initialize result as empty list
> > > > > > > > -%typemap(out) void "$result = PyList_New(0);";
> > > > > > > > -
> > > > > > > > -
> > > > > > > > -%apply char** OUTSTR {char **scheme, char **user, char
> **pass,
> > > > char
> > > > > > > > **host, char **port, char **path};
> > > > > > > > -void pni_parse_url(char* url, char **scheme, char **user,
> char
> > > > **pass,
> > > > > > > > char **host, char **port, char **path);
> > > > > > > > -%ignore pni_parse_url;
> > > > > > > > -
> > > > > > > >  %include "proton/cproton.i"
> > > > > > > >
> > > > > > > > Modified:
> qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/python/proton.py
> (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri
> Sep 19
> > > > > > > > 21:00:50 2014
> > > > > > > > @@ -3657,114 +3657,98 @@ __all__ = [
> > > > > > > >
> > > > > > > >
> > > > > > > >  class Url(object):
> > > > > > > > -    """
> > > > > > > > -    Simple URL parser/constructor, handles URLs of the form:
> > > > > > > > +  """
> > > > > > > > +  Simple URL parser/constructor, handles URLs of the form:
> > > > > > > >
> > > > > > > > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > > > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > > >
> > > > > > > > -    All components can be None if not specifeid in the URL
> string.
> > > > > > > > +  All components can be None if not specifeid in the URL
> string.
> > > > > > > >
> > > > > > > > -    The port can be specified as a service name, e.g.
> 'amqp' in
> > > > the
> > > > > > > > -    URL string but Url.port always gives the integer value.
> > > > > > > > +  The port can be specified as a service name, e.g. 'amqp'
> in the
> > > > > > > > +  URL string but Url.port always gives the integer value.
> > > > > > > > +
> > > > > > > > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > > > +  @ivar user: Username
> > > > > > > > +  @ivar password: Password
> > > > > > > > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > > > +  @ivar port: Integer port.
> > > > > > > > +  @ivar host_port: Returns host:port
> > > > > > > > +  """
> > > > > > > > +
> > > > > > > > +  AMQPS = "amqps"
> > > > > > > > +  AMQP = "amqp"
> > > > > > > > +
> > > > > > > > +  class Port(int):
> > > > > > > > +    """An integer port number that can be constructed from a
> > > > service
> > > > > > name
> > > > > > > > string"""
> > > > > > > > +
> > > > > > > > +    def __new__(cls, value):
> > > > > > > > +      port = super(Url.Port, cls).__new__(cls,
> > > > cls.port_int(value))
> > > > > > > > +      setattr(port, 'name', str(value))
> > > > > > > > +      return port
> > > > > > > > +
> > > > > > > > +    def __eq__(self, x): return str(self) == x or int(self)
> == x
> > > > > > > > +    def __ne__(self, x): return not self == x
> > > > > > > > +    def __str__(self): return str(self.name)
> > > > > > > > +
> > > > > > > > +    @staticmethod
> > > > > > > > +    def port_int(value):
> > > > > > > > +      """Convert service, an integer or a service name,
> into an
> > > > > > integer
> > > > > > > > port number."""
> > > > > > > > +      try:
> > > > > > > > +        return int(value)
> > > > > > > > +      except ValueError:
> > > > > > > > +        try:
> > > > > > > > +          return socket.getservbyname(value)
> > > > > > > > +        except socket.error:
> > > > > > > > +          raise ValueError("Not a valid port number or
> service
> > > > name:
> > > > > > > > '%s'" % value)
> > > > > > > >
> > > > > > > > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > > > -    @ivar user: Username
> > > > > > > > -    @ivar password: Password
> > > > > > > > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > > > -    @ivar port: Integer port.
> > > > > > > > -    @ivar host_port: Returns host:port
> > > > > > > > +  def __init__(self, url=None, **kwargs):
> > > > > > > > +    """
> > > > > > > > +    @param url: URL string to parse.
> > > > > > > > +    @param kwargs: scheme, user, password, host, port, path.
> > > > > > > > +      If specified, replaces corresponding part in url
> string.
> > > > > > > >      """
> > > > > > > > +    if url:
> > > > > > > > +      self._url = pn_url_parse(str(url))
> > > > > > > > +      if not self._url: raise ValueError("Invalid URL '%s'"
> % url)
> > > > > > > > +    else:
> > > > > > > > +      self._url = pn_url()
> > > > > > > > +    for k in kwargs:            # Let kwargs override values
> > > > parsed
> > > > > > from
> > > > > > > > url
> > > > > > > > +      getattr(self, k)          # Check for invalid kwargs
> > > > > > > > +      setattr(self, k, kwargs[k])
> > > > > > > > +
> > > > > > > > +  class PartDescriptor(object):
> > > > > > > > +    def __init__(self, part):
> > > > > > > > +      self.getter = globals()["pn_url_%s" % part]
> > > > > > > > +      self.setter = globals()["pn_url_set_%s" % part]
> > > > > > > > +    def __get__(self, obj, type=None): return
> > > > self.getter(obj._url)
> > > > > > > > +    def __set__(self, obj, value): return
> self.setter(obj._url,
> > > > > > > > str(value))
> > > > > > > > +
> > > > > > > > +  scheme = PartDescriptor('scheme')
> > > > > > > > +  username = PartDescriptor('username')
> > > > > > > > +  password = PartDescriptor('password')
> > > > > > > > +  host = PartDescriptor('host')
> > > > > > > > +  path = PartDescriptor('path')
> > > > > > > > +
> > > > > > > > +  @property
> > > > > > > > +  def port(self):
> > > > > > > > +    portstr = pn_url_port(self._url)
> > > > > > > > +    return portstr and Url.Port(portstr)
> > > > > > > > +
> > > > > > > > +  @port.setter
> > > > > > > > +  def port(self, value):
> > > > > > > > +    if value is None: pn_url_set_port(self._url, None)
> > > > > > > > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> > > > > > > >
> > > > > > > > -    AMQPS = "amqps"
> > > > > > > > -    AMQP = "amqp"
> > > > > > > > +  def __str__(self): return pn_url_str(self._url)
> > > > > > > >
> > > > > > > > -    class Port(int):
> > > > > > > > -      """An integer port number that can also have an
> associated
> > > > > > service
> > > > > > > > name string"""
> > > > > > > > +  def __repr__(self): return "Url(%r)" % str(self)
> > > > > > > >
> > > > > > > > -      def __new__(cls, value):
> > > > > > > > -        port = super(Url.Port, cls).__new__(cls,
> > > > cls.port_int(value))
> > > > > > > > -        setattr(port, 'name', str(value))
> > > > > > > > -        return port
> > > > > > > > -
> > > > > > > > -      def __eq__(self, x): return str(self) == x or
> int(self) == x
> > > > > > > > -      def __ne__(self, x): return not self == x
> > > > > > > > -      def __str__(self): return str(self.name)
> > > > > > > > -
> > > > > > > > -      @staticmethod
> > > > > > > > -      def port_int(value):
> > > > > > > > -        """Convert service, an integer or a service name,
> into an
> > > > > > integer
> > > > > > > > port number."""
> > > > > > > > -        try:
> > > > > > > > -          return int(value)
> > > > > > > > -        except ValueError:
> > > > > > > > -          try:
> > > > > > > > -            return socket.getservbyname(value)
> > > > > > > > -          except socket.error:
> > > > > > > > -            raise ValueError("Not a valid port number or
> service
> > > > name:
> > > > > > > > '%s'" % value)
> > > > > > > > -
> > > > > > > > -    def __init__(self, url=None, **kwargs):
> > > > > > > > -        """
> > > > > > > > -        @param url: String or Url instance to parse or copy.
> > > > > > > > -        @param kwargs: URL fields: scheme, user, password,
> host,
> > > > port,
> > > > > > > > path.
> > > > > > > > -            If specified, replaces corresponding component
> in url.
> > > > > > > > -        """
> > > > > > > > -
> > > > > > > > -        fields = ['scheme', 'user', 'password', 'host',
> 'port',
> > > > > > 'path']
> > > > > > > > -
> > > > > > > > -        for f in fields: setattr(self, f, None)
> > > > > > > > -        for k in kwargs: getattr(self, k) # Check for
> invalid
> > > > kwargs
> > > > > > > > -
> > > > > > > > -        if isinstance(url, Url): # Copy from another Url
> instance.
> > > > > > > > -            self.__dict__.update(url.__dict__)
> > > > > > > > -        elif url is not None:   # Parse from url
> > > > > > > > -            parts = pni_parse_url(str(url))
> > > > > > > > -            if not filter(None, parts): raise
> ValueError("Invalid
> > > > AMQP
> > > > > > > > URL: '%s'" % url)
> > > > > > > > -            self.scheme, self.user, self.password,
> self.host,
> > > > port,
> > > > > > > > self.path = parts
> > > > > > > > -            if not self.host: self.host = None
> > > > > > > > -            self.port = port and self.Port(port)
> > > > > > > > -
> > > > > > > > -        # Let kwargs override values previously set from url
> > > > > > > > -        for field in fields:
> > > > > > > > -            setattr(self, field, kwargs.get(field,
> getattr(self,
> > > > > > field)))
> > > > > > > > -
> > > > > > > > -    def __repr__(self):
> > > > > > > > -        return "Url(%r)" % str(self)
> > > > > > > > -
> > > > > > > > -    def __str__(self):
> > > > > > > > -        s = ""
> > > > > > > > -        if self.scheme:
> > > > > > > > -            s += "%s://" % self.scheme
> > > > > > > > -        if self.user:
> > > > > > > > -            s += self.user
> > > > > > > > -        if self.password:
> > > > > > > > -            s += ":%s" % self.password
> > > > > > > > -        if self.user or self.password:
> > > > > > > > -            s += '@'
> > > > > > > > -        if self.host and ':' in self.host:
> > > > > > > > -            s += "[%s]" % self.host
> > > > > > > > -        elif self.host:
> > > > > > > > -            s += self.host
> > > > > > > > -        if self.port:
> > > > > > > > -            s += ":%s" % self.port
> > > > > > > > -        if self.path:
> > > > > > > > -            s += "/%s" % self.path
> > > > > > > > -        return s
> > > > > > > > -
> > > > > > > > -    def __eq__(self, url):
> > > > > > > > -        return \
> > > > > > > > -            self.scheme == url.scheme and \
> > > > > > > > -            self.user == url.user and self.password ==
> > > > url.password
> > > > > > and \
> > > > > > > > -            self.host == url.host and self.port == url.port
> and \
> > > > > > > > -            self.path == url.path
> > > > > > > > -
> > > > > > > > -    def __ne__(self, url):
> > > > > > > > -        return not self.__eq__(url)
> > > > > > > > -
> > > > > > > > -    def defaults(self):
> > > > > > > > -        """
> > > > > > > > -        Fill in missing values with defaults
> > > > > > > > -        @return: self
> > > > > > > > -        """
> > > > > > > > -        self.scheme = self.scheme or self.AMQP
> > > > > > > > -        self.host = self.host or '0.0.0.0'
> > > > > > > > -        self.port = self.port or self.Port(self.scheme)
> > > > > > > > -        return self
> > > > > > > > +  def defaults(self):
> > > > > > > > +    """
> > > > > > > > +    Fill in missing values (scheme, host or port) with
> defaults
> > > > > > > > +    @return: self
> > > > > > > > +    """
> > > > > > > > +    self.scheme = self.scheme or self.AMQP
> > > > > > > > +    self.host = self.host or '0.0.0.0'
> > > > > > > > +    self.port = self.port or self.Port(self.scheme)
> > > > > > > > +    return self
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep
> 19
> > > > 21:00:50
> > > > > > > > 2014
> > > > > > > > @@ -26,8 +26,8 @@
> > > > > > > >  #include <proton/messenger.h>
> > > > > > > >  #include <proton/ssl.h>
> > > > > > > >  #include <proton/driver_extras.h>
> > > > > > > > -
> > > > > > > >  #include <proton/types.h>
> > > > > > > > +#include <proton/url.h>
> > > > > > > >
> > > > > > > >  #include <uuid/uuid.h>
> > > > > > > >  %}
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/include/proton/cproton.i
> (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri
> Sep 19
> > > > > > > > 21:00:50 2014
> > > > > > > > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> > > > > > > >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return
> > > > (pn_delivery_t
> > > > > > *)
> > > > > > > > x; }
> > > > > > > >    pn_transport_t *pn_cast_pn_transport(void *x) { return
> > > > > > (pn_transport_t
> > > > > > > > *) x; }
> > > > > > > >  %}
> > > > > > > > +
> > > > > > > > +%include "proton/url.h"
> > > > > > > > +
> > > > > > > >
> > > > > > > > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > > > > > > > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep
> 19
> > > > 21:00:50
> > > > > > > > 2014
> > > > > > > > @@ -0,0 +1,83 @@
> > > > > > > > +#ifndef PROTON_URL_H
> > > > > > > > +#define PROTON_URL_H
> > > > > > > > +/*
> > > > > > > > + * 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.
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +#include <proton/import_export.h>
> > > > > > > > +
> > > > > > > > +/** @file
> > > > > > > > + * URL API for parsing URLs.
> > > > > > > > + *
> > > > > > > > + * @defgroup url URL
> > > > > > > > + * @{
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +/** A parsed URL */
> > > > > > > > +typedef struct pn_url_t pn_url_t;
> > > > > > > > +
> > > > > > > > +/** Create an empty URL */
> > > > > > > > +PN_EXTERN pn_url_t *pn_url(void);
> > > > > > > > +
> > > > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > > > + *@param[in] url A URL string.
> > > > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid
> URL
> > > > > > string.
> > > > > > > > + */
> > > > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > > > > > > > +
> > > > > > > > +/** Free a URL */
> > > > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > > > > > > > +
> > > > > > > > +/** Clear the contents of the URL. */
> > > > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > > > > > > > +
> > > > > > > > +/** Return the string form of a URL. Owned by the
> pn_url_t.*/
> > > > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + *@name Getters for parts of the URL.
> > > > > > > > + *
> > > > > > > > + *Values belong to the URL. May return NULL if the value is
> not
> > > > set.
> > > > > > > > + *
> > > > > > > > + *@{
> > > > > > > > + */
> > > > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > > > > > > > +///@}
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + *@name Setters for parts of the URL.
> > > > > > > > + *
> > > > > > > > + *Values are copied. Value can be NULL to indicate the part
> is not
> > > > > > set.
> > > > > > > > + *
> > > > > > > > + *@{
> > > > > > > > + */
> > > > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > > > *scheme);
> > > > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > > > *username);
> > > > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > > > *password);
> > > > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char
> *host);
> > > > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char
> *port);
> > > > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char
> *path);
> > > > > > > > +///@}
> > > > > > > > +
> > > > > > > > +///@}
> > > > > > > > +#endif
> > > > > > > >
> > > > > > > > Added: qpid/proton/trunk/proton-c/src/url.c
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > > > > > > > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50
> 2014
> > > > > > > > @@ -0,0 +1,127 @@
> > > > > > > > +/*
> > > > > > > > + *
> > > > > > > > + * 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.
> > > > > > > > + *
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +#include <proton/url.h>
> > > > > > > > +#include <proton/util.h>
> > > > > > > > +#include <stdlib.h>
> > > > > > > > +#include <string.h>
> > > > > > > > +#include <stdio.h>
> > > > > > > > +
> > > > > > > > +static char* copy(const char* str) {
> > > > > > > > +    if (str ==  NULL) return NULL;
> > > > > > > > +    char *str2 = (char*)malloc(strlen(str));
> > > > > > > > +    if (str2) strcpy(str2, str);
> > > > > > > > +    return str2;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +struct pn_url_t {
> > > > > > > > +    char *scheme;
> > > > > > > > +    char *username;
> > > > > > > > +    char *password;
> > > > > > > > +    char *host;
> > > > > > > > +    char *port;
> > > > > > > > +    char *path;
> > > > > > > > +    char *str;
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +PN_EXTERN pn_url_t *pn_url() {
> > > > > > > > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > > > > > > > +    memset(url, 0, sizeof(*url));
> > > > > > > > +    return url;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > > > + *@param[in] url A URL string.
> > > > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid
> URL
> > > > > > string.
> > > > > > > > + */
> > > > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > > > > > > > +    if (!str || !*str)          /* Empty string or NULL is
> > > > illegal. */
> > > > > > > > +        return NULL;
> > > > > > > > +
> > > > > > > > +    pn_url_t *url = pn_url();
> > > > > > > > +    char *str2 = copy(str);         /* FIXME aconway
> 2014-09-19:
> > > > > > clean up
> > > > > > > > */
> > > > > > > > +    pni_parse_url(str2, &url->scheme, &url->username,
> > > > &url->password,
> > > > > > > > &url->host, &url->port, &url->path);
> > > > > > > > +    url->scheme = copy(url->scheme);
> > > > > > > > +    url->username = copy(url->username);
> > > > > > > > +    url->password = copy(url->password);
> > > > > > > > +    url->host = (url->host && !*url->host) ? NULL :
> > > > copy(url->host);
> > > > > > > > +    url->port = copy(url->port);
> > > > > > > > +    url->path = copy(url->path);
> > > > > > > > +    return url;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +/** Free a URL */
> > > > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > > > > > > > +    pn_url_clear(url);
> > > > > > > > +    free(url);
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +/** Clear the contents of the URL. */
> > > > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > > > > > > > +    pn_url_set_username(url, NULL);
> > > > > > > > +    pn_url_set_password(url, NULL);
> > > > > > > > +    pn_url_set_host(url, NULL);
> > > > > > > > +    pn_url_set_port(url, NULL);
> > > > > > > > +    pn_url_set_path(url, NULL);
> > > > > > > > +    free(url->str); url->str = NULL;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +static inline int len(const char *str) { return str ?
> strlen(str)
> > > > :
> > > > > > 0; }
> > > > > > > > +
> > > > > > > > +/** Return the string form of a URL. */
> > > > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > > > > > > > +    int size = len(url->scheme) + len(url->username) +
> > > > > > len(url->password)
> > > > > > > > +        + len(url->host) + len(url->port) + len(url->path)
> > > > > > > > +        + len("s://u:p@[h]:p/p");
> > > > > > > > +    free(url->str);
> > > > > > > > +    url->str = (char*)malloc(size);
> > > > > > > > +    if (!url->str) return NULL;
> > > > > > > > +
> > > > > > > > +    int i = 0;
> > > > > > > > +    if (url->scheme) i += snprintf(url->str+i, size-i,
> "%s://",
> > > > > > > > url->scheme);
> > > > > > > > +    if (url->username) i += snprintf(url->str+i, size-i,
> "%s",
> > > > > > > > url->username);
> > > > > > > > +    if (url->password) i += snprintf(url->str+i, size-i,
> ":%s",
> > > > > > > > url->password);
> > > > > > > > +    if (url->username || url->password) i +=
> snprintf(url->str+i,
> > > > > > size-i,
> > > > > > > > "@");
> > > > > > > > +    if (url->host) {
> > > > > > > > +        if (strchr(url->host, ':')) i +=
> snprintf(url->str+i,
> > > > size-i,
> > > > > > > > "[%s]", url->host);
> > > > > > > > +        else i += snprintf(url->str+i, size-i, "%s",
> url->host);
> > > > > > > > +    }
> > > > > > > > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
> > > > > > url->port);
> > > > > > > > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
> > > > > > url->path);
> > > > > > > > +    return url->str;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
> > > > > > url->scheme; }
> > > > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url) {
> return
> > > > > > > > url->username; }
> > > > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url) {
> return
> > > > > > > > url->password; }
> > > > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return
> > > > url->host; }
> > > > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return
> > > > url->port; }
> > > > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return
> > > > url->path; }
> > > > > > > > +
> > > > > > > > +#define SET(part) free(url->part); url->part = copy(part)
> > > > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > > > *scheme) {
> > > > > > > > SET(scheme); }
> > > > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > > > *username) {
> > > > > > > > SET(username); }
> > > > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > > > *password) {
> > > > > > > > SET(password); }
> > > > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char
> *host) {
> > > > > > > > SET(host); }
> > > > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char
> *port) {
> > > > > > > > SET(port); }
> > > > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char
> *path) {
> > > > > > > > SET(path); }
> > > > > > > > +
> > > > > > > > +
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/tests/python/proton_tests/url.py
> (original)
> > > > > > > > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri
> Sep 19
> > > > > > 21:00:50
> > > > > > > > 2014
> > > > > > > > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> > > > > > > >      def assertNotEqual(self, a, b):
> > > > > > > >          assert a != b, "%s == %s" % (a, b)
> > > > > > > >
> > > > > > > > -    def assertUrl(self, u, scheme, user, password, host,
> port,
> > > > path):
> > > > > > > > -        self.assertEqual((u.scheme, u.user, u.password,
> u.host,
> > > > > > u.port,
> > > > > > > > u.path),
> > > > > > > > -                         (scheme, user, password, host,
> port,
> > > > path))
> > > > > > > > +    def assertUrl(self, u, scheme, username, password,
> host, port,
> > > > > > path):
> > > > > > > > +        self.assertEqual((u.scheme, u.username, u.password,
> > > > u.host,
> > > > > > > > u.port, u.path),
> > > > > > > > +                         (scheme, username, password, host,
> port,
> > > > > > path))
> > > > > > > >
> > > > > > > >      def testUrl(self):
> > > > > > > >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > > > > > > > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> > > > > > > >
> > > > > > > >      def testDefaults(self):
> > > > > > > >          # Check that we allow None for scheme, port
> > > > > > > > -        url = Url(user='me', password='secret',
> host='myhost',
> > > > > > > > path='foobar')
> > > > > > > > +        url = Url(username='me', password='secret',
> host='myhost',
> > > > > > > > path='foobar')
> > > > > > > >          self.assertEqual(str(url), "me:secret@myhost
> /foobar")
> > > > > > > >          self.assertUrl(url, None, 'me', 'secret', 'myhost',
> None,
> > > > > > > > 'foobar')
> > > > > > > >
> > > > > > > > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> > > > > > > >      def testMissing(self):
> > > > > > > >          self.assertUrl(Url(), None, None, None, None, None,
> None)
> > > > > > > >          self.assertUrl(Url('amqp://'), 'amqp', None, None,
> None,
> > > > None,
> > > > > > > > None)
> > > > > > > > -        self.assertUrl(Url('user@'), None, 'user', None,
> None,
> > > > None,
> > > > > > > > None)
> > > > > > > > +        self.assertUrl(Url('username@'), None, 'username',
> None,
> > > > > > None,
> > > > > > > > None, None)
> > > > > > > >          self.assertUrl(Url(':pass@'), None, '', 'pass',
> None,
> > > > None,
> > > > > > None)
> > > > > > > >          self.assertUrl(Url('host'), None, None, None,
> 'host',
> > > > None,
> > > > > > None)
> > > > > > > >          self.assertUrl(Url(':1234'), None, None, None,
> None, 1234,
> > > > > > None)
> > > > > > > >          self.assertUrl(Url('/path'), None, None, None,
> None, None,
> > > > > > 'path')
> > > > > > > >
> > > > > > > > -        for s in ['amqp://', 'user@', ':pass@', ':1234',
> > > > '/path']:
> > > > > > > > +        for s in ['amqp://', 'username@', ':pass@',
> ':1234',
> > > > > > '/path']:
> > > > > > > >              self.assertEqual(s, str(Url(s)))
> > > > > > > >
> > > > > > > >          for s, full in [
> > > > > > > >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > > > > > > > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > > > > > > > +                ('username@', 'amqp://username@0.0.0.0:
> amqp'),
> > > > > > > >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> > > > > > > >                  (':1234', 'amqp://0.0.0.0:1234'),
> > > > > > > >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> > > > > > > >              self.assertEqual(str(Url(s).defaults()), full)
> > > > > > > > -
> > > > > > > > -        self.assertRaises(ValueError, Url, '')
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > ---------------------------------------------------------------------
> > > > > > > > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > > > > > > > For additional commands, e-mail:
> commits-help@qpid.apache.org
> > > > > > > >
> > > > > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > >
> ---------------------------------------------------------------------
> > > > > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > > > > For additional commands, e-mail: dev-help@qpid.apache.org
> > > > > >
> > > > > >
> > > >
> > > >
> > > >
> > > > ---------------------------------------------------------------------
> > > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > > For additional commands, e-mail: dev-help@qpid.apache.org
> > > >
> > > >
> >
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> For additional commands, e-mail: dev-help@qpid.apache.org
>
>

Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Robbie Gemmell <ro...@gmail.com>.
Sorry, I had gone out by the time you mailed. I wasn't clear in my earlier
mail in that the local test I did was just in my normal env using Java8,
not the old one I dug out using Java 6. Installing an old version of Java
is easy enough though. I see you have fixed it and it wasnt related to the
Java version in the end anyway :)

Robbie

On 25 September 2014 19:58, Alan Conway <ac...@redhat.com> wrote:

> Hum, CI is still broken.
>
> https://builds.apache.org/job/Qpid-proton-j/org.apache.qpid
> $proton-tests/683/testReport/org.apache.qpid.proton/JythonTest/test/
>
> Somehow my trivial re-org of the URL tests in python has caused the
> entire Jython test harness to explode in flight. It works fine on my box
> in python and Jython, and it works on CI in regular python - so maybe
> another Java 6 issue? Will I lose my mind if I try to install Java 6 on
> Fedora and get proton to use it?
>
> On Thu, 2014-09-25 at 13:59 -0400, Alan Conway wrote:
> > On Thu, 2014-09-25 at 15:59 +0100, Robbie Gemmell wrote:
> > > On 25 September 2014 15:00, Alan Conway <ac...@redhat.com> wrote:
> > >
> > > > On Wed, 2014-09-24 at 12:19 +0100, Robbie Gemmell wrote:
> > > > > The tests are now running again, but a couple of the URL tests
> still seem
> > > > > to be failing on the CI job:
> > > > >
> > > >
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/
> > > > >
> > > >
> > > > They are all failing with:
> > > >  Not a valid port number or service name: 'amqps'
> > > >
> > > > Could this be a configuration problem on the CI machine, i.e.
> missing an
> > > > 'amqps' entry in /etc/services? Can I get access to the CI machine to
> > > > poke around and see what's up?
> > > >
> > >
> > > Almost certainly no, only the core maintainers are allowed shell
> access as
> > > far as I've seen. You can ask on builds@apache.org for those with
> access to
> > > check things out and report back and see what happens.
> > >
> > > I think the CI instances will be running Ubuntu 12.04 or 14.04 LTS. For
> > > giggles, I dug out an ooooold Ubuntu VM with Java 6 on it and tried the
> > > tests, which failed, and it indeed has no amqp[s] entry in
> /etc/services
> > > file so that could well be it.
> >
> > Thanks for checking that out! I have hacked the tests to skip tests for
> > 'amqps' if it is not recognized. Poke me if there are still failures.
> >
> > ------------------------------------------------------------------------
> > r1627577 | aconway | 2014-09-25 13:59:17 -0400 (Thu, 25 Sep 2014) | 5
> > lines
> >
> > NO-JIRA: Fix URL test to skip 'amqps' tests if 'amqps' is not recognized
> > as a service name.
> >
> > On some older Ubuntu with Java 6, 'amqps' is not recognized as a service
> > name so
> > skip those tests in that case.
> >
> > ------------------------------------------------------------------------
> >
> > > >
> > > > The URL code uses socket.getservbyname() to look up service names. Is
> > > > there a more portable way to do it?
> > > >
> > >
> > > No idea I'm afraid.
> > >
> > >
> > > >
> > > > Cheers,
> > > > Alan.
> > > >
> > > > > As mentioned in my other post about a timeline for dropping Java6
> > > > support,
> > > > > they seem to work on Java8 (havent tried Java7).
> > > > >
> > > > > Robbie
> > > > >
> > > > > On 22 September 2014 21:14, Alan Conway <ac...@redhat.com>
> wrote:
> > > > >
> > > > > > My bad, didn't run the java tests. Will fix ASAP and then give
> myself a
> > > > > > flogging.
> > > > > >
> > > > > > On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> > > > > > > This seems to have broken the Java test runs:
> > > > > > >
> > > > > > >
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > > On 19 September 2014 22:00, <ac...@apache.org> wrote:
> > > > > > >
> > > > > > > > Author: aconway
> > > > > > > > Date: Fri Sep 19 21:00:50 2014
> > > > > > > > New Revision: 1626329
> > > > > > > >
> > > > > > > > URL: http://svn.apache.org/r1626329
> > > > > > > > Log:
> > > > > > > > PROTON-693: Python Url class to wrap C function pni_parse_url
> > > > > > > >
> > > > > > > > It was pointed out that pni_parse_url is an internal
> function and
> > > > the
> > > > > > > > interface
> > > > > > > > is not suitable for public API.
> > > > > > > >
> > > > > > > > Rewrote the URL parser as a proper swigable C API pn_url_*.
> This
> > > > gets
> > > > > > rid
> > > > > > > > of the
> > > > > > > > need for previous swig insanity and is cleaner all round.
> > > > > > > >
> > > > > > > > Internally still uses the pni_parse_url parser, we can clean
> that
> > > > up
> > > > > > later.
> > > > > > > >
> > > > > > > > Added:
> > > > > > > >     qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > > >     qpid/proton/trunk/proton-c/src/url.c
> > > > > > > > Modified:
> > > > > > > >     qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > > >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > > >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > > >     qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19
> 21:00:50
> > > > 2014
> > > > > > > > @@ -270,6 +270,7 @@ set (qpid-proton-core
> > > > > > > >    src/object/iterator.c
> > > > > > > >
> > > > > > > >    src/util.c
> > > > > > > > +  src/url.c
> > > > > > > >    src/error.c
> > > > > > > >    src/buffer.c
> > > > > > > >    src/parser.c
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i
> (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep
> 19
> > > > 21:00:50
> > > > > > > > 2014
> > > > > > > > @@ -8,6 +8,7 @@
> > > > > > > >  #include <proton/messenger.h>
> > > > > > > >  #include <proton/ssl.h>
> > > > > > > >  #include <proton/driver_extras.h>
> > > > > > > > +#include <proton/url.h>
> > > > > > > >  %}
> > > > > > > >
> > > > > > > >  %include <cstring.i>
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19
> > > > 21:00:50
> > > > > > 2014
> > > > > > > > @@ -29,6 +29,7 @@
> > > > > > > >  %header %{
> > > > > > > >  /* Include the headers needed by the code in this wrapper
> file */
> > > > > > > >  #include <proton/types.h>
> > > > > > > > +#include <proton/url.h>
> > > > > > > >  #include <proton/message.h>
> > > > > > > >  #include <proton/driver.h>
> > > > > > > >  #include <proton/driver_extras.h>
> > > > > > > >
> > > > > > > > Modified:
> qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i
> (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri
> Sep 19
> > > > > > > > 21:00:50 2014
> > > > > > > > @@ -23,6 +23,7 @@
> > > > > > > >  #include <winsock2.h>
> > > > > > > >  #endif
> > > > > > > >  #include <proton/engine.h>
> > > > > > > > +#include <proton/url.h>
> > > > > > > >  #include <proton/message.h>
> > > > > > > >  #include <proton/sasl.h>
> > > > > > > >  #include <proton/driver.h>
> > > > > > > > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> > > > > > > >    }
> > > > > > > >  %}
> > > > > > > >
> > > > > > > > -
> > > > > > > > -/**
> > > > > > > > -   pni_parse_url(char* url, char **scheme, char **user, char
> > > > **pass,
> > > > > > char
> > > > > > > > **host, char **port, char **path)
> > > > > > > > -   The following type maps convert this into a python
> function
> > > > that
> > > > > > taks
> > > > > > > > a URL string argument
> > > > > > > > -   and returns a list of strings [scheme, user, pass, host,
> port,
> > > > > > path]
> > > > > > > > -   This probably could be done more neatly.
> > > > > > > > -*/
> > > > > > > > -
> > > > > > > > -// Typemap to copy the url string as it will be modified by
> > > > parse_url
> > > > > > > > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize")
> char *url
> > > > (int
> > > > > > > > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > > > > > > > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > > > > > > > -  if (!SWIG_IsOK(res)) {
> > > > > > > > -    %argument_fail(res, "char *url", $symname, $argnum);
> > > > > > > > -  }
> > > > > > > > -  $1 = %new_array(n, $*1_ltype);
> > > > > > > > -  memcpy($1,t,sizeof(char)*n);
> > > > > > > > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > > > > > > > -  $1[n-1] = 0;
> > > > > > > > -}
> > > > > > > > -%typemap(freearg,match="in") char *url "free($1);";
> > > > > > > > -%typemap(argout) char *url "";
> > > > > > > > -
> > > > > > > > -// Typemap for char** return strings. Don't free them.
> > > > > > > > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0)
> "$1 =
> > > > > > &temp;";
> > > > > > > > -%typemap(freearg,match="in") char **OUTSTR "";
> > > > > > > > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char
> > > > **OUTSTR {
> > > > > > > > -    %append_output(SWIG_FromCharPtr(*$1));
> > > > > > > > -}
> > > > > > > > -
> > > > > > > > -// Typemap to initialize result as empty list
> > > > > > > > -%typemap(out) void "$result = PyList_New(0);";
> > > > > > > > -
> > > > > > > > -
> > > > > > > > -%apply char** OUTSTR {char **scheme, char **user, char
> **pass,
> > > > char
> > > > > > > > **host, char **port, char **path};
> > > > > > > > -void pni_parse_url(char* url, char **scheme, char **user,
> char
> > > > **pass,
> > > > > > > > char **host, char **port, char **path);
> > > > > > > > -%ignore pni_parse_url;
> > > > > > > > -
> > > > > > > >  %include "proton/cproton.i"
> > > > > > > >
> > > > > > > > Modified:
> qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/python/proton.py
> (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri
> Sep 19
> > > > > > > > 21:00:50 2014
> > > > > > > > @@ -3657,114 +3657,98 @@ __all__ = [
> > > > > > > >
> > > > > > > >
> > > > > > > >  class Url(object):
> > > > > > > > -    """
> > > > > > > > -    Simple URL parser/constructor, handles URLs of the form:
> > > > > > > > +  """
> > > > > > > > +  Simple URL parser/constructor, handles URLs of the form:
> > > > > > > >
> > > > > > > > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > > > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > > >
> > > > > > > > -    All components can be None if not specifeid in the URL
> string.
> > > > > > > > +  All components can be None if not specifeid in the URL
> string.
> > > > > > > >
> > > > > > > > -    The port can be specified as a service name, e.g.
> 'amqp' in
> > > > the
> > > > > > > > -    URL string but Url.port always gives the integer value.
> > > > > > > > +  The port can be specified as a service name, e.g. 'amqp'
> in the
> > > > > > > > +  URL string but Url.port always gives the integer value.
> > > > > > > > +
> > > > > > > > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > > > +  @ivar user: Username
> > > > > > > > +  @ivar password: Password
> > > > > > > > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > > > +  @ivar port: Integer port.
> > > > > > > > +  @ivar host_port: Returns host:port
> > > > > > > > +  """
> > > > > > > > +
> > > > > > > > +  AMQPS = "amqps"
> > > > > > > > +  AMQP = "amqp"
> > > > > > > > +
> > > > > > > > +  class Port(int):
> > > > > > > > +    """An integer port number that can be constructed from a
> > > > service
> > > > > > name
> > > > > > > > string"""
> > > > > > > > +
> > > > > > > > +    def __new__(cls, value):
> > > > > > > > +      port = super(Url.Port, cls).__new__(cls,
> > > > cls.port_int(value))
> > > > > > > > +      setattr(port, 'name', str(value))
> > > > > > > > +      return port
> > > > > > > > +
> > > > > > > > +    def __eq__(self, x): return str(self) == x or int(self)
> == x
> > > > > > > > +    def __ne__(self, x): return not self == x
> > > > > > > > +    def __str__(self): return str(self.name)
> > > > > > > > +
> > > > > > > > +    @staticmethod
> > > > > > > > +    def port_int(value):
> > > > > > > > +      """Convert service, an integer or a service name,
> into an
> > > > > > integer
> > > > > > > > port number."""
> > > > > > > > +      try:
> > > > > > > > +        return int(value)
> > > > > > > > +      except ValueError:
> > > > > > > > +        try:
> > > > > > > > +          return socket.getservbyname(value)
> > > > > > > > +        except socket.error:
> > > > > > > > +          raise ValueError("Not a valid port number or
> service
> > > > name:
> > > > > > > > '%s'" % value)
> > > > > > > >
> > > > > > > > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > > > -    @ivar user: Username
> > > > > > > > -    @ivar password: Password
> > > > > > > > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > > > -    @ivar port: Integer port.
> > > > > > > > -    @ivar host_port: Returns host:port
> > > > > > > > +  def __init__(self, url=None, **kwargs):
> > > > > > > > +    """
> > > > > > > > +    @param url: URL string to parse.
> > > > > > > > +    @param kwargs: scheme, user, password, host, port, path.
> > > > > > > > +      If specified, replaces corresponding part in url
> string.
> > > > > > > >      """
> > > > > > > > +    if url:
> > > > > > > > +      self._url = pn_url_parse(str(url))
> > > > > > > > +      if not self._url: raise ValueError("Invalid URL '%s'"
> % url)
> > > > > > > > +    else:
> > > > > > > > +      self._url = pn_url()
> > > > > > > > +    for k in kwargs:            # Let kwargs override values
> > > > parsed
> > > > > > from
> > > > > > > > url
> > > > > > > > +      getattr(self, k)          # Check for invalid kwargs
> > > > > > > > +      setattr(self, k, kwargs[k])
> > > > > > > > +
> > > > > > > > +  class PartDescriptor(object):
> > > > > > > > +    def __init__(self, part):
> > > > > > > > +      self.getter = globals()["pn_url_%s" % part]
> > > > > > > > +      self.setter = globals()["pn_url_set_%s" % part]
> > > > > > > > +    def __get__(self, obj, type=None): return
> > > > self.getter(obj._url)
> > > > > > > > +    def __set__(self, obj, value): return
> self.setter(obj._url,
> > > > > > > > str(value))
> > > > > > > > +
> > > > > > > > +  scheme = PartDescriptor('scheme')
> > > > > > > > +  username = PartDescriptor('username')
> > > > > > > > +  password = PartDescriptor('password')
> > > > > > > > +  host = PartDescriptor('host')
> > > > > > > > +  path = PartDescriptor('path')
> > > > > > > > +
> > > > > > > > +  @property
> > > > > > > > +  def port(self):
> > > > > > > > +    portstr = pn_url_port(self._url)
> > > > > > > > +    return portstr and Url.Port(portstr)
> > > > > > > > +
> > > > > > > > +  @port.setter
> > > > > > > > +  def port(self, value):
> > > > > > > > +    if value is None: pn_url_set_port(self._url, None)
> > > > > > > > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> > > > > > > >
> > > > > > > > -    AMQPS = "amqps"
> > > > > > > > -    AMQP = "amqp"
> > > > > > > > +  def __str__(self): return pn_url_str(self._url)
> > > > > > > >
> > > > > > > > -    class Port(int):
> > > > > > > > -      """An integer port number that can also have an
> associated
> > > > > > service
> > > > > > > > name string"""
> > > > > > > > +  def __repr__(self): return "Url(%r)" % str(self)
> > > > > > > >
> > > > > > > > -      def __new__(cls, value):
> > > > > > > > -        port = super(Url.Port, cls).__new__(cls,
> > > > cls.port_int(value))
> > > > > > > > -        setattr(port, 'name', str(value))
> > > > > > > > -        return port
> > > > > > > > -
> > > > > > > > -      def __eq__(self, x): return str(self) == x or
> int(self) == x
> > > > > > > > -      def __ne__(self, x): return not self == x
> > > > > > > > -      def __str__(self): return str(self.name)
> > > > > > > > -
> > > > > > > > -      @staticmethod
> > > > > > > > -      def port_int(value):
> > > > > > > > -        """Convert service, an integer or a service name,
> into an
> > > > > > integer
> > > > > > > > port number."""
> > > > > > > > -        try:
> > > > > > > > -          return int(value)
> > > > > > > > -        except ValueError:
> > > > > > > > -          try:
> > > > > > > > -            return socket.getservbyname(value)
> > > > > > > > -          except socket.error:
> > > > > > > > -            raise ValueError("Not a valid port number or
> service
> > > > name:
> > > > > > > > '%s'" % value)
> > > > > > > > -
> > > > > > > > -    def __init__(self, url=None, **kwargs):
> > > > > > > > -        """
> > > > > > > > -        @param url: String or Url instance to parse or copy.
> > > > > > > > -        @param kwargs: URL fields: scheme, user, password,
> host,
> > > > port,
> > > > > > > > path.
> > > > > > > > -            If specified, replaces corresponding component
> in url.
> > > > > > > > -        """
> > > > > > > > -
> > > > > > > > -        fields = ['scheme', 'user', 'password', 'host',
> 'port',
> > > > > > 'path']
> > > > > > > > -
> > > > > > > > -        for f in fields: setattr(self, f, None)
> > > > > > > > -        for k in kwargs: getattr(self, k) # Check for
> invalid
> > > > kwargs
> > > > > > > > -
> > > > > > > > -        if isinstance(url, Url): # Copy from another Url
> instance.
> > > > > > > > -            self.__dict__.update(url.__dict__)
> > > > > > > > -        elif url is not None:   # Parse from url
> > > > > > > > -            parts = pni_parse_url(str(url))
> > > > > > > > -            if not filter(None, parts): raise
> ValueError("Invalid
> > > > AMQP
> > > > > > > > URL: '%s'" % url)
> > > > > > > > -            self.scheme, self.user, self.password,
> self.host,
> > > > port,
> > > > > > > > self.path = parts
> > > > > > > > -            if not self.host: self.host = None
> > > > > > > > -            self.port = port and self.Port(port)
> > > > > > > > -
> > > > > > > > -        # Let kwargs override values previously set from url
> > > > > > > > -        for field in fields:
> > > > > > > > -            setattr(self, field, kwargs.get(field,
> getattr(self,
> > > > > > field)))
> > > > > > > > -
> > > > > > > > -    def __repr__(self):
> > > > > > > > -        return "Url(%r)" % str(self)
> > > > > > > > -
> > > > > > > > -    def __str__(self):
> > > > > > > > -        s = ""
> > > > > > > > -        if self.scheme:
> > > > > > > > -            s += "%s://" % self.scheme
> > > > > > > > -        if self.user:
> > > > > > > > -            s += self.user
> > > > > > > > -        if self.password:
> > > > > > > > -            s += ":%s" % self.password
> > > > > > > > -        if self.user or self.password:
> > > > > > > > -            s += '@'
> > > > > > > > -        if self.host and ':' in self.host:
> > > > > > > > -            s += "[%s]" % self.host
> > > > > > > > -        elif self.host:
> > > > > > > > -            s += self.host
> > > > > > > > -        if self.port:
> > > > > > > > -            s += ":%s" % self.port
> > > > > > > > -        if self.path:
> > > > > > > > -            s += "/%s" % self.path
> > > > > > > > -        return s
> > > > > > > > -
> > > > > > > > -    def __eq__(self, url):
> > > > > > > > -        return \
> > > > > > > > -            self.scheme == url.scheme and \
> > > > > > > > -            self.user == url.user and self.password ==
> > > > url.password
> > > > > > and \
> > > > > > > > -            self.host == url.host and self.port == url.port
> and \
> > > > > > > > -            self.path == url.path
> > > > > > > > -
> > > > > > > > -    def __ne__(self, url):
> > > > > > > > -        return not self.__eq__(url)
> > > > > > > > -
> > > > > > > > -    def defaults(self):
> > > > > > > > -        """
> > > > > > > > -        Fill in missing values with defaults
> > > > > > > > -        @return: self
> > > > > > > > -        """
> > > > > > > > -        self.scheme = self.scheme or self.AMQP
> > > > > > > > -        self.host = self.host or '0.0.0.0'
> > > > > > > > -        self.port = self.port or self.Port(self.scheme)
> > > > > > > > -        return self
> > > > > > > > +  def defaults(self):
> > > > > > > > +    """
> > > > > > > > +    Fill in missing values (scheme, host or port) with
> defaults
> > > > > > > > +    @return: self
> > > > > > > > +    """
> > > > > > > > +    self.scheme = self.scheme or self.AMQP
> > > > > > > > +    self.host = self.host or '0.0.0.0'
> > > > > > > > +    self.port = self.port or self.Port(self.scheme)
> > > > > > > > +    return self
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep
> 19
> > > > 21:00:50
> > > > > > > > 2014
> > > > > > > > @@ -26,8 +26,8 @@
> > > > > > > >  #include <proton/messenger.h>
> > > > > > > >  #include <proton/ssl.h>
> > > > > > > >  #include <proton/driver_extras.h>
> > > > > > > > -
> > > > > > > >  #include <proton/types.h>
> > > > > > > > +#include <proton/url.h>
> > > > > > > >
> > > > > > > >  #include <uuid/uuid.h>
> > > > > > > >  %}
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/include/proton/cproton.i
> (original)
> > > > > > > > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri
> Sep 19
> > > > > > > > 21:00:50 2014
> > > > > > > > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> > > > > > > >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return
> > > > (pn_delivery_t
> > > > > > *)
> > > > > > > > x; }
> > > > > > > >    pn_transport_t *pn_cast_pn_transport(void *x) { return
> > > > > > (pn_transport_t
> > > > > > > > *) x; }
> > > > > > > >  %}
> > > > > > > > +
> > > > > > > > +%include "proton/url.h"
> > > > > > > > +
> > > > > > > >
> > > > > > > > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > > > > > > > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep
> 19
> > > > 21:00:50
> > > > > > > > 2014
> > > > > > > > @@ -0,0 +1,83 @@
> > > > > > > > +#ifndef PROTON_URL_H
> > > > > > > > +#define PROTON_URL_H
> > > > > > > > +/*
> > > > > > > > + * 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.
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +#include <proton/import_export.h>
> > > > > > > > +
> > > > > > > > +/** @file
> > > > > > > > + * URL API for parsing URLs.
> > > > > > > > + *
> > > > > > > > + * @defgroup url URL
> > > > > > > > + * @{
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +/** A parsed URL */
> > > > > > > > +typedef struct pn_url_t pn_url_t;
> > > > > > > > +
> > > > > > > > +/** Create an empty URL */
> > > > > > > > +PN_EXTERN pn_url_t *pn_url(void);
> > > > > > > > +
> > > > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > > > + *@param[in] url A URL string.
> > > > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid
> URL
> > > > > > string.
> > > > > > > > + */
> > > > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > > > > > > > +
> > > > > > > > +/** Free a URL */
> > > > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > > > > > > > +
> > > > > > > > +/** Clear the contents of the URL. */
> > > > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > > > > > > > +
> > > > > > > > +/** Return the string form of a URL. Owned by the
> pn_url_t.*/
> > > > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + *@name Getters for parts of the URL.
> > > > > > > > + *
> > > > > > > > + *Values belong to the URL. May return NULL if the value is
> not
> > > > set.
> > > > > > > > + *
> > > > > > > > + *@{
> > > > > > > > + */
> > > > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > > > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > > > > > > > +///@}
> > > > > > > > +
> > > > > > > > +/**
> > > > > > > > + *@name Setters for parts of the URL.
> > > > > > > > + *
> > > > > > > > + *Values are copied. Value can be NULL to indicate the part
> is not
> > > > > > set.
> > > > > > > > + *
> > > > > > > > + *@{
> > > > > > > > + */
> > > > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > > > *scheme);
> > > > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > > > *username);
> > > > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > > > *password);
> > > > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char
> *host);
> > > > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char
> *port);
> > > > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char
> *path);
> > > > > > > > +///@}
> > > > > > > > +
> > > > > > > > +///@}
> > > > > > > > +#endif
> > > > > > > >
> > > > > > > > Added: qpid/proton/trunk/proton-c/src/url.c
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > > > > > > > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50
> 2014
> > > > > > > > @@ -0,0 +1,127 @@
> > > > > > > > +/*
> > > > > > > > + *
> > > > > > > > + * 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.
> > > > > > > > + *
> > > > > > > > + */
> > > > > > > > +
> > > > > > > > +#include <proton/url.h>
> > > > > > > > +#include <proton/util.h>
> > > > > > > > +#include <stdlib.h>
> > > > > > > > +#include <string.h>
> > > > > > > > +#include <stdio.h>
> > > > > > > > +
> > > > > > > > +static char* copy(const char* str) {
> > > > > > > > +    if (str ==  NULL) return NULL;
> > > > > > > > +    char *str2 = (char*)malloc(strlen(str));
> > > > > > > > +    if (str2) strcpy(str2, str);
> > > > > > > > +    return str2;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +struct pn_url_t {
> > > > > > > > +    char *scheme;
> > > > > > > > +    char *username;
> > > > > > > > +    char *password;
> > > > > > > > +    char *host;
> > > > > > > > +    char *port;
> > > > > > > > +    char *path;
> > > > > > > > +    char *str;
> > > > > > > > +};
> > > > > > > > +
> > > > > > > > +PN_EXTERN pn_url_t *pn_url() {
> > > > > > > > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > > > > > > > +    memset(url, 0, sizeof(*url));
> > > > > > > > +    return url;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > > > + *@param[in] url A URL string.
> > > > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid
> URL
> > > > > > string.
> > > > > > > > + */
> > > > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > > > > > > > +    if (!str || !*str)          /* Empty string or NULL is
> > > > illegal. */
> > > > > > > > +        return NULL;
> > > > > > > > +
> > > > > > > > +    pn_url_t *url = pn_url();
> > > > > > > > +    char *str2 = copy(str);         /* FIXME aconway
> 2014-09-19:
> > > > > > clean up
> > > > > > > > */
> > > > > > > > +    pni_parse_url(str2, &url->scheme, &url->username,
> > > > &url->password,
> > > > > > > > &url->host, &url->port, &url->path);
> > > > > > > > +    url->scheme = copy(url->scheme);
> > > > > > > > +    url->username = copy(url->username);
> > > > > > > > +    url->password = copy(url->password);
> > > > > > > > +    url->host = (url->host && !*url->host) ? NULL :
> > > > copy(url->host);
> > > > > > > > +    url->port = copy(url->port);
> > > > > > > > +    url->path = copy(url->path);
> > > > > > > > +    return url;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +/** Free a URL */
> > > > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > > > > > > > +    pn_url_clear(url);
> > > > > > > > +    free(url);
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +/** Clear the contents of the URL. */
> > > > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > > > > > > > +    pn_url_set_username(url, NULL);
> > > > > > > > +    pn_url_set_password(url, NULL);
> > > > > > > > +    pn_url_set_host(url, NULL);
> > > > > > > > +    pn_url_set_port(url, NULL);
> > > > > > > > +    pn_url_set_path(url, NULL);
> > > > > > > > +    free(url->str); url->str = NULL;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +static inline int len(const char *str) { return str ?
> strlen(str)
> > > > :
> > > > > > 0; }
> > > > > > > > +
> > > > > > > > +/** Return the string form of a URL. */
> > > > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > > > > > > > +    int size = len(url->scheme) + len(url->username) +
> > > > > > len(url->password)
> > > > > > > > +        + len(url->host) + len(url->port) + len(url->path)
> > > > > > > > +        + len("s://u:p@[h]:p/p");
> > > > > > > > +    free(url->str);
> > > > > > > > +    url->str = (char*)malloc(size);
> > > > > > > > +    if (!url->str) return NULL;
> > > > > > > > +
> > > > > > > > +    int i = 0;
> > > > > > > > +    if (url->scheme) i += snprintf(url->str+i, size-i,
> "%s://",
> > > > > > > > url->scheme);
> > > > > > > > +    if (url->username) i += snprintf(url->str+i, size-i,
> "%s",
> > > > > > > > url->username);
> > > > > > > > +    if (url->password) i += snprintf(url->str+i, size-i,
> ":%s",
> > > > > > > > url->password);
> > > > > > > > +    if (url->username || url->password) i +=
> snprintf(url->str+i,
> > > > > > size-i,
> > > > > > > > "@");
> > > > > > > > +    if (url->host) {
> > > > > > > > +        if (strchr(url->host, ':')) i +=
> snprintf(url->str+i,
> > > > size-i,
> > > > > > > > "[%s]", url->host);
> > > > > > > > +        else i += snprintf(url->str+i, size-i, "%s",
> url->host);
> > > > > > > > +    }
> > > > > > > > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
> > > > > > url->port);
> > > > > > > > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
> > > > > > url->path);
> > > > > > > > +    return url->str;
> > > > > > > > +}
> > > > > > > > +
> > > > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
> > > > > > url->scheme; }
> > > > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url) {
> return
> > > > > > > > url->username; }
> > > > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url) {
> return
> > > > > > > > url->password; }
> > > > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return
> > > > url->host; }
> > > > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return
> > > > url->port; }
> > > > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return
> > > > url->path; }
> > > > > > > > +
> > > > > > > > +#define SET(part) free(url->part); url->part = copy(part)
> > > > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > > > *scheme) {
> > > > > > > > SET(scheme); }
> > > > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > > > *username) {
> > > > > > > > SET(username); }
> > > > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > > > *password) {
> > > > > > > > SET(password); }
> > > > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char
> *host) {
> > > > > > > > SET(host); }
> > > > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char
> *port) {
> > > > > > > > SET(port); }
> > > > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char
> *path) {
> > > > > > > > SET(path); }
> > > > > > > > +
> > > > > > > > +
> > > > > > > >
> > > > > > > > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > > > URL:
> > > > > > > >
> > > > > >
> > > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > > >
> > > > > > > >
> > > > > >
> > > >
> ==============================================================================
> > > > > > > > --- qpid/proton/trunk/tests/python/proton_tests/url.py
> (original)
> > > > > > > > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri
> Sep 19
> > > > > > 21:00:50
> > > > > > > > 2014
> > > > > > > > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> > > > > > > >      def assertNotEqual(self, a, b):
> > > > > > > >          assert a != b, "%s == %s" % (a, b)
> > > > > > > >
> > > > > > > > -    def assertUrl(self, u, scheme, user, password, host,
> port,
> > > > path):
> > > > > > > > -        self.assertEqual((u.scheme, u.user, u.password,
> u.host,
> > > > > > u.port,
> > > > > > > > u.path),
> > > > > > > > -                         (scheme, user, password, host,
> port,
> > > > path))
> > > > > > > > +    def assertUrl(self, u, scheme, username, password,
> host, port,
> > > > > > path):
> > > > > > > > +        self.assertEqual((u.scheme, u.username, u.password,
> > > > u.host,
> > > > > > > > u.port, u.path),
> > > > > > > > +                         (scheme, username, password, host,
> port,
> > > > > > path))
> > > > > > > >
> > > > > > > >      def testUrl(self):
> > > > > > > >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > > > > > > > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> > > > > > > >
> > > > > > > >      def testDefaults(self):
> > > > > > > >          # Check that we allow None for scheme, port
> > > > > > > > -        url = Url(user='me', password='secret',
> host='myhost',
> > > > > > > > path='foobar')
> > > > > > > > +        url = Url(username='me', password='secret',
> host='myhost',
> > > > > > > > path='foobar')
> > > > > > > >          self.assertEqual(str(url), "me:secret@myhost
> /foobar")
> > > > > > > >          self.assertUrl(url, None, 'me', 'secret', 'myhost',
> None,
> > > > > > > > 'foobar')
> > > > > > > >
> > > > > > > > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> > > > > > > >      def testMissing(self):
> > > > > > > >          self.assertUrl(Url(), None, None, None, None, None,
> None)
> > > > > > > >          self.assertUrl(Url('amqp://'), 'amqp', None, None,
> None,
> > > > None,
> > > > > > > > None)
> > > > > > > > -        self.assertUrl(Url('user@'), None, 'user', None,
> None,
> > > > None,
> > > > > > > > None)
> > > > > > > > +        self.assertUrl(Url('username@'), None, 'username',
> None,
> > > > > > None,
> > > > > > > > None, None)
> > > > > > > >          self.assertUrl(Url(':pass@'), None, '', 'pass',
> None,
> > > > None,
> > > > > > None)
> > > > > > > >          self.assertUrl(Url('host'), None, None, None,
> 'host',
> > > > None,
> > > > > > None)
> > > > > > > >          self.assertUrl(Url(':1234'), None, None, None,
> None, 1234,
> > > > > > None)
> > > > > > > >          self.assertUrl(Url('/path'), None, None, None,
> None, None,
> > > > > > 'path')
> > > > > > > >
> > > > > > > > -        for s in ['amqp://', 'user@', ':pass@', ':1234',
> > > > '/path']:
> > > > > > > > +        for s in ['amqp://', 'username@', ':pass@',
> ':1234',
> > > > > > '/path']:
> > > > > > > >              self.assertEqual(s, str(Url(s)))
> > > > > > > >
> > > > > > > >          for s, full in [
> > > > > > > >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > > > > > > > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > > > > > > > +                ('username@', 'amqp://username@0.0.0.0:
> amqp'),
> > > > > > > >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> > > > > > > >                  (':1234', 'amqp://0.0.0.0:1234'),
> > > > > > > >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> > > > > > > >              self.assertEqual(str(Url(s).defaults()), full)
> > > > > > > > -
> > > > > > > > -        self.assertRaises(ValueError, Url, '')
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > > > > >
> > > > ---------------------------------------------------------------------
> > > > > > > > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > > > > > > > For additional commands, e-mail:
> commits-help@qpid.apache.org
> > > > > > > >
> > > > > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > >
> ---------------------------------------------------------------------
> > > > > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > > > > For additional commands, e-mail: dev-help@qpid.apache.org
> > > > > >
> > > > > >
> > > >
> > > >
> > > >
> > > > ---------------------------------------------------------------------
> > > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > > For additional commands, e-mail: dev-help@qpid.apache.org
> > > >
> > > >
> >
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> For additional commands, e-mail: dev-help@qpid.apache.org
>
>

Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Alan Conway <ac...@redhat.com>.
Hum, CI is still broken.

https://builds.apache.org/job/Qpid-proton-j/org.apache.qpid
$proton-tests/683/testReport/org.apache.qpid.proton/JythonTest/test/

Somehow my trivial re-org of the URL tests in python has caused the
entire Jython test harness to explode in flight. It works fine on my box
in python and Jython, and it works on CI in regular python - so maybe
another Java 6 issue? Will I lose my mind if I try to install Java 6 on
Fedora and get proton to use it?

On Thu, 2014-09-25 at 13:59 -0400, Alan Conway wrote:
> On Thu, 2014-09-25 at 15:59 +0100, Robbie Gemmell wrote:
> > On 25 September 2014 15:00, Alan Conway <ac...@redhat.com> wrote:
> > 
> > > On Wed, 2014-09-24 at 12:19 +0100, Robbie Gemmell wrote:
> > > > The tests are now running again, but a couple of the URL tests still seem
> > > > to be failing on the CI job:
> > > >
> > > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/
> > > >
> > >
> > > They are all failing with:
> > >  Not a valid port number or service name: 'amqps'
> > >
> > > Could this be a configuration problem on the CI machine, i.e. missing an
> > > 'amqps' entry in /etc/services? Can I get access to the CI machine to
> > > poke around and see what's up?
> > >
> > 
> > Almost certainly no, only the core maintainers are allowed shell access as
> > far as I've seen. You can ask on builds@apache.org for those with access to
> > check things out and report back and see what happens.
> > 
> > I think the CI instances will be running Ubuntu 12.04 or 14.04 LTS. For
> > giggles, I dug out an ooooold Ubuntu VM with Java 6 on it and tried the
> > tests, which failed, and it indeed has no amqp[s] entry in /etc/services
> > file so that could well be it.
> 
> Thanks for checking that out! I have hacked the tests to skip tests for
> 'amqps' if it is not recognized. Poke me if there are still failures.
> 
> ------------------------------------------------------------------------
> r1627577 | aconway | 2014-09-25 13:59:17 -0400 (Thu, 25 Sep 2014) | 5
> lines
> 
> NO-JIRA: Fix URL test to skip 'amqps' tests if 'amqps' is not recognized
> as a service name.
> 
> On some older Ubuntu with Java 6, 'amqps' is not recognized as a service
> name so
> skip those tests in that case.
> 
> ------------------------------------------------------------------------
> 
> > >
> > > The URL code uses socket.getservbyname() to look up service names. Is
> > > there a more portable way to do it?
> > >
> > 
> > No idea I'm afraid.
> > 
> > 
> > >
> > > Cheers,
> > > Alan.
> > >
> > > > As mentioned in my other post about a timeline for dropping Java6
> > > support,
> > > > they seem to work on Java8 (havent tried Java7).
> > > >
> > > > Robbie
> > > >
> > > > On 22 September 2014 21:14, Alan Conway <ac...@redhat.com> wrote:
> > > >
> > > > > My bad, didn't run the java tests. Will fix ASAP and then give myself a
> > > > > flogging.
> > > > >
> > > > > On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> > > > > > This seems to have broken the Java test runs:
> > > > > >
> > > > > > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> > > > > >
> > > > > >
> > > > > >
> > > > > > On 19 September 2014 22:00, <ac...@apache.org> wrote:
> > > > > >
> > > > > > > Author: aconway
> > > > > > > Date: Fri Sep 19 21:00:50 2014
> > > > > > > New Revision: 1626329
> > > > > > >
> > > > > > > URL: http://svn.apache.org/r1626329
> > > > > > > Log:
> > > > > > > PROTON-693: Python Url class to wrap C function pni_parse_url
> > > > > > >
> > > > > > > It was pointed out that pni_parse_url is an internal function and
> > > the
> > > > > > > interface
> > > > > > > is not suitable for public API.
> > > > > > >
> > > > > > > Rewrote the URL parser as a proper swigable C API pn_url_*. This
> > > gets
> > > > > rid
> > > > > > > of the
> > > > > > > need for previous swig insanity and is cleaner all round.
> > > > > > >
> > > > > > > Internally still uses the pni_parse_url parser, we can clean that
> > > up
> > > > > later.
> > > > > > >
> > > > > > > Added:
> > > > > > >     qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > >     qpid/proton/trunk/proton-c/src/url.c
> > > > > > > Modified:
> > > > > > >     qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > >     qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > >     qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19 21:00:50
> > > 2014
> > > > > > > @@ -270,6 +270,7 @@ set (qpid-proton-core
> > > > > > >    src/object/iterator.c
> > > > > > >
> > > > > > >    src/util.c
> > > > > > > +  src/url.c
> > > > > > >    src/error.c
> > > > > > >    src/buffer.c
> > > > > > >    src/parser.c
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19
> > > 21:00:50
> > > > > > > 2014
> > > > > > > @@ -8,6 +8,7 @@
> > > > > > >  #include <proton/messenger.h>
> > > > > > >  #include <proton/ssl.h>
> > > > > > >  #include <proton/driver_extras.h>
> > > > > > > +#include <proton/url.h>
> > > > > > >  %}
> > > > > > >
> > > > > > >  %include <cstring.i>
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19
> > > 21:00:50
> > > > > 2014
> > > > > > > @@ -29,6 +29,7 @@
> > > > > > >  %header %{
> > > > > > >  /* Include the headers needed by the code in this wrapper file */
> > > > > > >  #include <proton/types.h>
> > > > > > > +#include <proton/url.h>
> > > > > > >  #include <proton/message.h>
> > > > > > >  #include <proton/driver.h>
> > > > > > >  #include <proton/driver_extras.h>
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri Sep 19
> > > > > > > 21:00:50 2014
> > > > > > > @@ -23,6 +23,7 @@
> > > > > > >  #include <winsock2.h>
> > > > > > >  #endif
> > > > > > >  #include <proton/engine.h>
> > > > > > > +#include <proton/url.h>
> > > > > > >  #include <proton/message.h>
> > > > > > >  #include <proton/sasl.h>
> > > > > > >  #include <proton/driver.h>
> > > > > > > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> > > > > > >    }
> > > > > > >  %}
> > > > > > >
> > > > > > > -
> > > > > > > -/**
> > > > > > > -   pni_parse_url(char* url, char **scheme, char **user, char
> > > **pass,
> > > > > char
> > > > > > > **host, char **port, char **path)
> > > > > > > -   The following type maps convert this into a python function
> > > that
> > > > > taks
> > > > > > > a URL string argument
> > > > > > > -   and returns a list of strings [scheme, user, pass, host, port,
> > > > > path]
> > > > > > > -   This probably could be done more neatly.
> > > > > > > -*/
> > > > > > > -
> > > > > > > -// Typemap to copy the url string as it will be modified by
> > > parse_url
> > > > > > > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char *url
> > > (int
> > > > > > > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > > > > > > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > > > > > > -  if (!SWIG_IsOK(res)) {
> > > > > > > -    %argument_fail(res, "char *url", $symname, $argnum);
> > > > > > > -  }
> > > > > > > -  $1 = %new_array(n, $*1_ltype);
> > > > > > > -  memcpy($1,t,sizeof(char)*n);
> > > > > > > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > > > > > > -  $1[n-1] = 0;
> > > > > > > -}
> > > > > > > -%typemap(freearg,match="in") char *url "free($1);";
> > > > > > > -%typemap(argout) char *url "";
> > > > > > > -
> > > > > > > -// Typemap for char** return strings. Don't free them.
> > > > > > > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0) "$1 =
> > > > > &temp;";
> > > > > > > -%typemap(freearg,match="in") char **OUTSTR "";
> > > > > > > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char
> > > **OUTSTR {
> > > > > > > -    %append_output(SWIG_FromCharPtr(*$1));
> > > > > > > -}
> > > > > > > -
> > > > > > > -// Typemap to initialize result as empty list
> > > > > > > -%typemap(out) void "$result = PyList_New(0);";
> > > > > > > -
> > > > > > > -
> > > > > > > -%apply char** OUTSTR {char **scheme, char **user, char **pass,
> > > char
> > > > > > > **host, char **port, char **path};
> > > > > > > -void pni_parse_url(char* url, char **scheme, char **user, char
> > > **pass,
> > > > > > > char **host, char **port, char **path);
> > > > > > > -%ignore pni_parse_url;
> > > > > > > -
> > > > > > >  %include "proton/cproton.i"
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri Sep 19
> > > > > > > 21:00:50 2014
> > > > > > > @@ -3657,114 +3657,98 @@ __all__ = [
> > > > > > >
> > > > > > >
> > > > > > >  class Url(object):
> > > > > > > -    """
> > > > > > > -    Simple URL parser/constructor, handles URLs of the form:
> > > > > > > +  """
> > > > > > > +  Simple URL parser/constructor, handles URLs of the form:
> > > > > > >
> > > > > > > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > >
> > > > > > > -    All components can be None if not specifeid in the URL string.
> > > > > > > +  All components can be None if not specifeid in the URL string.
> > > > > > >
> > > > > > > -    The port can be specified as a service name, e.g. 'amqp' in
> > > the
> > > > > > > -    URL string but Url.port always gives the integer value.
> > > > > > > +  The port can be specified as a service name, e.g. 'amqp' in the
> > > > > > > +  URL string but Url.port always gives the integer value.
> > > > > > > +
> > > > > > > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > > +  @ivar user: Username
> > > > > > > +  @ivar password: Password
> > > > > > > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > > +  @ivar port: Integer port.
> > > > > > > +  @ivar host_port: Returns host:port
> > > > > > > +  """
> > > > > > > +
> > > > > > > +  AMQPS = "amqps"
> > > > > > > +  AMQP = "amqp"
> > > > > > > +
> > > > > > > +  class Port(int):
> > > > > > > +    """An integer port number that can be constructed from a
> > > service
> > > > > name
> > > > > > > string"""
> > > > > > > +
> > > > > > > +    def __new__(cls, value):
> > > > > > > +      port = super(Url.Port, cls).__new__(cls,
> > > cls.port_int(value))
> > > > > > > +      setattr(port, 'name', str(value))
> > > > > > > +      return port
> > > > > > > +
> > > > > > > +    def __eq__(self, x): return str(self) == x or int(self) == x
> > > > > > > +    def __ne__(self, x): return not self == x
> > > > > > > +    def __str__(self): return str(self.name)
> > > > > > > +
> > > > > > > +    @staticmethod
> > > > > > > +    def port_int(value):
> > > > > > > +      """Convert service, an integer or a service name, into an
> > > > > integer
> > > > > > > port number."""
> > > > > > > +      try:
> > > > > > > +        return int(value)
> > > > > > > +      except ValueError:
> > > > > > > +        try:
> > > > > > > +          return socket.getservbyname(value)
> > > > > > > +        except socket.error:
> > > > > > > +          raise ValueError("Not a valid port number or service
> > > name:
> > > > > > > '%s'" % value)
> > > > > > >
> > > > > > > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > > -    @ivar user: Username
> > > > > > > -    @ivar password: Password
> > > > > > > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > > -    @ivar port: Integer port.
> > > > > > > -    @ivar host_port: Returns host:port
> > > > > > > +  def __init__(self, url=None, **kwargs):
> > > > > > > +    """
> > > > > > > +    @param url: URL string to parse.
> > > > > > > +    @param kwargs: scheme, user, password, host, port, path.
> > > > > > > +      If specified, replaces corresponding part in url string.
> > > > > > >      """
> > > > > > > +    if url:
> > > > > > > +      self._url = pn_url_parse(str(url))
> > > > > > > +      if not self._url: raise ValueError("Invalid URL '%s'" % url)
> > > > > > > +    else:
> > > > > > > +      self._url = pn_url()
> > > > > > > +    for k in kwargs:            # Let kwargs override values
> > > parsed
> > > > > from
> > > > > > > url
> > > > > > > +      getattr(self, k)          # Check for invalid kwargs
> > > > > > > +      setattr(self, k, kwargs[k])
> > > > > > > +
> > > > > > > +  class PartDescriptor(object):
> > > > > > > +    def __init__(self, part):
> > > > > > > +      self.getter = globals()["pn_url_%s" % part]
> > > > > > > +      self.setter = globals()["pn_url_set_%s" % part]
> > > > > > > +    def __get__(self, obj, type=None): return
> > > self.getter(obj._url)
> > > > > > > +    def __set__(self, obj, value): return self.setter(obj._url,
> > > > > > > str(value))
> > > > > > > +
> > > > > > > +  scheme = PartDescriptor('scheme')
> > > > > > > +  username = PartDescriptor('username')
> > > > > > > +  password = PartDescriptor('password')
> > > > > > > +  host = PartDescriptor('host')
> > > > > > > +  path = PartDescriptor('path')
> > > > > > > +
> > > > > > > +  @property
> > > > > > > +  def port(self):
> > > > > > > +    portstr = pn_url_port(self._url)
> > > > > > > +    return portstr and Url.Port(portstr)
> > > > > > > +
> > > > > > > +  @port.setter
> > > > > > > +  def port(self, value):
> > > > > > > +    if value is None: pn_url_set_port(self._url, None)
> > > > > > > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> > > > > > >
> > > > > > > -    AMQPS = "amqps"
> > > > > > > -    AMQP = "amqp"
> > > > > > > +  def __str__(self): return pn_url_str(self._url)
> > > > > > >
> > > > > > > -    class Port(int):
> > > > > > > -      """An integer port number that can also have an associated
> > > > > service
> > > > > > > name string"""
> > > > > > > +  def __repr__(self): return "Url(%r)" % str(self)
> > > > > > >
> > > > > > > -      def __new__(cls, value):
> > > > > > > -        port = super(Url.Port, cls).__new__(cls,
> > > cls.port_int(value))
> > > > > > > -        setattr(port, 'name', str(value))
> > > > > > > -        return port
> > > > > > > -
> > > > > > > -      def __eq__(self, x): return str(self) == x or int(self) == x
> > > > > > > -      def __ne__(self, x): return not self == x
> > > > > > > -      def __str__(self): return str(self.name)
> > > > > > > -
> > > > > > > -      @staticmethod
> > > > > > > -      def port_int(value):
> > > > > > > -        """Convert service, an integer or a service name, into an
> > > > > integer
> > > > > > > port number."""
> > > > > > > -        try:
> > > > > > > -          return int(value)
> > > > > > > -        except ValueError:
> > > > > > > -          try:
> > > > > > > -            return socket.getservbyname(value)
> > > > > > > -          except socket.error:
> > > > > > > -            raise ValueError("Not a valid port number or service
> > > name:
> > > > > > > '%s'" % value)
> > > > > > > -
> > > > > > > -    def __init__(self, url=None, **kwargs):
> > > > > > > -        """
> > > > > > > -        @param url: String or Url instance to parse or copy.
> > > > > > > -        @param kwargs: URL fields: scheme, user, password, host,
> > > port,
> > > > > > > path.
> > > > > > > -            If specified, replaces corresponding component in url.
> > > > > > > -        """
> > > > > > > -
> > > > > > > -        fields = ['scheme', 'user', 'password', 'host', 'port',
> > > > > 'path']
> > > > > > > -
> > > > > > > -        for f in fields: setattr(self, f, None)
> > > > > > > -        for k in kwargs: getattr(self, k) # Check for invalid
> > > kwargs
> > > > > > > -
> > > > > > > -        if isinstance(url, Url): # Copy from another Url instance.
> > > > > > > -            self.__dict__.update(url.__dict__)
> > > > > > > -        elif url is not None:   # Parse from url
> > > > > > > -            parts = pni_parse_url(str(url))
> > > > > > > -            if not filter(None, parts): raise ValueError("Invalid
> > > AMQP
> > > > > > > URL: '%s'" % url)
> > > > > > > -            self.scheme, self.user, self.password, self.host,
> > > port,
> > > > > > > self.path = parts
> > > > > > > -            if not self.host: self.host = None
> > > > > > > -            self.port = port and self.Port(port)
> > > > > > > -
> > > > > > > -        # Let kwargs override values previously set from url
> > > > > > > -        for field in fields:
> > > > > > > -            setattr(self, field, kwargs.get(field, getattr(self,
> > > > > field)))
> > > > > > > -
> > > > > > > -    def __repr__(self):
> > > > > > > -        return "Url(%r)" % str(self)
> > > > > > > -
> > > > > > > -    def __str__(self):
> > > > > > > -        s = ""
> > > > > > > -        if self.scheme:
> > > > > > > -            s += "%s://" % self.scheme
> > > > > > > -        if self.user:
> > > > > > > -            s += self.user
> > > > > > > -        if self.password:
> > > > > > > -            s += ":%s" % self.password
> > > > > > > -        if self.user or self.password:
> > > > > > > -            s += '@'
> > > > > > > -        if self.host and ':' in self.host:
> > > > > > > -            s += "[%s]" % self.host
> > > > > > > -        elif self.host:
> > > > > > > -            s += self.host
> > > > > > > -        if self.port:
> > > > > > > -            s += ":%s" % self.port
> > > > > > > -        if self.path:
> > > > > > > -            s += "/%s" % self.path
> > > > > > > -        return s
> > > > > > > -
> > > > > > > -    def __eq__(self, url):
> > > > > > > -        return \
> > > > > > > -            self.scheme == url.scheme and \
> > > > > > > -            self.user == url.user and self.password ==
> > > url.password
> > > > > and \
> > > > > > > -            self.host == url.host and self.port == url.port and \
> > > > > > > -            self.path == url.path
> > > > > > > -
> > > > > > > -    def __ne__(self, url):
> > > > > > > -        return not self.__eq__(url)
> > > > > > > -
> > > > > > > -    def defaults(self):
> > > > > > > -        """
> > > > > > > -        Fill in missing values with defaults
> > > > > > > -        @return: self
> > > > > > > -        """
> > > > > > > -        self.scheme = self.scheme or self.AMQP
> > > > > > > -        self.host = self.host or '0.0.0.0'
> > > > > > > -        self.port = self.port or self.Port(self.scheme)
> > > > > > > -        return self
> > > > > > > +  def defaults(self):
> > > > > > > +    """
> > > > > > > +    Fill in missing values (scheme, host or port) with defaults
> > > > > > > +    @return: self
> > > > > > > +    """
> > > > > > > +    self.scheme = self.scheme or self.AMQP
> > > > > > > +    self.host = self.host or '0.0.0.0'
> > > > > > > +    self.port = self.port or self.Port(self.scheme)
> > > > > > > +    return self
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19
> > > 21:00:50
> > > > > > > 2014
> > > > > > > @@ -26,8 +26,8 @@
> > > > > > >  #include <proton/messenger.h>
> > > > > > >  #include <proton/ssl.h>
> > > > > > >  #include <proton/driver_extras.h>
> > > > > > > -
> > > > > > >  #include <proton/types.h>
> > > > > > > +#include <proton/url.h>
> > > > > > >
> > > > > > >  #include <uuid/uuid.h>
> > > > > > >  %}
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/include/proton/cproton.i (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri Sep 19
> > > > > > > 21:00:50 2014
> > > > > > > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> > > > > > >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return
> > > (pn_delivery_t
> > > > > *)
> > > > > > > x; }
> > > > > > >    pn_transport_t *pn_cast_pn_transport(void *x) { return
> > > > > (pn_transport_t
> > > > > > > *) x; }
> > > > > > >  %}
> > > > > > > +
> > > > > > > +%include "proton/url.h"
> > > > > > > +
> > > > > > >
> > > > > > > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > > > > > > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19
> > > 21:00:50
> > > > > > > 2014
> > > > > > > @@ -0,0 +1,83 @@
> > > > > > > +#ifndef PROTON_URL_H
> > > > > > > +#define PROTON_URL_H
> > > > > > > +/*
> > > > > > > + * 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.
> > > > > > > + */
> > > > > > > +
> > > > > > > +#include <proton/import_export.h>
> > > > > > > +
> > > > > > > +/** @file
> > > > > > > + * URL API for parsing URLs.
> > > > > > > + *
> > > > > > > + * @defgroup url URL
> > > > > > > + * @{
> > > > > > > + */
> > > > > > > +
> > > > > > > +/** A parsed URL */
> > > > > > > +typedef struct pn_url_t pn_url_t;
> > > > > > > +
> > > > > > > +/** Create an empty URL */
> > > > > > > +PN_EXTERN pn_url_t *pn_url(void);
> > > > > > > +
> > > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > > + *@param[in] url A URL string.
> > > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> > > > > string.
> > > > > > > + */
> > > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > > > > > > +
> > > > > > > +/** Free a URL */
> > > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > > > > > > +
> > > > > > > +/** Clear the contents of the URL. */
> > > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > > > > > > +
> > > > > > > +/** Return the string form of a URL. Owned by the pn_url_t.*/
> > > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > > > > > > +
> > > > > > > +/**
> > > > > > > + *@name Getters for parts of the URL.
> > > > > > > + *
> > > > > > > + *Values belong to the URL. May return NULL if the value is not
> > > set.
> > > > > > > + *
> > > > > > > + *@{
> > > > > > > + */
> > > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > > > > > > +///@}
> > > > > > > +
> > > > > > > +/**
> > > > > > > + *@name Setters for parts of the URL.
> > > > > > > + *
> > > > > > > + *Values are copied. Value can be NULL to indicate the part is not
> > > > > set.
> > > > > > > + *
> > > > > > > + *@{
> > > > > > > + */
> > > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > > *scheme);
> > > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > > *username);
> > > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > > *password);
> > > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host);
> > > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port);
> > > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path);
> > > > > > > +///@}
> > > > > > > +
> > > > > > > +///@}
> > > > > > > +#endif
> > > > > > >
> > > > > > > Added: qpid/proton/trunk/proton-c/src/url.c
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > > > > > > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50 2014
> > > > > > > @@ -0,0 +1,127 @@
> > > > > > > +/*
> > > > > > > + *
> > > > > > > + * 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.
> > > > > > > + *
> > > > > > > + */
> > > > > > > +
> > > > > > > +#include <proton/url.h>
> > > > > > > +#include <proton/util.h>
> > > > > > > +#include <stdlib.h>
> > > > > > > +#include <string.h>
> > > > > > > +#include <stdio.h>
> > > > > > > +
> > > > > > > +static char* copy(const char* str) {
> > > > > > > +    if (str ==  NULL) return NULL;
> > > > > > > +    char *str2 = (char*)malloc(strlen(str));
> > > > > > > +    if (str2) strcpy(str2, str);
> > > > > > > +    return str2;
> > > > > > > +}
> > > > > > > +
> > > > > > > +struct pn_url_t {
> > > > > > > +    char *scheme;
> > > > > > > +    char *username;
> > > > > > > +    char *password;
> > > > > > > +    char *host;
> > > > > > > +    char *port;
> > > > > > > +    char *path;
> > > > > > > +    char *str;
> > > > > > > +};
> > > > > > > +
> > > > > > > +PN_EXTERN pn_url_t *pn_url() {
> > > > > > > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > > > > > > +    memset(url, 0, sizeof(*url));
> > > > > > > +    return url;
> > > > > > > +}
> > > > > > > +
> > > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > > + *@param[in] url A URL string.
> > > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> > > > > string.
> > > > > > > + */
> > > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > > > > > > +    if (!str || !*str)          /* Empty string or NULL is
> > > illegal. */
> > > > > > > +        return NULL;
> > > > > > > +
> > > > > > > +    pn_url_t *url = pn_url();
> > > > > > > +    char *str2 = copy(str);         /* FIXME aconway 2014-09-19:
> > > > > clean up
> > > > > > > */
> > > > > > > +    pni_parse_url(str2, &url->scheme, &url->username,
> > > &url->password,
> > > > > > > &url->host, &url->port, &url->path);
> > > > > > > +    url->scheme = copy(url->scheme);
> > > > > > > +    url->username = copy(url->username);
> > > > > > > +    url->password = copy(url->password);
> > > > > > > +    url->host = (url->host && !*url->host) ? NULL :
> > > copy(url->host);
> > > > > > > +    url->port = copy(url->port);
> > > > > > > +    url->path = copy(url->path);
> > > > > > > +    return url;
> > > > > > > +}
> > > > > > > +
> > > > > > > +/** Free a URL */
> > > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > > > > > > +    pn_url_clear(url);
> > > > > > > +    free(url);
> > > > > > > +}
> > > > > > > +
> > > > > > > +/** Clear the contents of the URL. */
> > > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > > > > > > +    pn_url_set_username(url, NULL);
> > > > > > > +    pn_url_set_password(url, NULL);
> > > > > > > +    pn_url_set_host(url, NULL);
> > > > > > > +    pn_url_set_port(url, NULL);
> > > > > > > +    pn_url_set_path(url, NULL);
> > > > > > > +    free(url->str); url->str = NULL;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static inline int len(const char *str) { return str ? strlen(str)
> > > :
> > > > > 0; }
> > > > > > > +
> > > > > > > +/** Return the string form of a URL. */
> > > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > > > > > > +    int size = len(url->scheme) + len(url->username) +
> > > > > len(url->password)
> > > > > > > +        + len(url->host) + len(url->port) + len(url->path)
> > > > > > > +        + len("s://u:p@[h]:p/p");
> > > > > > > +    free(url->str);
> > > > > > > +    url->str = (char*)malloc(size);
> > > > > > > +    if (!url->str) return NULL;
> > > > > > > +
> > > > > > > +    int i = 0;
> > > > > > > +    if (url->scheme) i += snprintf(url->str+i, size-i, "%s://",
> > > > > > > url->scheme);
> > > > > > > +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> > > > > > > url->username);
> > > > > > > +    if (url->password) i += snprintf(url->str+i, size-i, ":%s",
> > > > > > > url->password);
> > > > > > > +    if (url->username || url->password) i += snprintf(url->str+i,
> > > > > size-i,
> > > > > > > "@");
> > > > > > > +    if (url->host) {
> > > > > > > +        if (strchr(url->host, ':')) i += snprintf(url->str+i,
> > > size-i,
> > > > > > > "[%s]", url->host);
> > > > > > > +        else i += snprintf(url->str+i, size-i, "%s", url->host);
> > > > > > > +    }
> > > > > > > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
> > > > > url->port);
> > > > > > > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
> > > > > url->path);
> > > > > > > +    return url->str;
> > > > > > > +}
> > > > > > > +
> > > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
> > > > > url->scheme; }
> > > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> > > > > > > url->username; }
> > > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> > > > > > > url->password; }
> > > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return
> > > url->host; }
> > > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return
> > > url->port; }
> > > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return
> > > url->path; }
> > > > > > > +
> > > > > > > +#define SET(part) free(url->part); url->part = copy(part)
> > > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > > *scheme) {
> > > > > > > SET(scheme); }
> > > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > > *username) {
> > > > > > > SET(username); }
> > > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > > *password) {
> > > > > > > SET(password); }
> > > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host) {
> > > > > > > SET(host); }
> > > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port) {
> > > > > > > SET(port); }
> > > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path) {
> > > > > > > SET(path); }
> > > > > > > +
> > > > > > > +
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/tests/python/proton_tests/url.py (original)
> > > > > > > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep 19
> > > > > 21:00:50
> > > > > > > 2014
> > > > > > > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> > > > > > >      def assertNotEqual(self, a, b):
> > > > > > >          assert a != b, "%s == %s" % (a, b)
> > > > > > >
> > > > > > > -    def assertUrl(self, u, scheme, user, password, host, port,
> > > path):
> > > > > > > -        self.assertEqual((u.scheme, u.user, u.password, u.host,
> > > > > u.port,
> > > > > > > u.path),
> > > > > > > -                         (scheme, user, password, host, port,
> > > path))
> > > > > > > +    def assertUrl(self, u, scheme, username, password, host, port,
> > > > > path):
> > > > > > > +        self.assertEqual((u.scheme, u.username, u.password,
> > > u.host,
> > > > > > > u.port, u.path),
> > > > > > > +                         (scheme, username, password, host, port,
> > > > > path))
> > > > > > >
> > > > > > >      def testUrl(self):
> > > > > > >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > > > > > > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> > > > > > >
> > > > > > >      def testDefaults(self):
> > > > > > >          # Check that we allow None for scheme, port
> > > > > > > -        url = Url(user='me', password='secret', host='myhost',
> > > > > > > path='foobar')
> > > > > > > +        url = Url(username='me', password='secret', host='myhost',
> > > > > > > path='foobar')
> > > > > > >          self.assertEqual(str(url), "me:secret@myhost/foobar")
> > > > > > >          self.assertUrl(url, None, 'me', 'secret', 'myhost', None,
> > > > > > > 'foobar')
> > > > > > >
> > > > > > > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> > > > > > >      def testMissing(self):
> > > > > > >          self.assertUrl(Url(), None, None, None, None, None, None)
> > > > > > >          self.assertUrl(Url('amqp://'), 'amqp', None, None, None,
> > > None,
> > > > > > > None)
> > > > > > > -        self.assertUrl(Url('user@'), None, 'user', None, None,
> > > None,
> > > > > > > None)
> > > > > > > +        self.assertUrl(Url('username@'), None, 'username', None,
> > > > > None,
> > > > > > > None, None)
> > > > > > >          self.assertUrl(Url(':pass@'), None, '', 'pass', None,
> > > None,
> > > > > None)
> > > > > > >          self.assertUrl(Url('host'), None, None, None, 'host',
> > > None,
> > > > > None)
> > > > > > >          self.assertUrl(Url(':1234'), None, None, None, None, 1234,
> > > > > None)
> > > > > > >          self.assertUrl(Url('/path'), None, None, None, None, None,
> > > > > 'path')
> > > > > > >
> > > > > > > -        for s in ['amqp://', 'user@', ':pass@', ':1234',
> > > '/path']:
> > > > > > > +        for s in ['amqp://', 'username@', ':pass@', ':1234',
> > > > > '/path']:
> > > > > > >              self.assertEqual(s, str(Url(s)))
> > > > > > >
> > > > > > >          for s, full in [
> > > > > > >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > > > > > > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > > > > > > +                ('username@', 'amqp://username@0.0.0.0:amqp'),
> > > > > > >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> > > > > > >                  (':1234', 'amqp://0.0.0.0:1234'),
> > > > > > >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> > > > > > >              self.assertEqual(str(Url(s).defaults()), full)
> > > > > > > -
> > > > > > > -        self.assertRaises(ValueError, Url, '')
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >
> > > ---------------------------------------------------------------------
> > > > > > > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > > > > > > For additional commands, e-mail: commits-help@qpid.apache.org
> > > > > > >
> > > > > > >
> > > > >
> > > > >
> > > > >
> > > > > ---------------------------------------------------------------------
> > > > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > > > For additional commands, e-mail: dev-help@qpid.apache.org
> > > > >
> > > > >
> > >
> > >
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > For additional commands, e-mail: dev-help@qpid.apache.org
> > >
> > >
> 



Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Alan Conway <ac...@redhat.com>.
Hum, CI is still broken.

https://builds.apache.org/job/Qpid-proton-j/org.apache.qpid
$proton-tests/683/testReport/org.apache.qpid.proton/JythonTest/test/

Somehow my trivial re-org of the URL tests in python has caused the
entire Jython test harness to explode in flight. It works fine on my box
in python and Jython, and it works on CI in regular python - so maybe
another Java 6 issue? Will I lose my mind if I try to install Java 6 on
Fedora and get proton to use it?

On Thu, 2014-09-25 at 13:59 -0400, Alan Conway wrote:
> On Thu, 2014-09-25 at 15:59 +0100, Robbie Gemmell wrote:
> > On 25 September 2014 15:00, Alan Conway <ac...@redhat.com> wrote:
> > 
> > > On Wed, 2014-09-24 at 12:19 +0100, Robbie Gemmell wrote:
> > > > The tests are now running again, but a couple of the URL tests still seem
> > > > to be failing on the CI job:
> > > >
> > > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/
> > > >
> > >
> > > They are all failing with:
> > >  Not a valid port number or service name: 'amqps'
> > >
> > > Could this be a configuration problem on the CI machine, i.e. missing an
> > > 'amqps' entry in /etc/services? Can I get access to the CI machine to
> > > poke around and see what's up?
> > >
> > 
> > Almost certainly no, only the core maintainers are allowed shell access as
> > far as I've seen. You can ask on builds@apache.org for those with access to
> > check things out and report back and see what happens.
> > 
> > I think the CI instances will be running Ubuntu 12.04 or 14.04 LTS. For
> > giggles, I dug out an ooooold Ubuntu VM with Java 6 on it and tried the
> > tests, which failed, and it indeed has no amqp[s] entry in /etc/services
> > file so that could well be it.
> 
> Thanks for checking that out! I have hacked the tests to skip tests for
> 'amqps' if it is not recognized. Poke me if there are still failures.
> 
> ------------------------------------------------------------------------
> r1627577 | aconway | 2014-09-25 13:59:17 -0400 (Thu, 25 Sep 2014) | 5
> lines
> 
> NO-JIRA: Fix URL test to skip 'amqps' tests if 'amqps' is not recognized
> as a service name.
> 
> On some older Ubuntu with Java 6, 'amqps' is not recognized as a service
> name so
> skip those tests in that case.
> 
> ------------------------------------------------------------------------
> 
> > >
> > > The URL code uses socket.getservbyname() to look up service names. Is
> > > there a more portable way to do it?
> > >
> > 
> > No idea I'm afraid.
> > 
> > 
> > >
> > > Cheers,
> > > Alan.
> > >
> > > > As mentioned in my other post about a timeline for dropping Java6
> > > support,
> > > > they seem to work on Java8 (havent tried Java7).
> > > >
> > > > Robbie
> > > >
> > > > On 22 September 2014 21:14, Alan Conway <ac...@redhat.com> wrote:
> > > >
> > > > > My bad, didn't run the java tests. Will fix ASAP and then give myself a
> > > > > flogging.
> > > > >
> > > > > On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> > > > > > This seems to have broken the Java test runs:
> > > > > >
> > > > > > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> > > > > >
> > > > > >
> > > > > >
> > > > > > On 19 September 2014 22:00, <ac...@apache.org> wrote:
> > > > > >
> > > > > > > Author: aconway
> > > > > > > Date: Fri Sep 19 21:00:50 2014
> > > > > > > New Revision: 1626329
> > > > > > >
> > > > > > > URL: http://svn.apache.org/r1626329
> > > > > > > Log:
> > > > > > > PROTON-693: Python Url class to wrap C function pni_parse_url
> > > > > > >
> > > > > > > It was pointed out that pni_parse_url is an internal function and
> > > the
> > > > > > > interface
> > > > > > > is not suitable for public API.
> > > > > > >
> > > > > > > Rewrote the URL parser as a proper swigable C API pn_url_*. This
> > > gets
> > > > > rid
> > > > > > > of the
> > > > > > > need for previous swig insanity and is cleaner all round.
> > > > > > >
> > > > > > > Internally still uses the pni_parse_url parser, we can clean that
> > > up
> > > > > later.
> > > > > > >
> > > > > > > Added:
> > > > > > >     qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > >     qpid/proton/trunk/proton-c/src/url.c
> > > > > > > Modified:
> > > > > > >     qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > >     qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > >     qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19 21:00:50
> > > 2014
> > > > > > > @@ -270,6 +270,7 @@ set (qpid-proton-core
> > > > > > >    src/object/iterator.c
> > > > > > >
> > > > > > >    src/util.c
> > > > > > > +  src/url.c
> > > > > > >    src/error.c
> > > > > > >    src/buffer.c
> > > > > > >    src/parser.c
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19
> > > 21:00:50
> > > > > > > 2014
> > > > > > > @@ -8,6 +8,7 @@
> > > > > > >  #include <proton/messenger.h>
> > > > > > >  #include <proton/ssl.h>
> > > > > > >  #include <proton/driver_extras.h>
> > > > > > > +#include <proton/url.h>
> > > > > > >  %}
> > > > > > >
> > > > > > >  %include <cstring.i>
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19
> > > 21:00:50
> > > > > 2014
> > > > > > > @@ -29,6 +29,7 @@
> > > > > > >  %header %{
> > > > > > >  /* Include the headers needed by the code in this wrapper file */
> > > > > > >  #include <proton/types.h>
> > > > > > > +#include <proton/url.h>
> > > > > > >  #include <proton/message.h>
> > > > > > >  #include <proton/driver.h>
> > > > > > >  #include <proton/driver_extras.h>
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri Sep 19
> > > > > > > 21:00:50 2014
> > > > > > > @@ -23,6 +23,7 @@
> > > > > > >  #include <winsock2.h>
> > > > > > >  #endif
> > > > > > >  #include <proton/engine.h>
> > > > > > > +#include <proton/url.h>
> > > > > > >  #include <proton/message.h>
> > > > > > >  #include <proton/sasl.h>
> > > > > > >  #include <proton/driver.h>
> > > > > > > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> > > > > > >    }
> > > > > > >  %}
> > > > > > >
> > > > > > > -
> > > > > > > -/**
> > > > > > > -   pni_parse_url(char* url, char **scheme, char **user, char
> > > **pass,
> > > > > char
> > > > > > > **host, char **port, char **path)
> > > > > > > -   The following type maps convert this into a python function
> > > that
> > > > > taks
> > > > > > > a URL string argument
> > > > > > > -   and returns a list of strings [scheme, user, pass, host, port,
> > > > > path]
> > > > > > > -   This probably could be done more neatly.
> > > > > > > -*/
> > > > > > > -
> > > > > > > -// Typemap to copy the url string as it will be modified by
> > > parse_url
> > > > > > > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char *url
> > > (int
> > > > > > > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > > > > > > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > > > > > > -  if (!SWIG_IsOK(res)) {
> > > > > > > -    %argument_fail(res, "char *url", $symname, $argnum);
> > > > > > > -  }
> > > > > > > -  $1 = %new_array(n, $*1_ltype);
> > > > > > > -  memcpy($1,t,sizeof(char)*n);
> > > > > > > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > > > > > > -  $1[n-1] = 0;
> > > > > > > -}
> > > > > > > -%typemap(freearg,match="in") char *url "free($1);";
> > > > > > > -%typemap(argout) char *url "";
> > > > > > > -
> > > > > > > -// Typemap for char** return strings. Don't free them.
> > > > > > > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0) "$1 =
> > > > > &temp;";
> > > > > > > -%typemap(freearg,match="in") char **OUTSTR "";
> > > > > > > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char
> > > **OUTSTR {
> > > > > > > -    %append_output(SWIG_FromCharPtr(*$1));
> > > > > > > -}
> > > > > > > -
> > > > > > > -// Typemap to initialize result as empty list
> > > > > > > -%typemap(out) void "$result = PyList_New(0);";
> > > > > > > -
> > > > > > > -
> > > > > > > -%apply char** OUTSTR {char **scheme, char **user, char **pass,
> > > char
> > > > > > > **host, char **port, char **path};
> > > > > > > -void pni_parse_url(char* url, char **scheme, char **user, char
> > > **pass,
> > > > > > > char **host, char **port, char **path);
> > > > > > > -%ignore pni_parse_url;
> > > > > > > -
> > > > > > >  %include "proton/cproton.i"
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri Sep 19
> > > > > > > 21:00:50 2014
> > > > > > > @@ -3657,114 +3657,98 @@ __all__ = [
> > > > > > >
> > > > > > >
> > > > > > >  class Url(object):
> > > > > > > -    """
> > > > > > > -    Simple URL parser/constructor, handles URLs of the form:
> > > > > > > +  """
> > > > > > > +  Simple URL parser/constructor, handles URLs of the form:
> > > > > > >
> > > > > > > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > >
> > > > > > > -    All components can be None if not specifeid in the URL string.
> > > > > > > +  All components can be None if not specifeid in the URL string.
> > > > > > >
> > > > > > > -    The port can be specified as a service name, e.g. 'amqp' in
> > > the
> > > > > > > -    URL string but Url.port always gives the integer value.
> > > > > > > +  The port can be specified as a service name, e.g. 'amqp' in the
> > > > > > > +  URL string but Url.port always gives the integer value.
> > > > > > > +
> > > > > > > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > > +  @ivar user: Username
> > > > > > > +  @ivar password: Password
> > > > > > > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > > +  @ivar port: Integer port.
> > > > > > > +  @ivar host_port: Returns host:port
> > > > > > > +  """
> > > > > > > +
> > > > > > > +  AMQPS = "amqps"
> > > > > > > +  AMQP = "amqp"
> > > > > > > +
> > > > > > > +  class Port(int):
> > > > > > > +    """An integer port number that can be constructed from a
> > > service
> > > > > name
> > > > > > > string"""
> > > > > > > +
> > > > > > > +    def __new__(cls, value):
> > > > > > > +      port = super(Url.Port, cls).__new__(cls,
> > > cls.port_int(value))
> > > > > > > +      setattr(port, 'name', str(value))
> > > > > > > +      return port
> > > > > > > +
> > > > > > > +    def __eq__(self, x): return str(self) == x or int(self) == x
> > > > > > > +    def __ne__(self, x): return not self == x
> > > > > > > +    def __str__(self): return str(self.name)
> > > > > > > +
> > > > > > > +    @staticmethod
> > > > > > > +    def port_int(value):
> > > > > > > +      """Convert service, an integer or a service name, into an
> > > > > integer
> > > > > > > port number."""
> > > > > > > +      try:
> > > > > > > +        return int(value)
> > > > > > > +      except ValueError:
> > > > > > > +        try:
> > > > > > > +          return socket.getservbyname(value)
> > > > > > > +        except socket.error:
> > > > > > > +          raise ValueError("Not a valid port number or service
> > > name:
> > > > > > > '%s'" % value)
> > > > > > >
> > > > > > > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > > -    @ivar user: Username
> > > > > > > -    @ivar password: Password
> > > > > > > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > > -    @ivar port: Integer port.
> > > > > > > -    @ivar host_port: Returns host:port
> > > > > > > +  def __init__(self, url=None, **kwargs):
> > > > > > > +    """
> > > > > > > +    @param url: URL string to parse.
> > > > > > > +    @param kwargs: scheme, user, password, host, port, path.
> > > > > > > +      If specified, replaces corresponding part in url string.
> > > > > > >      """
> > > > > > > +    if url:
> > > > > > > +      self._url = pn_url_parse(str(url))
> > > > > > > +      if not self._url: raise ValueError("Invalid URL '%s'" % url)
> > > > > > > +    else:
> > > > > > > +      self._url = pn_url()
> > > > > > > +    for k in kwargs:            # Let kwargs override values
> > > parsed
> > > > > from
> > > > > > > url
> > > > > > > +      getattr(self, k)          # Check for invalid kwargs
> > > > > > > +      setattr(self, k, kwargs[k])
> > > > > > > +
> > > > > > > +  class PartDescriptor(object):
> > > > > > > +    def __init__(self, part):
> > > > > > > +      self.getter = globals()["pn_url_%s" % part]
> > > > > > > +      self.setter = globals()["pn_url_set_%s" % part]
> > > > > > > +    def __get__(self, obj, type=None): return
> > > self.getter(obj._url)
> > > > > > > +    def __set__(self, obj, value): return self.setter(obj._url,
> > > > > > > str(value))
> > > > > > > +
> > > > > > > +  scheme = PartDescriptor('scheme')
> > > > > > > +  username = PartDescriptor('username')
> > > > > > > +  password = PartDescriptor('password')
> > > > > > > +  host = PartDescriptor('host')
> > > > > > > +  path = PartDescriptor('path')
> > > > > > > +
> > > > > > > +  @property
> > > > > > > +  def port(self):
> > > > > > > +    portstr = pn_url_port(self._url)
> > > > > > > +    return portstr and Url.Port(portstr)
> > > > > > > +
> > > > > > > +  @port.setter
> > > > > > > +  def port(self, value):
> > > > > > > +    if value is None: pn_url_set_port(self._url, None)
> > > > > > > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> > > > > > >
> > > > > > > -    AMQPS = "amqps"
> > > > > > > -    AMQP = "amqp"
> > > > > > > +  def __str__(self): return pn_url_str(self._url)
> > > > > > >
> > > > > > > -    class Port(int):
> > > > > > > -      """An integer port number that can also have an associated
> > > > > service
> > > > > > > name string"""
> > > > > > > +  def __repr__(self): return "Url(%r)" % str(self)
> > > > > > >
> > > > > > > -      def __new__(cls, value):
> > > > > > > -        port = super(Url.Port, cls).__new__(cls,
> > > cls.port_int(value))
> > > > > > > -        setattr(port, 'name', str(value))
> > > > > > > -        return port
> > > > > > > -
> > > > > > > -      def __eq__(self, x): return str(self) == x or int(self) == x
> > > > > > > -      def __ne__(self, x): return not self == x
> > > > > > > -      def __str__(self): return str(self.name)
> > > > > > > -
> > > > > > > -      @staticmethod
> > > > > > > -      def port_int(value):
> > > > > > > -        """Convert service, an integer or a service name, into an
> > > > > integer
> > > > > > > port number."""
> > > > > > > -        try:
> > > > > > > -          return int(value)
> > > > > > > -        except ValueError:
> > > > > > > -          try:
> > > > > > > -            return socket.getservbyname(value)
> > > > > > > -          except socket.error:
> > > > > > > -            raise ValueError("Not a valid port number or service
> > > name:
> > > > > > > '%s'" % value)
> > > > > > > -
> > > > > > > -    def __init__(self, url=None, **kwargs):
> > > > > > > -        """
> > > > > > > -        @param url: String or Url instance to parse or copy.
> > > > > > > -        @param kwargs: URL fields: scheme, user, password, host,
> > > port,
> > > > > > > path.
> > > > > > > -            If specified, replaces corresponding component in url.
> > > > > > > -        """
> > > > > > > -
> > > > > > > -        fields = ['scheme', 'user', 'password', 'host', 'port',
> > > > > 'path']
> > > > > > > -
> > > > > > > -        for f in fields: setattr(self, f, None)
> > > > > > > -        for k in kwargs: getattr(self, k) # Check for invalid
> > > kwargs
> > > > > > > -
> > > > > > > -        if isinstance(url, Url): # Copy from another Url instance.
> > > > > > > -            self.__dict__.update(url.__dict__)
> > > > > > > -        elif url is not None:   # Parse from url
> > > > > > > -            parts = pni_parse_url(str(url))
> > > > > > > -            if not filter(None, parts): raise ValueError("Invalid
> > > AMQP
> > > > > > > URL: '%s'" % url)
> > > > > > > -            self.scheme, self.user, self.password, self.host,
> > > port,
> > > > > > > self.path = parts
> > > > > > > -            if not self.host: self.host = None
> > > > > > > -            self.port = port and self.Port(port)
> > > > > > > -
> > > > > > > -        # Let kwargs override values previously set from url
> > > > > > > -        for field in fields:
> > > > > > > -            setattr(self, field, kwargs.get(field, getattr(self,
> > > > > field)))
> > > > > > > -
> > > > > > > -    def __repr__(self):
> > > > > > > -        return "Url(%r)" % str(self)
> > > > > > > -
> > > > > > > -    def __str__(self):
> > > > > > > -        s = ""
> > > > > > > -        if self.scheme:
> > > > > > > -            s += "%s://" % self.scheme
> > > > > > > -        if self.user:
> > > > > > > -            s += self.user
> > > > > > > -        if self.password:
> > > > > > > -            s += ":%s" % self.password
> > > > > > > -        if self.user or self.password:
> > > > > > > -            s += '@'
> > > > > > > -        if self.host and ':' in self.host:
> > > > > > > -            s += "[%s]" % self.host
> > > > > > > -        elif self.host:
> > > > > > > -            s += self.host
> > > > > > > -        if self.port:
> > > > > > > -            s += ":%s" % self.port
> > > > > > > -        if self.path:
> > > > > > > -            s += "/%s" % self.path
> > > > > > > -        return s
> > > > > > > -
> > > > > > > -    def __eq__(self, url):
> > > > > > > -        return \
> > > > > > > -            self.scheme == url.scheme and \
> > > > > > > -            self.user == url.user and self.password ==
> > > url.password
> > > > > and \
> > > > > > > -            self.host == url.host and self.port == url.port and \
> > > > > > > -            self.path == url.path
> > > > > > > -
> > > > > > > -    def __ne__(self, url):
> > > > > > > -        return not self.__eq__(url)
> > > > > > > -
> > > > > > > -    def defaults(self):
> > > > > > > -        """
> > > > > > > -        Fill in missing values with defaults
> > > > > > > -        @return: self
> > > > > > > -        """
> > > > > > > -        self.scheme = self.scheme or self.AMQP
> > > > > > > -        self.host = self.host or '0.0.0.0'
> > > > > > > -        self.port = self.port or self.Port(self.scheme)
> > > > > > > -        return self
> > > > > > > +  def defaults(self):
> > > > > > > +    """
> > > > > > > +    Fill in missing values (scheme, host or port) with defaults
> > > > > > > +    @return: self
> > > > > > > +    """
> > > > > > > +    self.scheme = self.scheme or self.AMQP
> > > > > > > +    self.host = self.host or '0.0.0.0'
> > > > > > > +    self.port = self.port or self.Port(self.scheme)
> > > > > > > +    return self
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19
> > > 21:00:50
> > > > > > > 2014
> > > > > > > @@ -26,8 +26,8 @@
> > > > > > >  #include <proton/messenger.h>
> > > > > > >  #include <proton/ssl.h>
> > > > > > >  #include <proton/driver_extras.h>
> > > > > > > -
> > > > > > >  #include <proton/types.h>
> > > > > > > +#include <proton/url.h>
> > > > > > >
> > > > > > >  #include <uuid/uuid.h>
> > > > > > >  %}
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/include/proton/cproton.i (original)
> > > > > > > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri Sep 19
> > > > > > > 21:00:50 2014
> > > > > > > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> > > > > > >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return
> > > (pn_delivery_t
> > > > > *)
> > > > > > > x; }
> > > > > > >    pn_transport_t *pn_cast_pn_transport(void *x) { return
> > > > > (pn_transport_t
> > > > > > > *) x; }
> > > > > > >  %}
> > > > > > > +
> > > > > > > +%include "proton/url.h"
> > > > > > > +
> > > > > > >
> > > > > > > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > > > > > > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19
> > > 21:00:50
> > > > > > > 2014
> > > > > > > @@ -0,0 +1,83 @@
> > > > > > > +#ifndef PROTON_URL_H
> > > > > > > +#define PROTON_URL_H
> > > > > > > +/*
> > > > > > > + * 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.
> > > > > > > + */
> > > > > > > +
> > > > > > > +#include <proton/import_export.h>
> > > > > > > +
> > > > > > > +/** @file
> > > > > > > + * URL API for parsing URLs.
> > > > > > > + *
> > > > > > > + * @defgroup url URL
> > > > > > > + * @{
> > > > > > > + */
> > > > > > > +
> > > > > > > +/** A parsed URL */
> > > > > > > +typedef struct pn_url_t pn_url_t;
> > > > > > > +
> > > > > > > +/** Create an empty URL */
> > > > > > > +PN_EXTERN pn_url_t *pn_url(void);
> > > > > > > +
> > > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > > + *@param[in] url A URL string.
> > > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> > > > > string.
> > > > > > > + */
> > > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > > > > > > +
> > > > > > > +/** Free a URL */
> > > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > > > > > > +
> > > > > > > +/** Clear the contents of the URL. */
> > > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > > > > > > +
> > > > > > > +/** Return the string form of a URL. Owned by the pn_url_t.*/
> > > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > > > > > > +
> > > > > > > +/**
> > > > > > > + *@name Getters for parts of the URL.
> > > > > > > + *
> > > > > > > + *Values belong to the URL. May return NULL if the value is not
> > > set.
> > > > > > > + *
> > > > > > > + *@{
> > > > > > > + */
> > > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > > > > > > +///@}
> > > > > > > +
> > > > > > > +/**
> > > > > > > + *@name Setters for parts of the URL.
> > > > > > > + *
> > > > > > > + *Values are copied. Value can be NULL to indicate the part is not
> > > > > set.
> > > > > > > + *
> > > > > > > + *@{
> > > > > > > + */
> > > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > > *scheme);
> > > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > > *username);
> > > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > > *password);
> > > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host);
> > > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port);
> > > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path);
> > > > > > > +///@}
> > > > > > > +
> > > > > > > +///@}
> > > > > > > +#endif
> > > > > > >
> > > > > > > Added: qpid/proton/trunk/proton-c/src/url.c
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > > > > > > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50 2014
> > > > > > > @@ -0,0 +1,127 @@
> > > > > > > +/*
> > > > > > > + *
> > > > > > > + * 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.
> > > > > > > + *
> > > > > > > + */
> > > > > > > +
> > > > > > > +#include <proton/url.h>
> > > > > > > +#include <proton/util.h>
> > > > > > > +#include <stdlib.h>
> > > > > > > +#include <string.h>
> > > > > > > +#include <stdio.h>
> > > > > > > +
> > > > > > > +static char* copy(const char* str) {
> > > > > > > +    if (str ==  NULL) return NULL;
> > > > > > > +    char *str2 = (char*)malloc(strlen(str));
> > > > > > > +    if (str2) strcpy(str2, str);
> > > > > > > +    return str2;
> > > > > > > +}
> > > > > > > +
> > > > > > > +struct pn_url_t {
> > > > > > > +    char *scheme;
> > > > > > > +    char *username;
> > > > > > > +    char *password;
> > > > > > > +    char *host;
> > > > > > > +    char *port;
> > > > > > > +    char *path;
> > > > > > > +    char *str;
> > > > > > > +};
> > > > > > > +
> > > > > > > +PN_EXTERN pn_url_t *pn_url() {
> > > > > > > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > > > > > > +    memset(url, 0, sizeof(*url));
> > > > > > > +    return url;
> > > > > > > +}
> > > > > > > +
> > > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > > + *@param[in] url A URL string.
> > > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> > > > > string.
> > > > > > > + */
> > > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > > > > > > +    if (!str || !*str)          /* Empty string or NULL is
> > > illegal. */
> > > > > > > +        return NULL;
> > > > > > > +
> > > > > > > +    pn_url_t *url = pn_url();
> > > > > > > +    char *str2 = copy(str);         /* FIXME aconway 2014-09-19:
> > > > > clean up
> > > > > > > */
> > > > > > > +    pni_parse_url(str2, &url->scheme, &url->username,
> > > &url->password,
> > > > > > > &url->host, &url->port, &url->path);
> > > > > > > +    url->scheme = copy(url->scheme);
> > > > > > > +    url->username = copy(url->username);
> > > > > > > +    url->password = copy(url->password);
> > > > > > > +    url->host = (url->host && !*url->host) ? NULL :
> > > copy(url->host);
> > > > > > > +    url->port = copy(url->port);
> > > > > > > +    url->path = copy(url->path);
> > > > > > > +    return url;
> > > > > > > +}
> > > > > > > +
> > > > > > > +/** Free a URL */
> > > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > > > > > > +    pn_url_clear(url);
> > > > > > > +    free(url);
> > > > > > > +}
> > > > > > > +
> > > > > > > +/** Clear the contents of the URL. */
> > > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > > > > > > +    pn_url_set_username(url, NULL);
> > > > > > > +    pn_url_set_password(url, NULL);
> > > > > > > +    pn_url_set_host(url, NULL);
> > > > > > > +    pn_url_set_port(url, NULL);
> > > > > > > +    pn_url_set_path(url, NULL);
> > > > > > > +    free(url->str); url->str = NULL;
> > > > > > > +}
> > > > > > > +
> > > > > > > +static inline int len(const char *str) { return str ? strlen(str)
> > > :
> > > > > 0; }
> > > > > > > +
> > > > > > > +/** Return the string form of a URL. */
> > > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > > > > > > +    int size = len(url->scheme) + len(url->username) +
> > > > > len(url->password)
> > > > > > > +        + len(url->host) + len(url->port) + len(url->path)
> > > > > > > +        + len("s://u:p@[h]:p/p");
> > > > > > > +    free(url->str);
> > > > > > > +    url->str = (char*)malloc(size);
> > > > > > > +    if (!url->str) return NULL;
> > > > > > > +
> > > > > > > +    int i = 0;
> > > > > > > +    if (url->scheme) i += snprintf(url->str+i, size-i, "%s://",
> > > > > > > url->scheme);
> > > > > > > +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> > > > > > > url->username);
> > > > > > > +    if (url->password) i += snprintf(url->str+i, size-i, ":%s",
> > > > > > > url->password);
> > > > > > > +    if (url->username || url->password) i += snprintf(url->str+i,
> > > > > size-i,
> > > > > > > "@");
> > > > > > > +    if (url->host) {
> > > > > > > +        if (strchr(url->host, ':')) i += snprintf(url->str+i,
> > > size-i,
> > > > > > > "[%s]", url->host);
> > > > > > > +        else i += snprintf(url->str+i, size-i, "%s", url->host);
> > > > > > > +    }
> > > > > > > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
> > > > > url->port);
> > > > > > > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
> > > > > url->path);
> > > > > > > +    return url->str;
> > > > > > > +}
> > > > > > > +
> > > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
> > > > > url->scheme; }
> > > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> > > > > > > url->username; }
> > > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> > > > > > > url->password; }
> > > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return
> > > url->host; }
> > > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return
> > > url->port; }
> > > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return
> > > url->path; }
> > > > > > > +
> > > > > > > +#define SET(part) free(url->part); url->part = copy(part)
> > > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > > *scheme) {
> > > > > > > SET(scheme); }
> > > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > > *username) {
> > > > > > > SET(username); }
> > > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > > *password) {
> > > > > > > SET(password); }
> > > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host) {
> > > > > > > SET(host); }
> > > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port) {
> > > > > > > SET(port); }
> > > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path) {
> > > > > > > SET(path); }
> > > > > > > +
> > > > > > > +
> > > > > > >
> > > > > > > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > > URL:
> > > > > > >
> > > > >
> > > http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > > >
> > > > > > >
> > > > >
> > > ==============================================================================
> > > > > > > --- qpid/proton/trunk/tests/python/proton_tests/url.py (original)
> > > > > > > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep 19
> > > > > 21:00:50
> > > > > > > 2014
> > > > > > > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> > > > > > >      def assertNotEqual(self, a, b):
> > > > > > >          assert a != b, "%s == %s" % (a, b)
> > > > > > >
> > > > > > > -    def assertUrl(self, u, scheme, user, password, host, port,
> > > path):
> > > > > > > -        self.assertEqual((u.scheme, u.user, u.password, u.host,
> > > > > u.port,
> > > > > > > u.path),
> > > > > > > -                         (scheme, user, password, host, port,
> > > path))
> > > > > > > +    def assertUrl(self, u, scheme, username, password, host, port,
> > > > > path):
> > > > > > > +        self.assertEqual((u.scheme, u.username, u.password,
> > > u.host,
> > > > > > > u.port, u.path),
> > > > > > > +                         (scheme, username, password, host, port,
> > > > > path))
> > > > > > >
> > > > > > >      def testUrl(self):
> > > > > > >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > > > > > > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> > > > > > >
> > > > > > >      def testDefaults(self):
> > > > > > >          # Check that we allow None for scheme, port
> > > > > > > -        url = Url(user='me', password='secret', host='myhost',
> > > > > > > path='foobar')
> > > > > > > +        url = Url(username='me', password='secret', host='myhost',
> > > > > > > path='foobar')
> > > > > > >          self.assertEqual(str(url), "me:secret@myhost/foobar")
> > > > > > >          self.assertUrl(url, None, 'me', 'secret', 'myhost', None,
> > > > > > > 'foobar')
> > > > > > >
> > > > > > > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> > > > > > >      def testMissing(self):
> > > > > > >          self.assertUrl(Url(), None, None, None, None, None, None)
> > > > > > >          self.assertUrl(Url('amqp://'), 'amqp', None, None, None,
> > > None,
> > > > > > > None)
> > > > > > > -        self.assertUrl(Url('user@'), None, 'user', None, None,
> > > None,
> > > > > > > None)
> > > > > > > +        self.assertUrl(Url('username@'), None, 'username', None,
> > > > > None,
> > > > > > > None, None)
> > > > > > >          self.assertUrl(Url(':pass@'), None, '', 'pass', None,
> > > None,
> > > > > None)
> > > > > > >          self.assertUrl(Url('host'), None, None, None, 'host',
> > > None,
> > > > > None)
> > > > > > >          self.assertUrl(Url(':1234'), None, None, None, None, 1234,
> > > > > None)
> > > > > > >          self.assertUrl(Url('/path'), None, None, None, None, None,
> > > > > 'path')
> > > > > > >
> > > > > > > -        for s in ['amqp://', 'user@', ':pass@', ':1234',
> > > '/path']:
> > > > > > > +        for s in ['amqp://', 'username@', ':pass@', ':1234',
> > > > > '/path']:
> > > > > > >              self.assertEqual(s, str(Url(s)))
> > > > > > >
> > > > > > >          for s, full in [
> > > > > > >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > > > > > > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > > > > > > +                ('username@', 'amqp://username@0.0.0.0:amqp'),
> > > > > > >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> > > > > > >                  (':1234', 'amqp://0.0.0.0:1234'),
> > > > > > >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> > > > > > >              self.assertEqual(str(Url(s).defaults()), full)
> > > > > > > -
> > > > > > > -        self.assertRaises(ValueError, Url, '')
> > > > > > >
> > > > > > >
> > > > > > >
> > > > > > >
> > > ---------------------------------------------------------------------
> > > > > > > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > > > > > > For additional commands, e-mail: commits-help@qpid.apache.org
> > > > > > >
> > > > > > >
> > > > >
> > > > >
> > > > >
> > > > > ---------------------------------------------------------------------
> > > > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > > > For additional commands, e-mail: dev-help@qpid.apache.org
> > > > >
> > > > >
> > >
> > >
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > For additional commands, e-mail: dev-help@qpid.apache.org
> > >
> > >
> 



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
For additional commands, e-mail: dev-help@qpid.apache.org


Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Alan Conway <ac...@redhat.com>.
On Thu, 2014-09-25 at 15:59 +0100, Robbie Gemmell wrote:
> On 25 September 2014 15:00, Alan Conway <ac...@redhat.com> wrote:
> 
> > On Wed, 2014-09-24 at 12:19 +0100, Robbie Gemmell wrote:
> > > The tests are now running again, but a couple of the URL tests still seem
> > > to be failing on the CI job:
> > >
> > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/
> > >
> >
> > They are all failing with:
> >  Not a valid port number or service name: 'amqps'
> >
> > Could this be a configuration problem on the CI machine, i.e. missing an
> > 'amqps' entry in /etc/services? Can I get access to the CI machine to
> > poke around and see what's up?
> >
> 
> Almost certainly no, only the core maintainers are allowed shell access as
> far as I've seen. You can ask on builds@apache.org for those with access to
> check things out and report back and see what happens.
> 
> I think the CI instances will be running Ubuntu 12.04 or 14.04 LTS. For
> giggles, I dug out an ooooold Ubuntu VM with Java 6 on it and tried the
> tests, which failed, and it indeed has no amqp[s] entry in /etc/services
> file so that could well be it.

Thanks for checking that out! I have hacked the tests to skip tests for
'amqps' if it is not recognized. Poke me if there are still failures.

------------------------------------------------------------------------
r1627577 | aconway | 2014-09-25 13:59:17 -0400 (Thu, 25 Sep 2014) | 5
lines

NO-JIRA: Fix URL test to skip 'amqps' tests if 'amqps' is not recognized
as a service name.

On some older Ubuntu with Java 6, 'amqps' is not recognized as a service
name so
skip those tests in that case.

------------------------------------------------------------------------

> >
> > The URL code uses socket.getservbyname() to look up service names. Is
> > there a more portable way to do it?
> >
> 
> No idea I'm afraid.
> 
> 
> >
> > Cheers,
> > Alan.
> >
> > > As mentioned in my other post about a timeline for dropping Java6
> > support,
> > > they seem to work on Java8 (havent tried Java7).
> > >
> > > Robbie
> > >
> > > On 22 September 2014 21:14, Alan Conway <ac...@redhat.com> wrote:
> > >
> > > > My bad, didn't run the java tests. Will fix ASAP and then give myself a
> > > > flogging.
> > > >
> > > > On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> > > > > This seems to have broken the Java test runs:
> > > > >
> > > > > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> > > > >
> > > > >
> > > > >
> > > > > On 19 September 2014 22:00, <ac...@apache.org> wrote:
> > > > >
> > > > > > Author: aconway
> > > > > > Date: Fri Sep 19 21:00:50 2014
> > > > > > New Revision: 1626329
> > > > > >
> > > > > > URL: http://svn.apache.org/r1626329
> > > > > > Log:
> > > > > > PROTON-693: Python Url class to wrap C function pni_parse_url
> > > > > >
> > > > > > It was pointed out that pni_parse_url is an internal function and
> > the
> > > > > > interface
> > > > > > is not suitable for public API.
> > > > > >
> > > > > > Rewrote the URL parser as a proper swigable C API pn_url_*. This
> > gets
> > > > rid
> > > > > > of the
> > > > > > need for previous swig insanity and is cleaner all round.
> > > > > >
> > > > > > Internally still uses the pni_parse_url parser, we can clean that
> > up
> > > > later.
> > > > > >
> > > > > > Added:
> > > > > >     qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > >     qpid/proton/trunk/proton-c/src/url.c
> > > > > > Modified:
> > > > > >     qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > >     qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > >     qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > >
> > > > > > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > > > > > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19 21:00:50
> > 2014
> > > > > > @@ -270,6 +270,7 @@ set (qpid-proton-core
> > > > > >    src/object/iterator.c
> > > > > >
> > > > > >    src/util.c
> > > > > > +  src/url.c
> > > > > >    src/error.c
> > > > > >    src/buffer.c
> > > > > >    src/parser.c
> > > > > >
> > > > > > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> > > > > > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19
> > 21:00:50
> > > > > > 2014
> > > > > > @@ -8,6 +8,7 @@
> > > > > >  #include <proton/messenger.h>
> > > > > >  #include <proton/ssl.h>
> > > > > >  #include <proton/driver_extras.h>
> > > > > > +#include <proton/url.h>
> > > > > >  %}
> > > > > >
> > > > > >  %include <cstring.i>
> > > > > >
> > > > > > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > > > > > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19
> > 21:00:50
> > > > 2014
> > > > > > @@ -29,6 +29,7 @@
> > > > > >  %header %{
> > > > > >  /* Include the headers needed by the code in this wrapper file */
> > > > > >  #include <proton/types.h>
> > > > > > +#include <proton/url.h>
> > > > > >  #include <proton/message.h>
> > > > > >  #include <proton/driver.h>
> > > > > >  #include <proton/driver_extras.h>
> > > > > >
> > > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i (original)
> > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri Sep 19
> > > > > > 21:00:50 2014
> > > > > > @@ -23,6 +23,7 @@
> > > > > >  #include <winsock2.h>
> > > > > >  #endif
> > > > > >  #include <proton/engine.h>
> > > > > > +#include <proton/url.h>
> > > > > >  #include <proton/message.h>
> > > > > >  #include <proton/sasl.h>
> > > > > >  #include <proton/driver.h>
> > > > > > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> > > > > >    }
> > > > > >  %}
> > > > > >
> > > > > > -
> > > > > > -/**
> > > > > > -   pni_parse_url(char* url, char **scheme, char **user, char
> > **pass,
> > > > char
> > > > > > **host, char **port, char **path)
> > > > > > -   The following type maps convert this into a python function
> > that
> > > > taks
> > > > > > a URL string argument
> > > > > > -   and returns a list of strings [scheme, user, pass, host, port,
> > > > path]
> > > > > > -   This probably could be done more neatly.
> > > > > > -*/
> > > > > > -
> > > > > > -// Typemap to copy the url string as it will be modified by
> > parse_url
> > > > > > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char *url
> > (int
> > > > > > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > > > > > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > > > > > -  if (!SWIG_IsOK(res)) {
> > > > > > -    %argument_fail(res, "char *url", $symname, $argnum);
> > > > > > -  }
> > > > > > -  $1 = %new_array(n, $*1_ltype);
> > > > > > -  memcpy($1,t,sizeof(char)*n);
> > > > > > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > > > > > -  $1[n-1] = 0;
> > > > > > -}
> > > > > > -%typemap(freearg,match="in") char *url "free($1);";
> > > > > > -%typemap(argout) char *url "";
> > > > > > -
> > > > > > -// Typemap for char** return strings. Don't free them.
> > > > > > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0) "$1 =
> > > > &temp;";
> > > > > > -%typemap(freearg,match="in") char **OUTSTR "";
> > > > > > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char
> > **OUTSTR {
> > > > > > -    %append_output(SWIG_FromCharPtr(*$1));
> > > > > > -}
> > > > > > -
> > > > > > -// Typemap to initialize result as empty list
> > > > > > -%typemap(out) void "$result = PyList_New(0);";
> > > > > > -
> > > > > > -
> > > > > > -%apply char** OUTSTR {char **scheme, char **user, char **pass,
> > char
> > > > > > **host, char **port, char **path};
> > > > > > -void pni_parse_url(char* url, char **scheme, char **user, char
> > **pass,
> > > > > > char **host, char **port, char **path);
> > > > > > -%ignore pni_parse_url;
> > > > > > -
> > > > > >  %include "proton/cproton.i"
> > > > > >
> > > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
> > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri Sep 19
> > > > > > 21:00:50 2014
> > > > > > @@ -3657,114 +3657,98 @@ __all__ = [
> > > > > >
> > > > > >
> > > > > >  class Url(object):
> > > > > > -    """
> > > > > > -    Simple URL parser/constructor, handles URLs of the form:
> > > > > > +  """
> > > > > > +  Simple URL parser/constructor, handles URLs of the form:
> > > > > >
> > > > > > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > >
> > > > > > -    All components can be None if not specifeid in the URL string.
> > > > > > +  All components can be None if not specifeid in the URL string.
> > > > > >
> > > > > > -    The port can be specified as a service name, e.g. 'amqp' in
> > the
> > > > > > -    URL string but Url.port always gives the integer value.
> > > > > > +  The port can be specified as a service name, e.g. 'amqp' in the
> > > > > > +  URL string but Url.port always gives the integer value.
> > > > > > +
> > > > > > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > +  @ivar user: Username
> > > > > > +  @ivar password: Password
> > > > > > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > +  @ivar port: Integer port.
> > > > > > +  @ivar host_port: Returns host:port
> > > > > > +  """
> > > > > > +
> > > > > > +  AMQPS = "amqps"
> > > > > > +  AMQP = "amqp"
> > > > > > +
> > > > > > +  class Port(int):
> > > > > > +    """An integer port number that can be constructed from a
> > service
> > > > name
> > > > > > string"""
> > > > > > +
> > > > > > +    def __new__(cls, value):
> > > > > > +      port = super(Url.Port, cls).__new__(cls,
> > cls.port_int(value))
> > > > > > +      setattr(port, 'name', str(value))
> > > > > > +      return port
> > > > > > +
> > > > > > +    def __eq__(self, x): return str(self) == x or int(self) == x
> > > > > > +    def __ne__(self, x): return not self == x
> > > > > > +    def __str__(self): return str(self.name)
> > > > > > +
> > > > > > +    @staticmethod
> > > > > > +    def port_int(value):
> > > > > > +      """Convert service, an integer or a service name, into an
> > > > integer
> > > > > > port number."""
> > > > > > +      try:
> > > > > > +        return int(value)
> > > > > > +      except ValueError:
> > > > > > +        try:
> > > > > > +          return socket.getservbyname(value)
> > > > > > +        except socket.error:
> > > > > > +          raise ValueError("Not a valid port number or service
> > name:
> > > > > > '%s'" % value)
> > > > > >
> > > > > > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > -    @ivar user: Username
> > > > > > -    @ivar password: Password
> > > > > > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > -    @ivar port: Integer port.
> > > > > > -    @ivar host_port: Returns host:port
> > > > > > +  def __init__(self, url=None, **kwargs):
> > > > > > +    """
> > > > > > +    @param url: URL string to parse.
> > > > > > +    @param kwargs: scheme, user, password, host, port, path.
> > > > > > +      If specified, replaces corresponding part in url string.
> > > > > >      """
> > > > > > +    if url:
> > > > > > +      self._url = pn_url_parse(str(url))
> > > > > > +      if not self._url: raise ValueError("Invalid URL '%s'" % url)
> > > > > > +    else:
> > > > > > +      self._url = pn_url()
> > > > > > +    for k in kwargs:            # Let kwargs override values
> > parsed
> > > > from
> > > > > > url
> > > > > > +      getattr(self, k)          # Check for invalid kwargs
> > > > > > +      setattr(self, k, kwargs[k])
> > > > > > +
> > > > > > +  class PartDescriptor(object):
> > > > > > +    def __init__(self, part):
> > > > > > +      self.getter = globals()["pn_url_%s" % part]
> > > > > > +      self.setter = globals()["pn_url_set_%s" % part]
> > > > > > +    def __get__(self, obj, type=None): return
> > self.getter(obj._url)
> > > > > > +    def __set__(self, obj, value): return self.setter(obj._url,
> > > > > > str(value))
> > > > > > +
> > > > > > +  scheme = PartDescriptor('scheme')
> > > > > > +  username = PartDescriptor('username')
> > > > > > +  password = PartDescriptor('password')
> > > > > > +  host = PartDescriptor('host')
> > > > > > +  path = PartDescriptor('path')
> > > > > > +
> > > > > > +  @property
> > > > > > +  def port(self):
> > > > > > +    portstr = pn_url_port(self._url)
> > > > > > +    return portstr and Url.Port(portstr)
> > > > > > +
> > > > > > +  @port.setter
> > > > > > +  def port(self, value):
> > > > > > +    if value is None: pn_url_set_port(self._url, None)
> > > > > > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> > > > > >
> > > > > > -    AMQPS = "amqps"
> > > > > > -    AMQP = "amqp"
> > > > > > +  def __str__(self): return pn_url_str(self._url)
> > > > > >
> > > > > > -    class Port(int):
> > > > > > -      """An integer port number that can also have an associated
> > > > service
> > > > > > name string"""
> > > > > > +  def __repr__(self): return "Url(%r)" % str(self)
> > > > > >
> > > > > > -      def __new__(cls, value):
> > > > > > -        port = super(Url.Port, cls).__new__(cls,
> > cls.port_int(value))
> > > > > > -        setattr(port, 'name', str(value))
> > > > > > -        return port
> > > > > > -
> > > > > > -      def __eq__(self, x): return str(self) == x or int(self) == x
> > > > > > -      def __ne__(self, x): return not self == x
> > > > > > -      def __str__(self): return str(self.name)
> > > > > > -
> > > > > > -      @staticmethod
> > > > > > -      def port_int(value):
> > > > > > -        """Convert service, an integer or a service name, into an
> > > > integer
> > > > > > port number."""
> > > > > > -        try:
> > > > > > -          return int(value)
> > > > > > -        except ValueError:
> > > > > > -          try:
> > > > > > -            return socket.getservbyname(value)
> > > > > > -          except socket.error:
> > > > > > -            raise ValueError("Not a valid port number or service
> > name:
> > > > > > '%s'" % value)
> > > > > > -
> > > > > > -    def __init__(self, url=None, **kwargs):
> > > > > > -        """
> > > > > > -        @param url: String or Url instance to parse or copy.
> > > > > > -        @param kwargs: URL fields: scheme, user, password, host,
> > port,
> > > > > > path.
> > > > > > -            If specified, replaces corresponding component in url.
> > > > > > -        """
> > > > > > -
> > > > > > -        fields = ['scheme', 'user', 'password', 'host', 'port',
> > > > 'path']
> > > > > > -
> > > > > > -        for f in fields: setattr(self, f, None)
> > > > > > -        for k in kwargs: getattr(self, k) # Check for invalid
> > kwargs
> > > > > > -
> > > > > > -        if isinstance(url, Url): # Copy from another Url instance.
> > > > > > -            self.__dict__.update(url.__dict__)
> > > > > > -        elif url is not None:   # Parse from url
> > > > > > -            parts = pni_parse_url(str(url))
> > > > > > -            if not filter(None, parts): raise ValueError("Invalid
> > AMQP
> > > > > > URL: '%s'" % url)
> > > > > > -            self.scheme, self.user, self.password, self.host,
> > port,
> > > > > > self.path = parts
> > > > > > -            if not self.host: self.host = None
> > > > > > -            self.port = port and self.Port(port)
> > > > > > -
> > > > > > -        # Let kwargs override values previously set from url
> > > > > > -        for field in fields:
> > > > > > -            setattr(self, field, kwargs.get(field, getattr(self,
> > > > field)))
> > > > > > -
> > > > > > -    def __repr__(self):
> > > > > > -        return "Url(%r)" % str(self)
> > > > > > -
> > > > > > -    def __str__(self):
> > > > > > -        s = ""
> > > > > > -        if self.scheme:
> > > > > > -            s += "%s://" % self.scheme
> > > > > > -        if self.user:
> > > > > > -            s += self.user
> > > > > > -        if self.password:
> > > > > > -            s += ":%s" % self.password
> > > > > > -        if self.user or self.password:
> > > > > > -            s += '@'
> > > > > > -        if self.host and ':' in self.host:
> > > > > > -            s += "[%s]" % self.host
> > > > > > -        elif self.host:
> > > > > > -            s += self.host
> > > > > > -        if self.port:
> > > > > > -            s += ":%s" % self.port
> > > > > > -        if self.path:
> > > > > > -            s += "/%s" % self.path
> > > > > > -        return s
> > > > > > -
> > > > > > -    def __eq__(self, url):
> > > > > > -        return \
> > > > > > -            self.scheme == url.scheme and \
> > > > > > -            self.user == url.user and self.password ==
> > url.password
> > > > and \
> > > > > > -            self.host == url.host and self.port == url.port and \
> > > > > > -            self.path == url.path
> > > > > > -
> > > > > > -    def __ne__(self, url):
> > > > > > -        return not self.__eq__(url)
> > > > > > -
> > > > > > -    def defaults(self):
> > > > > > -        """
> > > > > > -        Fill in missing values with defaults
> > > > > > -        @return: self
> > > > > > -        """
> > > > > > -        self.scheme = self.scheme or self.AMQP
> > > > > > -        self.host = self.host or '0.0.0.0'
> > > > > > -        self.port = self.port or self.Port(self.scheme)
> > > > > > -        return self
> > > > > > +  def defaults(self):
> > > > > > +    """
> > > > > > +    Fill in missing values (scheme, host or port) with defaults
> > > > > > +    @return: self
> > > > > > +    """
> > > > > > +    self.scheme = self.scheme or self.AMQP
> > > > > > +    self.host = self.host or '0.0.0.0'
> > > > > > +    self.port = self.port or self.Port(self.scheme)
> > > > > > +    return self
> > > > > >
> > > > > > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> > > > > > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19
> > 21:00:50
> > > > > > 2014
> > > > > > @@ -26,8 +26,8 @@
> > > > > >  #include <proton/messenger.h>
> > > > > >  #include <proton/ssl.h>
> > > > > >  #include <proton/driver_extras.h>
> > > > > > -
> > > > > >  #include <proton/types.h>
> > > > > > +#include <proton/url.h>
> > > > > >
> > > > > >  #include <uuid/uuid.h>
> > > > > >  %}
> > > > > >
> > > > > > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/include/proton/cproton.i (original)
> > > > > > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri Sep 19
> > > > > > 21:00:50 2014
> > > > > > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> > > > > >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return
> > (pn_delivery_t
> > > > *)
> > > > > > x; }
> > > > > >    pn_transport_t *pn_cast_pn_transport(void *x) { return
> > > > (pn_transport_t
> > > > > > *) x; }
> > > > > >  %}
> > > > > > +
> > > > > > +%include "proton/url.h"
> > > > > > +
> > > > > >
> > > > > > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > > > > > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19
> > 21:00:50
> > > > > > 2014
> > > > > > @@ -0,0 +1,83 @@
> > > > > > +#ifndef PROTON_URL_H
> > > > > > +#define PROTON_URL_H
> > > > > > +/*
> > > > > > + * 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.
> > > > > > + */
> > > > > > +
> > > > > > +#include <proton/import_export.h>
> > > > > > +
> > > > > > +/** @file
> > > > > > + * URL API for parsing URLs.
> > > > > > + *
> > > > > > + * @defgroup url URL
> > > > > > + * @{
> > > > > > + */
> > > > > > +
> > > > > > +/** A parsed URL */
> > > > > > +typedef struct pn_url_t pn_url_t;
> > > > > > +
> > > > > > +/** Create an empty URL */
> > > > > > +PN_EXTERN pn_url_t *pn_url(void);
> > > > > > +
> > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > + *@param[in] url A URL string.
> > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> > > > string.
> > > > > > + */
> > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > > > > > +
> > > > > > +/** Free a URL */
> > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > > > > > +
> > > > > > +/** Clear the contents of the URL. */
> > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > > > > > +
> > > > > > +/** Return the string form of a URL. Owned by the pn_url_t.*/
> > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > > > > > +
> > > > > > +/**
> > > > > > + *@name Getters for parts of the URL.
> > > > > > + *
> > > > > > + *Values belong to the URL. May return NULL if the value is not
> > set.
> > > > > > + *
> > > > > > + *@{
> > > > > > + */
> > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > > > > > +///@}
> > > > > > +
> > > > > > +/**
> > > > > > + *@name Setters for parts of the URL.
> > > > > > + *
> > > > > > + *Values are copied. Value can be NULL to indicate the part is not
> > > > set.
> > > > > > + *
> > > > > > + *@{
> > > > > > + */
> > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > *scheme);
> > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > *username);
> > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > *password);
> > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host);
> > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port);
> > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path);
> > > > > > +///@}
> > > > > > +
> > > > > > +///@}
> > > > > > +#endif
> > > > > >
> > > > > > Added: qpid/proton/trunk/proton-c/src/url.c
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > > > > > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50 2014
> > > > > > @@ -0,0 +1,127 @@
> > > > > > +/*
> > > > > > + *
> > > > > > + * 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.
> > > > > > + *
> > > > > > + */
> > > > > > +
> > > > > > +#include <proton/url.h>
> > > > > > +#include <proton/util.h>
> > > > > > +#include <stdlib.h>
> > > > > > +#include <string.h>
> > > > > > +#include <stdio.h>
> > > > > > +
> > > > > > +static char* copy(const char* str) {
> > > > > > +    if (str ==  NULL) return NULL;
> > > > > > +    char *str2 = (char*)malloc(strlen(str));
> > > > > > +    if (str2) strcpy(str2, str);
> > > > > > +    return str2;
> > > > > > +}
> > > > > > +
> > > > > > +struct pn_url_t {
> > > > > > +    char *scheme;
> > > > > > +    char *username;
> > > > > > +    char *password;
> > > > > > +    char *host;
> > > > > > +    char *port;
> > > > > > +    char *path;
> > > > > > +    char *str;
> > > > > > +};
> > > > > > +
> > > > > > +PN_EXTERN pn_url_t *pn_url() {
> > > > > > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > > > > > +    memset(url, 0, sizeof(*url));
> > > > > > +    return url;
> > > > > > +}
> > > > > > +
> > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > + *@param[in] url A URL string.
> > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> > > > string.
> > > > > > + */
> > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > > > > > +    if (!str || !*str)          /* Empty string or NULL is
> > illegal. */
> > > > > > +        return NULL;
> > > > > > +
> > > > > > +    pn_url_t *url = pn_url();
> > > > > > +    char *str2 = copy(str);         /* FIXME aconway 2014-09-19:
> > > > clean up
> > > > > > */
> > > > > > +    pni_parse_url(str2, &url->scheme, &url->username,
> > &url->password,
> > > > > > &url->host, &url->port, &url->path);
> > > > > > +    url->scheme = copy(url->scheme);
> > > > > > +    url->username = copy(url->username);
> > > > > > +    url->password = copy(url->password);
> > > > > > +    url->host = (url->host && !*url->host) ? NULL :
> > copy(url->host);
> > > > > > +    url->port = copy(url->port);
> > > > > > +    url->path = copy(url->path);
> > > > > > +    return url;
> > > > > > +}
> > > > > > +
> > > > > > +/** Free a URL */
> > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > > > > > +    pn_url_clear(url);
> > > > > > +    free(url);
> > > > > > +}
> > > > > > +
> > > > > > +/** Clear the contents of the URL. */
> > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > > > > > +    pn_url_set_username(url, NULL);
> > > > > > +    pn_url_set_password(url, NULL);
> > > > > > +    pn_url_set_host(url, NULL);
> > > > > > +    pn_url_set_port(url, NULL);
> > > > > > +    pn_url_set_path(url, NULL);
> > > > > > +    free(url->str); url->str = NULL;
> > > > > > +}
> > > > > > +
> > > > > > +static inline int len(const char *str) { return str ? strlen(str)
> > :
> > > > 0; }
> > > > > > +
> > > > > > +/** Return the string form of a URL. */
> > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > > > > > +    int size = len(url->scheme) + len(url->username) +
> > > > len(url->password)
> > > > > > +        + len(url->host) + len(url->port) + len(url->path)
> > > > > > +        + len("s://u:p@[h]:p/p");
> > > > > > +    free(url->str);
> > > > > > +    url->str = (char*)malloc(size);
> > > > > > +    if (!url->str) return NULL;
> > > > > > +
> > > > > > +    int i = 0;
> > > > > > +    if (url->scheme) i += snprintf(url->str+i, size-i, "%s://",
> > > > > > url->scheme);
> > > > > > +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> > > > > > url->username);
> > > > > > +    if (url->password) i += snprintf(url->str+i, size-i, ":%s",
> > > > > > url->password);
> > > > > > +    if (url->username || url->password) i += snprintf(url->str+i,
> > > > size-i,
> > > > > > "@");
> > > > > > +    if (url->host) {
> > > > > > +        if (strchr(url->host, ':')) i += snprintf(url->str+i,
> > size-i,
> > > > > > "[%s]", url->host);
> > > > > > +        else i += snprintf(url->str+i, size-i, "%s", url->host);
> > > > > > +    }
> > > > > > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
> > > > url->port);
> > > > > > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
> > > > url->path);
> > > > > > +    return url->str;
> > > > > > +}
> > > > > > +
> > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
> > > > url->scheme; }
> > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> > > > > > url->username; }
> > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> > > > > > url->password; }
> > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return
> > url->host; }
> > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return
> > url->port; }
> > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return
> > url->path; }
> > > > > > +
> > > > > > +#define SET(part) free(url->part); url->part = copy(part)
> > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > *scheme) {
> > > > > > SET(scheme); }
> > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > *username) {
> > > > > > SET(username); }
> > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > *password) {
> > > > > > SET(password); }
> > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host) {
> > > > > > SET(host); }
> > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port) {
> > > > > > SET(port); }
> > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path) {
> > > > > > SET(path); }
> > > > > > +
> > > > > > +
> > > > > >
> > > > > > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/tests/python/proton_tests/url.py (original)
> > > > > > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep 19
> > > > 21:00:50
> > > > > > 2014
> > > > > > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> > > > > >      def assertNotEqual(self, a, b):
> > > > > >          assert a != b, "%s == %s" % (a, b)
> > > > > >
> > > > > > -    def assertUrl(self, u, scheme, user, password, host, port,
> > path):
> > > > > > -        self.assertEqual((u.scheme, u.user, u.password, u.host,
> > > > u.port,
> > > > > > u.path),
> > > > > > -                         (scheme, user, password, host, port,
> > path))
> > > > > > +    def assertUrl(self, u, scheme, username, password, host, port,
> > > > path):
> > > > > > +        self.assertEqual((u.scheme, u.username, u.password,
> > u.host,
> > > > > > u.port, u.path),
> > > > > > +                         (scheme, username, password, host, port,
> > > > path))
> > > > > >
> > > > > >      def testUrl(self):
> > > > > >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > > > > > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> > > > > >
> > > > > >      def testDefaults(self):
> > > > > >          # Check that we allow None for scheme, port
> > > > > > -        url = Url(user='me', password='secret', host='myhost',
> > > > > > path='foobar')
> > > > > > +        url = Url(username='me', password='secret', host='myhost',
> > > > > > path='foobar')
> > > > > >          self.assertEqual(str(url), "me:secret@myhost/foobar")
> > > > > >          self.assertUrl(url, None, 'me', 'secret', 'myhost', None,
> > > > > > 'foobar')
> > > > > >
> > > > > > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> > > > > >      def testMissing(self):
> > > > > >          self.assertUrl(Url(), None, None, None, None, None, None)
> > > > > >          self.assertUrl(Url('amqp://'), 'amqp', None, None, None,
> > None,
> > > > > > None)
> > > > > > -        self.assertUrl(Url('user@'), None, 'user', None, None,
> > None,
> > > > > > None)
> > > > > > +        self.assertUrl(Url('username@'), None, 'username', None,
> > > > None,
> > > > > > None, None)
> > > > > >          self.assertUrl(Url(':pass@'), None, '', 'pass', None,
> > None,
> > > > None)
> > > > > >          self.assertUrl(Url('host'), None, None, None, 'host',
> > None,
> > > > None)
> > > > > >          self.assertUrl(Url(':1234'), None, None, None, None, 1234,
> > > > None)
> > > > > >          self.assertUrl(Url('/path'), None, None, None, None, None,
> > > > 'path')
> > > > > >
> > > > > > -        for s in ['amqp://', 'user@', ':pass@', ':1234',
> > '/path']:
> > > > > > +        for s in ['amqp://', 'username@', ':pass@', ':1234',
> > > > '/path']:
> > > > > >              self.assertEqual(s, str(Url(s)))
> > > > > >
> > > > > >          for s, full in [
> > > > > >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > > > > > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > > > > > +                ('username@', 'amqp://username@0.0.0.0:amqp'),
> > > > > >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> > > > > >                  (':1234', 'amqp://0.0.0.0:1234'),
> > > > > >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> > > > > >              self.assertEqual(str(Url(s).defaults()), full)
> > > > > > -
> > > > > > -        self.assertRaises(ValueError, Url, '')
> > > > > >
> > > > > >
> > > > > >
> > > > > >
> > ---------------------------------------------------------------------
> > > > > > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > > > > > For additional commands, e-mail: commits-help@qpid.apache.org
> > > > > >
> > > > > >
> > > >
> > > >
> > > >
> > > > ---------------------------------------------------------------------
> > > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > > For additional commands, e-mail: dev-help@qpid.apache.org
> > > >
> > > >
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > For additional commands, e-mail: dev-help@qpid.apache.org
> >
> >



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
For additional commands, e-mail: dev-help@qpid.apache.org


Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Alan Conway <ac...@redhat.com>.
On Thu, 2014-09-25 at 15:59 +0100, Robbie Gemmell wrote:
> On 25 September 2014 15:00, Alan Conway <ac...@redhat.com> wrote:
> 
> > On Wed, 2014-09-24 at 12:19 +0100, Robbie Gemmell wrote:
> > > The tests are now running again, but a couple of the URL tests still seem
> > > to be failing on the CI job:
> > >
> > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/
> > >
> >
> > They are all failing with:
> >  Not a valid port number or service name: 'amqps'
> >
> > Could this be a configuration problem on the CI machine, i.e. missing an
> > 'amqps' entry in /etc/services? Can I get access to the CI machine to
> > poke around and see what's up?
> >
> 
> Almost certainly no, only the core maintainers are allowed shell access as
> far as I've seen. You can ask on builds@apache.org for those with access to
> check things out and report back and see what happens.
> 
> I think the CI instances will be running Ubuntu 12.04 or 14.04 LTS. For
> giggles, I dug out an ooooold Ubuntu VM with Java 6 on it and tried the
> tests, which failed, and it indeed has no amqp[s] entry in /etc/services
> file so that could well be it.

Thanks for checking that out! I have hacked the tests to skip tests for
'amqps' if it is not recognized. Poke me if there are still failures.

------------------------------------------------------------------------
r1627577 | aconway | 2014-09-25 13:59:17 -0400 (Thu, 25 Sep 2014) | 5
lines

NO-JIRA: Fix URL test to skip 'amqps' tests if 'amqps' is not recognized
as a service name.

On some older Ubuntu with Java 6, 'amqps' is not recognized as a service
name so
skip those tests in that case.

------------------------------------------------------------------------

> >
> > The URL code uses socket.getservbyname() to look up service names. Is
> > there a more portable way to do it?
> >
> 
> No idea I'm afraid.
> 
> 
> >
> > Cheers,
> > Alan.
> >
> > > As mentioned in my other post about a timeline for dropping Java6
> > support,
> > > they seem to work on Java8 (havent tried Java7).
> > >
> > > Robbie
> > >
> > > On 22 September 2014 21:14, Alan Conway <ac...@redhat.com> wrote:
> > >
> > > > My bad, didn't run the java tests. Will fix ASAP and then give myself a
> > > > flogging.
> > > >
> > > > On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> > > > > This seems to have broken the Java test runs:
> > > > >
> > > > > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> > > > >
> > > > >
> > > > >
> > > > > On 19 September 2014 22:00, <ac...@apache.org> wrote:
> > > > >
> > > > > > Author: aconway
> > > > > > Date: Fri Sep 19 21:00:50 2014
> > > > > > New Revision: 1626329
> > > > > >
> > > > > > URL: http://svn.apache.org/r1626329
> > > > > > Log:
> > > > > > PROTON-693: Python Url class to wrap C function pni_parse_url
> > > > > >
> > > > > > It was pointed out that pni_parse_url is an internal function and
> > the
> > > > > > interface
> > > > > > is not suitable for public API.
> > > > > >
> > > > > > Rewrote the URL parser as a proper swigable C API pn_url_*. This
> > gets
> > > > rid
> > > > > > of the
> > > > > > need for previous swig insanity and is cleaner all round.
> > > > > >
> > > > > > Internally still uses the pni_parse_url parser, we can clean that
> > up
> > > > later.
> > > > > >
> > > > > > Added:
> > > > > >     qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > >     qpid/proton/trunk/proton-c/src/url.c
> > > > > > Modified:
> > > > > >     qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > >     qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > >     qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > >
> > > > > > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > > > > > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19 21:00:50
> > 2014
> > > > > > @@ -270,6 +270,7 @@ set (qpid-proton-core
> > > > > >    src/object/iterator.c
> > > > > >
> > > > > >    src/util.c
> > > > > > +  src/url.c
> > > > > >    src/error.c
> > > > > >    src/buffer.c
> > > > > >    src/parser.c
> > > > > >
> > > > > > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> > > > > > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19
> > 21:00:50
> > > > > > 2014
> > > > > > @@ -8,6 +8,7 @@
> > > > > >  #include <proton/messenger.h>
> > > > > >  #include <proton/ssl.h>
> > > > > >  #include <proton/driver_extras.h>
> > > > > > +#include <proton/url.h>
> > > > > >  %}
> > > > > >
> > > > > >  %include <cstring.i>
> > > > > >
> > > > > > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > > > > > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19
> > 21:00:50
> > > > 2014
> > > > > > @@ -29,6 +29,7 @@
> > > > > >  %header %{
> > > > > >  /* Include the headers needed by the code in this wrapper file */
> > > > > >  #include <proton/types.h>
> > > > > > +#include <proton/url.h>
> > > > > >  #include <proton/message.h>
> > > > > >  #include <proton/driver.h>
> > > > > >  #include <proton/driver_extras.h>
> > > > > >
> > > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i (original)
> > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri Sep 19
> > > > > > 21:00:50 2014
> > > > > > @@ -23,6 +23,7 @@
> > > > > >  #include <winsock2.h>
> > > > > >  #endif
> > > > > >  #include <proton/engine.h>
> > > > > > +#include <proton/url.h>
> > > > > >  #include <proton/message.h>
> > > > > >  #include <proton/sasl.h>
> > > > > >  #include <proton/driver.h>
> > > > > > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> > > > > >    }
> > > > > >  %}
> > > > > >
> > > > > > -
> > > > > > -/**
> > > > > > -   pni_parse_url(char* url, char **scheme, char **user, char
> > **pass,
> > > > char
> > > > > > **host, char **port, char **path)
> > > > > > -   The following type maps convert this into a python function
> > that
> > > > taks
> > > > > > a URL string argument
> > > > > > -   and returns a list of strings [scheme, user, pass, host, port,
> > > > path]
> > > > > > -   This probably could be done more neatly.
> > > > > > -*/
> > > > > > -
> > > > > > -// Typemap to copy the url string as it will be modified by
> > parse_url
> > > > > > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char *url
> > (int
> > > > > > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > > > > > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > > > > > -  if (!SWIG_IsOK(res)) {
> > > > > > -    %argument_fail(res, "char *url", $symname, $argnum);
> > > > > > -  }
> > > > > > -  $1 = %new_array(n, $*1_ltype);
> > > > > > -  memcpy($1,t,sizeof(char)*n);
> > > > > > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > > > > > -  $1[n-1] = 0;
> > > > > > -}
> > > > > > -%typemap(freearg,match="in") char *url "free($1);";
> > > > > > -%typemap(argout) char *url "";
> > > > > > -
> > > > > > -// Typemap for char** return strings. Don't free them.
> > > > > > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0) "$1 =
> > > > &temp;";
> > > > > > -%typemap(freearg,match="in") char **OUTSTR "";
> > > > > > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char
> > **OUTSTR {
> > > > > > -    %append_output(SWIG_FromCharPtr(*$1));
> > > > > > -}
> > > > > > -
> > > > > > -// Typemap to initialize result as empty list
> > > > > > -%typemap(out) void "$result = PyList_New(0);";
> > > > > > -
> > > > > > -
> > > > > > -%apply char** OUTSTR {char **scheme, char **user, char **pass,
> > char
> > > > > > **host, char **port, char **path};
> > > > > > -void pni_parse_url(char* url, char **scheme, char **user, char
> > **pass,
> > > > > > char **host, char **port, char **path);
> > > > > > -%ignore pni_parse_url;
> > > > > > -
> > > > > >  %include "proton/cproton.i"
> > > > > >
> > > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
> > > > > > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri Sep 19
> > > > > > 21:00:50 2014
> > > > > > @@ -3657,114 +3657,98 @@ __all__ = [
> > > > > >
> > > > > >
> > > > > >  class Url(object):
> > > > > > -    """
> > > > > > -    Simple URL parser/constructor, handles URLs of the form:
> > > > > > +  """
> > > > > > +  Simple URL parser/constructor, handles URLs of the form:
> > > > > >
> > > > > > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > >
> > > > > > -    All components can be None if not specifeid in the URL string.
> > > > > > +  All components can be None if not specifeid in the URL string.
> > > > > >
> > > > > > -    The port can be specified as a service name, e.g. 'amqp' in
> > the
> > > > > > -    URL string but Url.port always gives the integer value.
> > > > > > +  The port can be specified as a service name, e.g. 'amqp' in the
> > > > > > +  URL string but Url.port always gives the integer value.
> > > > > > +
> > > > > > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > +  @ivar user: Username
> > > > > > +  @ivar password: Password
> > > > > > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > +  @ivar port: Integer port.
> > > > > > +  @ivar host_port: Returns host:port
> > > > > > +  """
> > > > > > +
> > > > > > +  AMQPS = "amqps"
> > > > > > +  AMQP = "amqp"
> > > > > > +
> > > > > > +  class Port(int):
> > > > > > +    """An integer port number that can be constructed from a
> > service
> > > > name
> > > > > > string"""
> > > > > > +
> > > > > > +    def __new__(cls, value):
> > > > > > +      port = super(Url.Port, cls).__new__(cls,
> > cls.port_int(value))
> > > > > > +      setattr(port, 'name', str(value))
> > > > > > +      return port
> > > > > > +
> > > > > > +    def __eq__(self, x): return str(self) == x or int(self) == x
> > > > > > +    def __ne__(self, x): return not self == x
> > > > > > +    def __str__(self): return str(self.name)
> > > > > > +
> > > > > > +    @staticmethod
> > > > > > +    def port_int(value):
> > > > > > +      """Convert service, an integer or a service name, into an
> > > > integer
> > > > > > port number."""
> > > > > > +      try:
> > > > > > +        return int(value)
> > > > > > +      except ValueError:
> > > > > > +        try:
> > > > > > +          return socket.getservbyname(value)
> > > > > > +        except socket.error:
> > > > > > +          raise ValueError("Not a valid port number or service
> > name:
> > > > > > '%s'" % value)
> > > > > >
> > > > > > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > > -    @ivar user: Username
> > > > > > -    @ivar password: Password
> > > > > > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > > -    @ivar port: Integer port.
> > > > > > -    @ivar host_port: Returns host:port
> > > > > > +  def __init__(self, url=None, **kwargs):
> > > > > > +    """
> > > > > > +    @param url: URL string to parse.
> > > > > > +    @param kwargs: scheme, user, password, host, port, path.
> > > > > > +      If specified, replaces corresponding part in url string.
> > > > > >      """
> > > > > > +    if url:
> > > > > > +      self._url = pn_url_parse(str(url))
> > > > > > +      if not self._url: raise ValueError("Invalid URL '%s'" % url)
> > > > > > +    else:
> > > > > > +      self._url = pn_url()
> > > > > > +    for k in kwargs:            # Let kwargs override values
> > parsed
> > > > from
> > > > > > url
> > > > > > +      getattr(self, k)          # Check for invalid kwargs
> > > > > > +      setattr(self, k, kwargs[k])
> > > > > > +
> > > > > > +  class PartDescriptor(object):
> > > > > > +    def __init__(self, part):
> > > > > > +      self.getter = globals()["pn_url_%s" % part]
> > > > > > +      self.setter = globals()["pn_url_set_%s" % part]
> > > > > > +    def __get__(self, obj, type=None): return
> > self.getter(obj._url)
> > > > > > +    def __set__(self, obj, value): return self.setter(obj._url,
> > > > > > str(value))
> > > > > > +
> > > > > > +  scheme = PartDescriptor('scheme')
> > > > > > +  username = PartDescriptor('username')
> > > > > > +  password = PartDescriptor('password')
> > > > > > +  host = PartDescriptor('host')
> > > > > > +  path = PartDescriptor('path')
> > > > > > +
> > > > > > +  @property
> > > > > > +  def port(self):
> > > > > > +    portstr = pn_url_port(self._url)
> > > > > > +    return portstr and Url.Port(portstr)
> > > > > > +
> > > > > > +  @port.setter
> > > > > > +  def port(self, value):
> > > > > > +    if value is None: pn_url_set_port(self._url, None)
> > > > > > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> > > > > >
> > > > > > -    AMQPS = "amqps"
> > > > > > -    AMQP = "amqp"
> > > > > > +  def __str__(self): return pn_url_str(self._url)
> > > > > >
> > > > > > -    class Port(int):
> > > > > > -      """An integer port number that can also have an associated
> > > > service
> > > > > > name string"""
> > > > > > +  def __repr__(self): return "Url(%r)" % str(self)
> > > > > >
> > > > > > -      def __new__(cls, value):
> > > > > > -        port = super(Url.Port, cls).__new__(cls,
> > cls.port_int(value))
> > > > > > -        setattr(port, 'name', str(value))
> > > > > > -        return port
> > > > > > -
> > > > > > -      def __eq__(self, x): return str(self) == x or int(self) == x
> > > > > > -      def __ne__(self, x): return not self == x
> > > > > > -      def __str__(self): return str(self.name)
> > > > > > -
> > > > > > -      @staticmethod
> > > > > > -      def port_int(value):
> > > > > > -        """Convert service, an integer or a service name, into an
> > > > integer
> > > > > > port number."""
> > > > > > -        try:
> > > > > > -          return int(value)
> > > > > > -        except ValueError:
> > > > > > -          try:
> > > > > > -            return socket.getservbyname(value)
> > > > > > -          except socket.error:
> > > > > > -            raise ValueError("Not a valid port number or service
> > name:
> > > > > > '%s'" % value)
> > > > > > -
> > > > > > -    def __init__(self, url=None, **kwargs):
> > > > > > -        """
> > > > > > -        @param url: String or Url instance to parse or copy.
> > > > > > -        @param kwargs: URL fields: scheme, user, password, host,
> > port,
> > > > > > path.
> > > > > > -            If specified, replaces corresponding component in url.
> > > > > > -        """
> > > > > > -
> > > > > > -        fields = ['scheme', 'user', 'password', 'host', 'port',
> > > > 'path']
> > > > > > -
> > > > > > -        for f in fields: setattr(self, f, None)
> > > > > > -        for k in kwargs: getattr(self, k) # Check for invalid
> > kwargs
> > > > > > -
> > > > > > -        if isinstance(url, Url): # Copy from another Url instance.
> > > > > > -            self.__dict__.update(url.__dict__)
> > > > > > -        elif url is not None:   # Parse from url
> > > > > > -            parts = pni_parse_url(str(url))
> > > > > > -            if not filter(None, parts): raise ValueError("Invalid
> > AMQP
> > > > > > URL: '%s'" % url)
> > > > > > -            self.scheme, self.user, self.password, self.host,
> > port,
> > > > > > self.path = parts
> > > > > > -            if not self.host: self.host = None
> > > > > > -            self.port = port and self.Port(port)
> > > > > > -
> > > > > > -        # Let kwargs override values previously set from url
> > > > > > -        for field in fields:
> > > > > > -            setattr(self, field, kwargs.get(field, getattr(self,
> > > > field)))
> > > > > > -
> > > > > > -    def __repr__(self):
> > > > > > -        return "Url(%r)" % str(self)
> > > > > > -
> > > > > > -    def __str__(self):
> > > > > > -        s = ""
> > > > > > -        if self.scheme:
> > > > > > -            s += "%s://" % self.scheme
> > > > > > -        if self.user:
> > > > > > -            s += self.user
> > > > > > -        if self.password:
> > > > > > -            s += ":%s" % self.password
> > > > > > -        if self.user or self.password:
> > > > > > -            s += '@'
> > > > > > -        if self.host and ':' in self.host:
> > > > > > -            s += "[%s]" % self.host
> > > > > > -        elif self.host:
> > > > > > -            s += self.host
> > > > > > -        if self.port:
> > > > > > -            s += ":%s" % self.port
> > > > > > -        if self.path:
> > > > > > -            s += "/%s" % self.path
> > > > > > -        return s
> > > > > > -
> > > > > > -    def __eq__(self, url):
> > > > > > -        return \
> > > > > > -            self.scheme == url.scheme and \
> > > > > > -            self.user == url.user and self.password ==
> > url.password
> > > > and \
> > > > > > -            self.host == url.host and self.port == url.port and \
> > > > > > -            self.path == url.path
> > > > > > -
> > > > > > -    def __ne__(self, url):
> > > > > > -        return not self.__eq__(url)
> > > > > > -
> > > > > > -    def defaults(self):
> > > > > > -        """
> > > > > > -        Fill in missing values with defaults
> > > > > > -        @return: self
> > > > > > -        """
> > > > > > -        self.scheme = self.scheme or self.AMQP
> > > > > > -        self.host = self.host or '0.0.0.0'
> > > > > > -        self.port = self.port or self.Port(self.scheme)
> > > > > > -        return self
> > > > > > +  def defaults(self):
> > > > > > +    """
> > > > > > +    Fill in missing values (scheme, host or port) with defaults
> > > > > > +    @return: self
> > > > > > +    """
> > > > > > +    self.scheme = self.scheme or self.AMQP
> > > > > > +    self.host = self.host or '0.0.0.0'
> > > > > > +    self.port = self.port or self.Port(self.scheme)
> > > > > > +    return self
> > > > > >
> > > > > > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> > > > > > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19
> > 21:00:50
> > > > > > 2014
> > > > > > @@ -26,8 +26,8 @@
> > > > > >  #include <proton/messenger.h>
> > > > > >  #include <proton/ssl.h>
> > > > > >  #include <proton/driver_extras.h>
> > > > > > -
> > > > > >  #include <proton/types.h>
> > > > > > +#include <proton/url.h>
> > > > > >
> > > > > >  #include <uuid/uuid.h>
> > > > > >  %}
> > > > > >
> > > > > > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/include/proton/cproton.i (original)
> > > > > > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri Sep 19
> > > > > > 21:00:50 2014
> > > > > > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> > > > > >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return
> > (pn_delivery_t
> > > > *)
> > > > > > x; }
> > > > > >    pn_transport_t *pn_cast_pn_transport(void *x) { return
> > > > (pn_transport_t
> > > > > > *) x; }
> > > > > >  %}
> > > > > > +
> > > > > > +%include "proton/url.h"
> > > > > > +
> > > > > >
> > > > > > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > > > > > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19
> > 21:00:50
> > > > > > 2014
> > > > > > @@ -0,0 +1,83 @@
> > > > > > +#ifndef PROTON_URL_H
> > > > > > +#define PROTON_URL_H
> > > > > > +/*
> > > > > > + * 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.
> > > > > > + */
> > > > > > +
> > > > > > +#include <proton/import_export.h>
> > > > > > +
> > > > > > +/** @file
> > > > > > + * URL API for parsing URLs.
> > > > > > + *
> > > > > > + * @defgroup url URL
> > > > > > + * @{
> > > > > > + */
> > > > > > +
> > > > > > +/** A parsed URL */
> > > > > > +typedef struct pn_url_t pn_url_t;
> > > > > > +
> > > > > > +/** Create an empty URL */
> > > > > > +PN_EXTERN pn_url_t *pn_url(void);
> > > > > > +
> > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > + *@param[in] url A URL string.
> > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> > > > string.
> > > > > > + */
> > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > > > > > +
> > > > > > +/** Free a URL */
> > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > > > > > +
> > > > > > +/** Clear the contents of the URL. */
> > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > > > > > +
> > > > > > +/** Return the string form of a URL. Owned by the pn_url_t.*/
> > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > > > > > +
> > > > > > +/**
> > > > > > + *@name Getters for parts of the URL.
> > > > > > + *
> > > > > > + *Values belong to the URL. May return NULL if the value is not
> > set.
> > > > > > + *
> > > > > > + *@{
> > > > > > + */
> > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > > > > > +///@}
> > > > > > +
> > > > > > +/**
> > > > > > + *@name Setters for parts of the URL.
> > > > > > + *
> > > > > > + *Values are copied. Value can be NULL to indicate the part is not
> > > > set.
> > > > > > + *
> > > > > > + *@{
> > > > > > + */
> > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > *scheme);
> > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > *username);
> > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > *password);
> > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host);
> > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port);
> > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path);
> > > > > > +///@}
> > > > > > +
> > > > > > +///@}
> > > > > > +#endif
> > > > > >
> > > > > > Added: qpid/proton/trunk/proton-c/src/url.c
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > > > > > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50 2014
> > > > > > @@ -0,0 +1,127 @@
> > > > > > +/*
> > > > > > + *
> > > > > > + * 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.
> > > > > > + *
> > > > > > + */
> > > > > > +
> > > > > > +#include <proton/url.h>
> > > > > > +#include <proton/util.h>
> > > > > > +#include <stdlib.h>
> > > > > > +#include <string.h>
> > > > > > +#include <stdio.h>
> > > > > > +
> > > > > > +static char* copy(const char* str) {
> > > > > > +    if (str ==  NULL) return NULL;
> > > > > > +    char *str2 = (char*)malloc(strlen(str));
> > > > > > +    if (str2) strcpy(str2, str);
> > > > > > +    return str2;
> > > > > > +}
> > > > > > +
> > > > > > +struct pn_url_t {
> > > > > > +    char *scheme;
> > > > > > +    char *username;
> > > > > > +    char *password;
> > > > > > +    char *host;
> > > > > > +    char *port;
> > > > > > +    char *path;
> > > > > > +    char *str;
> > > > > > +};
> > > > > > +
> > > > > > +PN_EXTERN pn_url_t *pn_url() {
> > > > > > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > > > > > +    memset(url, 0, sizeof(*url));
> > > > > > +    return url;
> > > > > > +}
> > > > > > +
> > > > > > +/** Parse a string URL as a pn_url_t.
> > > > > > + *@param[in] url A URL string.
> > > > > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> > > > string.
> > > > > > + */
> > > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > > > > > +    if (!str || !*str)          /* Empty string or NULL is
> > illegal. */
> > > > > > +        return NULL;
> > > > > > +
> > > > > > +    pn_url_t *url = pn_url();
> > > > > > +    char *str2 = copy(str);         /* FIXME aconway 2014-09-19:
> > > > clean up
> > > > > > */
> > > > > > +    pni_parse_url(str2, &url->scheme, &url->username,
> > &url->password,
> > > > > > &url->host, &url->port, &url->path);
> > > > > > +    url->scheme = copy(url->scheme);
> > > > > > +    url->username = copy(url->username);
> > > > > > +    url->password = copy(url->password);
> > > > > > +    url->host = (url->host && !*url->host) ? NULL :
> > copy(url->host);
> > > > > > +    url->port = copy(url->port);
> > > > > > +    url->path = copy(url->path);
> > > > > > +    return url;
> > > > > > +}
> > > > > > +
> > > > > > +/** Free a URL */
> > > > > > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > > > > > +    pn_url_clear(url);
> > > > > > +    free(url);
> > > > > > +}
> > > > > > +
> > > > > > +/** Clear the contents of the URL. */
> > > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > > > > > +    pn_url_set_username(url, NULL);
> > > > > > +    pn_url_set_password(url, NULL);
> > > > > > +    pn_url_set_host(url, NULL);
> > > > > > +    pn_url_set_port(url, NULL);
> > > > > > +    pn_url_set_path(url, NULL);
> > > > > > +    free(url->str); url->str = NULL;
> > > > > > +}
> > > > > > +
> > > > > > +static inline int len(const char *str) { return str ? strlen(str)
> > :
> > > > 0; }
> > > > > > +
> > > > > > +/** Return the string form of a URL. */
> > > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > > > > > +    int size = len(url->scheme) + len(url->username) +
> > > > len(url->password)
> > > > > > +        + len(url->host) + len(url->port) + len(url->path)
> > > > > > +        + len("s://u:p@[h]:p/p");
> > > > > > +    free(url->str);
> > > > > > +    url->str = (char*)malloc(size);
> > > > > > +    if (!url->str) return NULL;
> > > > > > +
> > > > > > +    int i = 0;
> > > > > > +    if (url->scheme) i += snprintf(url->str+i, size-i, "%s://",
> > > > > > url->scheme);
> > > > > > +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> > > > > > url->username);
> > > > > > +    if (url->password) i += snprintf(url->str+i, size-i, ":%s",
> > > > > > url->password);
> > > > > > +    if (url->username || url->password) i += snprintf(url->str+i,
> > > > size-i,
> > > > > > "@");
> > > > > > +    if (url->host) {
> > > > > > +        if (strchr(url->host, ':')) i += snprintf(url->str+i,
> > size-i,
> > > > > > "[%s]", url->host);
> > > > > > +        else i += snprintf(url->str+i, size-i, "%s", url->host);
> > > > > > +    }
> > > > > > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
> > > > url->port);
> > > > > > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
> > > > url->path);
> > > > > > +    return url->str;
> > > > > > +}
> > > > > > +
> > > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
> > > > url->scheme; }
> > > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> > > > > > url->username; }
> > > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> > > > > > url->password; }
> > > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return
> > url->host; }
> > > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return
> > url->port; }
> > > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return
> > url->path; }
> > > > > > +
> > > > > > +#define SET(part) free(url->part); url->part = copy(part)
> > > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> > *scheme) {
> > > > > > SET(scheme); }
> > > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > > *username) {
> > > > > > SET(username); }
> > > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > > *password) {
> > > > > > SET(password); }
> > > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host) {
> > > > > > SET(host); }
> > > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port) {
> > > > > > SET(port); }
> > > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path) {
> > > > > > SET(path); }
> > > > > > +
> > > > > > +
> > > > > >
> > > > > > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > > URL:
> > > > > >
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > > >
> > > > > >
> > > >
> > ==============================================================================
> > > > > > --- qpid/proton/trunk/tests/python/proton_tests/url.py (original)
> > > > > > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep 19
> > > > 21:00:50
> > > > > > 2014
> > > > > > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> > > > > >      def assertNotEqual(self, a, b):
> > > > > >          assert a != b, "%s == %s" % (a, b)
> > > > > >
> > > > > > -    def assertUrl(self, u, scheme, user, password, host, port,
> > path):
> > > > > > -        self.assertEqual((u.scheme, u.user, u.password, u.host,
> > > > u.port,
> > > > > > u.path),
> > > > > > -                         (scheme, user, password, host, port,
> > path))
> > > > > > +    def assertUrl(self, u, scheme, username, password, host, port,
> > > > path):
> > > > > > +        self.assertEqual((u.scheme, u.username, u.password,
> > u.host,
> > > > > > u.port, u.path),
> > > > > > +                         (scheme, username, password, host, port,
> > > > path))
> > > > > >
> > > > > >      def testUrl(self):
> > > > > >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > > > > > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> > > > > >
> > > > > >      def testDefaults(self):
> > > > > >          # Check that we allow None for scheme, port
> > > > > > -        url = Url(user='me', password='secret', host='myhost',
> > > > > > path='foobar')
> > > > > > +        url = Url(username='me', password='secret', host='myhost',
> > > > > > path='foobar')
> > > > > >          self.assertEqual(str(url), "me:secret@myhost/foobar")
> > > > > >          self.assertUrl(url, None, 'me', 'secret', 'myhost', None,
> > > > > > 'foobar')
> > > > > >
> > > > > > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> > > > > >      def testMissing(self):
> > > > > >          self.assertUrl(Url(), None, None, None, None, None, None)
> > > > > >          self.assertUrl(Url('amqp://'), 'amqp', None, None, None,
> > None,
> > > > > > None)
> > > > > > -        self.assertUrl(Url('user@'), None, 'user', None, None,
> > None,
> > > > > > None)
> > > > > > +        self.assertUrl(Url('username@'), None, 'username', None,
> > > > None,
> > > > > > None, None)
> > > > > >          self.assertUrl(Url(':pass@'), None, '', 'pass', None,
> > None,
> > > > None)
> > > > > >          self.assertUrl(Url('host'), None, None, None, 'host',
> > None,
> > > > None)
> > > > > >          self.assertUrl(Url(':1234'), None, None, None, None, 1234,
> > > > None)
> > > > > >          self.assertUrl(Url('/path'), None, None, None, None, None,
> > > > 'path')
> > > > > >
> > > > > > -        for s in ['amqp://', 'user@', ':pass@', ':1234',
> > '/path']:
> > > > > > +        for s in ['amqp://', 'username@', ':pass@', ':1234',
> > > > '/path']:
> > > > > >              self.assertEqual(s, str(Url(s)))
> > > > > >
> > > > > >          for s, full in [
> > > > > >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > > > > > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > > > > > +                ('username@', 'amqp://username@0.0.0.0:amqp'),
> > > > > >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> > > > > >                  (':1234', 'amqp://0.0.0.0:1234'),
> > > > > >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> > > > > >              self.assertEqual(str(Url(s).defaults()), full)
> > > > > > -
> > > > > > -        self.assertRaises(ValueError, Url, '')
> > > > > >
> > > > > >
> > > > > >
> > > > > >
> > ---------------------------------------------------------------------
> > > > > > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > > > > > For additional commands, e-mail: commits-help@qpid.apache.org
> > > > > >
> > > > > >
> > > >
> > > >
> > > >
> > > > ---------------------------------------------------------------------
> > > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > > For additional commands, e-mail: dev-help@qpid.apache.org
> > > >
> > > >
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > For additional commands, e-mail: dev-help@qpid.apache.org
> >
> >



Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Robbie Gemmell <ro...@gmail.com>.
On 25 September 2014 15:00, Alan Conway <ac...@redhat.com> wrote:

> On Wed, 2014-09-24 at 12:19 +0100, Robbie Gemmell wrote:
> > The tests are now running again, but a couple of the URL tests still seem
> > to be failing on the CI job:
> >
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/
> >
>
> They are all failing with:
>  Not a valid port number or service name: 'amqps'
>
> Could this be a configuration problem on the CI machine, i.e. missing an
> 'amqps' entry in /etc/services? Can I get access to the CI machine to
> poke around and see what's up?
>

Almost certainly no, only the core maintainers are allowed shell access as
far as I've seen. You can ask on builds@apache.org for those with access to
check things out and report back and see what happens.

I think the CI instances will be running Ubuntu 12.04 or 14.04 LTS. For
giggles, I dug out an ooooold Ubuntu VM with Java 6 on it and tried the
tests, which failed, and it indeed has no amqp[s] entry in /etc/services
file so that could well be it.


>
> The URL code uses socket.getservbyname() to look up service names. Is
> there a more portable way to do it?
>

No idea I'm afraid.


>
> Cheers,
> Alan.
>
> > As mentioned in my other post about a timeline for dropping Java6
> support,
> > they seem to work on Java8 (havent tried Java7).
> >
> > Robbie
> >
> > On 22 September 2014 21:14, Alan Conway <ac...@redhat.com> wrote:
> >
> > > My bad, didn't run the java tests. Will fix ASAP and then give myself a
> > > flogging.
> > >
> > > On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> > > > This seems to have broken the Java test runs:
> > > >
> > > > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> > > >
> > > >
> > > >
> > > > On 19 September 2014 22:00, <ac...@apache.org> wrote:
> > > >
> > > > > Author: aconway
> > > > > Date: Fri Sep 19 21:00:50 2014
> > > > > New Revision: 1626329
> > > > >
> > > > > URL: http://svn.apache.org/r1626329
> > > > > Log:
> > > > > PROTON-693: Python Url class to wrap C function pni_parse_url
> > > > >
> > > > > It was pointed out that pni_parse_url is an internal function and
> the
> > > > > interface
> > > > > is not suitable for public API.
> > > > >
> > > > > Rewrote the URL parser as a proper swigable C API pn_url_*. This
> gets
> > > rid
> > > > > of the
> > > > > need for previous swig insanity and is cleaner all round.
> > > > >
> > > > > Internally still uses the pni_parse_url parser, we can clean that
> up
> > > later.
> > > > >
> > > > > Added:
> > > > >     qpid/proton/trunk/proton-c/include/proton/url.h
> > > > >     qpid/proton/trunk/proton-c/src/url.c
> > > > > Modified:
> > > > >     qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > >     qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > >     qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > >
> > > > > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > > > > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19 21:00:50
> 2014
> > > > > @@ -270,6 +270,7 @@ set (qpid-proton-core
> > > > >    src/object/iterator.c
> > > > >
> > > > >    src/util.c
> > > > > +  src/url.c
> > > > >    src/error.c
> > > > >    src/buffer.c
> > > > >    src/parser.c
> > > > >
> > > > > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> > > > > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19
> 21:00:50
> > > > > 2014
> > > > > @@ -8,6 +8,7 @@
> > > > >  #include <proton/messenger.h>
> > > > >  #include <proton/ssl.h>
> > > > >  #include <proton/driver_extras.h>
> > > > > +#include <proton/url.h>
> > > > >  %}
> > > > >
> > > > >  %include <cstring.i>
> > > > >
> > > > > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > > > > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19
> 21:00:50
> > > 2014
> > > > > @@ -29,6 +29,7 @@
> > > > >  %header %{
> > > > >  /* Include the headers needed by the code in this wrapper file */
> > > > >  #include <proton/types.h>
> > > > > +#include <proton/url.h>
> > > > >  #include <proton/message.h>
> > > > >  #include <proton/driver.h>
> > > > >  #include <proton/driver_extras.h>
> > > > >
> > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i (original)
> > > > > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri Sep 19
> > > > > 21:00:50 2014
> > > > > @@ -23,6 +23,7 @@
> > > > >  #include <winsock2.h>
> > > > >  #endif
> > > > >  #include <proton/engine.h>
> > > > > +#include <proton/url.h>
> > > > >  #include <proton/message.h>
> > > > >  #include <proton/sasl.h>
> > > > >  #include <proton/driver.h>
> > > > > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> > > > >    }
> > > > >  %}
> > > > >
> > > > > -
> > > > > -/**
> > > > > -   pni_parse_url(char* url, char **scheme, char **user, char
> **pass,
> > > char
> > > > > **host, char **port, char **path)
> > > > > -   The following type maps convert this into a python function
> that
> > > taks
> > > > > a URL string argument
> > > > > -   and returns a list of strings [scheme, user, pass, host, port,
> > > path]
> > > > > -   This probably could be done more neatly.
> > > > > -*/
> > > > > -
> > > > > -// Typemap to copy the url string as it will be modified by
> parse_url
> > > > > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char *url
> (int
> > > > > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > > > > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > > > > -  if (!SWIG_IsOK(res)) {
> > > > > -    %argument_fail(res, "char *url", $symname, $argnum);
> > > > > -  }
> > > > > -  $1 = %new_array(n, $*1_ltype);
> > > > > -  memcpy($1,t,sizeof(char)*n);
> > > > > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > > > > -  $1[n-1] = 0;
> > > > > -}
> > > > > -%typemap(freearg,match="in") char *url "free($1);";
> > > > > -%typemap(argout) char *url "";
> > > > > -
> > > > > -// Typemap for char** return strings. Don't free them.
> > > > > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0) "$1 =
> > > &temp;";
> > > > > -%typemap(freearg,match="in") char **OUTSTR "";
> > > > > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char
> **OUTSTR {
> > > > > -    %append_output(SWIG_FromCharPtr(*$1));
> > > > > -}
> > > > > -
> > > > > -// Typemap to initialize result as empty list
> > > > > -%typemap(out) void "$result = PyList_New(0);";
> > > > > -
> > > > > -
> > > > > -%apply char** OUTSTR {char **scheme, char **user, char **pass,
> char
> > > > > **host, char **port, char **path};
> > > > > -void pni_parse_url(char* url, char **scheme, char **user, char
> **pass,
> > > > > char **host, char **port, char **path);
> > > > > -%ignore pni_parse_url;
> > > > > -
> > > > >  %include "proton/cproton.i"
> > > > >
> > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
> > > > > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri Sep 19
> > > > > 21:00:50 2014
> > > > > @@ -3657,114 +3657,98 @@ __all__ = [
> > > > >
> > > > >
> > > > >  class Url(object):
> > > > > -    """
> > > > > -    Simple URL parser/constructor, handles URLs of the form:
> > > > > +  """
> > > > > +  Simple URL parser/constructor, handles URLs of the form:
> > > > >
> > > > > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > >
> > > > > -    All components can be None if not specifeid in the URL string.
> > > > > +  All components can be None if not specifeid in the URL string.
> > > > >
> > > > > -    The port can be specified as a service name, e.g. 'amqp' in
> the
> > > > > -    URL string but Url.port always gives the integer value.
> > > > > +  The port can be specified as a service name, e.g. 'amqp' in the
> > > > > +  URL string but Url.port always gives the integer value.
> > > > > +
> > > > > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > +  @ivar user: Username
> > > > > +  @ivar password: Password
> > > > > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > +  @ivar port: Integer port.
> > > > > +  @ivar host_port: Returns host:port
> > > > > +  """
> > > > > +
> > > > > +  AMQPS = "amqps"
> > > > > +  AMQP = "amqp"
> > > > > +
> > > > > +  class Port(int):
> > > > > +    """An integer port number that can be constructed from a
> service
> > > name
> > > > > string"""
> > > > > +
> > > > > +    def __new__(cls, value):
> > > > > +      port = super(Url.Port, cls).__new__(cls,
> cls.port_int(value))
> > > > > +      setattr(port, 'name', str(value))
> > > > > +      return port
> > > > > +
> > > > > +    def __eq__(self, x): return str(self) == x or int(self) == x
> > > > > +    def __ne__(self, x): return not self == x
> > > > > +    def __str__(self): return str(self.name)
> > > > > +
> > > > > +    @staticmethod
> > > > > +    def port_int(value):
> > > > > +      """Convert service, an integer or a service name, into an
> > > integer
> > > > > port number."""
> > > > > +      try:
> > > > > +        return int(value)
> > > > > +      except ValueError:
> > > > > +        try:
> > > > > +          return socket.getservbyname(value)
> > > > > +        except socket.error:
> > > > > +          raise ValueError("Not a valid port number or service
> name:
> > > > > '%s'" % value)
> > > > >
> > > > > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > -    @ivar user: Username
> > > > > -    @ivar password: Password
> > > > > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > -    @ivar port: Integer port.
> > > > > -    @ivar host_port: Returns host:port
> > > > > +  def __init__(self, url=None, **kwargs):
> > > > > +    """
> > > > > +    @param url: URL string to parse.
> > > > > +    @param kwargs: scheme, user, password, host, port, path.
> > > > > +      If specified, replaces corresponding part in url string.
> > > > >      """
> > > > > +    if url:
> > > > > +      self._url = pn_url_parse(str(url))
> > > > > +      if not self._url: raise ValueError("Invalid URL '%s'" % url)
> > > > > +    else:
> > > > > +      self._url = pn_url()
> > > > > +    for k in kwargs:            # Let kwargs override values
> parsed
> > > from
> > > > > url
> > > > > +      getattr(self, k)          # Check for invalid kwargs
> > > > > +      setattr(self, k, kwargs[k])
> > > > > +
> > > > > +  class PartDescriptor(object):
> > > > > +    def __init__(self, part):
> > > > > +      self.getter = globals()["pn_url_%s" % part]
> > > > > +      self.setter = globals()["pn_url_set_%s" % part]
> > > > > +    def __get__(self, obj, type=None): return
> self.getter(obj._url)
> > > > > +    def __set__(self, obj, value): return self.setter(obj._url,
> > > > > str(value))
> > > > > +
> > > > > +  scheme = PartDescriptor('scheme')
> > > > > +  username = PartDescriptor('username')
> > > > > +  password = PartDescriptor('password')
> > > > > +  host = PartDescriptor('host')
> > > > > +  path = PartDescriptor('path')
> > > > > +
> > > > > +  @property
> > > > > +  def port(self):
> > > > > +    portstr = pn_url_port(self._url)
> > > > > +    return portstr and Url.Port(portstr)
> > > > > +
> > > > > +  @port.setter
> > > > > +  def port(self, value):
> > > > > +    if value is None: pn_url_set_port(self._url, None)
> > > > > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> > > > >
> > > > > -    AMQPS = "amqps"
> > > > > -    AMQP = "amqp"
> > > > > +  def __str__(self): return pn_url_str(self._url)
> > > > >
> > > > > -    class Port(int):
> > > > > -      """An integer port number that can also have an associated
> > > service
> > > > > name string"""
> > > > > +  def __repr__(self): return "Url(%r)" % str(self)
> > > > >
> > > > > -      def __new__(cls, value):
> > > > > -        port = super(Url.Port, cls).__new__(cls,
> cls.port_int(value))
> > > > > -        setattr(port, 'name', str(value))
> > > > > -        return port
> > > > > -
> > > > > -      def __eq__(self, x): return str(self) == x or int(self) == x
> > > > > -      def __ne__(self, x): return not self == x
> > > > > -      def __str__(self): return str(self.name)
> > > > > -
> > > > > -      @staticmethod
> > > > > -      def port_int(value):
> > > > > -        """Convert service, an integer or a service name, into an
> > > integer
> > > > > port number."""
> > > > > -        try:
> > > > > -          return int(value)
> > > > > -        except ValueError:
> > > > > -          try:
> > > > > -            return socket.getservbyname(value)
> > > > > -          except socket.error:
> > > > > -            raise ValueError("Not a valid port number or service
> name:
> > > > > '%s'" % value)
> > > > > -
> > > > > -    def __init__(self, url=None, **kwargs):
> > > > > -        """
> > > > > -        @param url: String or Url instance to parse or copy.
> > > > > -        @param kwargs: URL fields: scheme, user, password, host,
> port,
> > > > > path.
> > > > > -            If specified, replaces corresponding component in url.
> > > > > -        """
> > > > > -
> > > > > -        fields = ['scheme', 'user', 'password', 'host', 'port',
> > > 'path']
> > > > > -
> > > > > -        for f in fields: setattr(self, f, None)
> > > > > -        for k in kwargs: getattr(self, k) # Check for invalid
> kwargs
> > > > > -
> > > > > -        if isinstance(url, Url): # Copy from another Url instance.
> > > > > -            self.__dict__.update(url.__dict__)
> > > > > -        elif url is not None:   # Parse from url
> > > > > -            parts = pni_parse_url(str(url))
> > > > > -            if not filter(None, parts): raise ValueError("Invalid
> AMQP
> > > > > URL: '%s'" % url)
> > > > > -            self.scheme, self.user, self.password, self.host,
> port,
> > > > > self.path = parts
> > > > > -            if not self.host: self.host = None
> > > > > -            self.port = port and self.Port(port)
> > > > > -
> > > > > -        # Let kwargs override values previously set from url
> > > > > -        for field in fields:
> > > > > -            setattr(self, field, kwargs.get(field, getattr(self,
> > > field)))
> > > > > -
> > > > > -    def __repr__(self):
> > > > > -        return "Url(%r)" % str(self)
> > > > > -
> > > > > -    def __str__(self):
> > > > > -        s = ""
> > > > > -        if self.scheme:
> > > > > -            s += "%s://" % self.scheme
> > > > > -        if self.user:
> > > > > -            s += self.user
> > > > > -        if self.password:
> > > > > -            s += ":%s" % self.password
> > > > > -        if self.user or self.password:
> > > > > -            s += '@'
> > > > > -        if self.host and ':' in self.host:
> > > > > -            s += "[%s]" % self.host
> > > > > -        elif self.host:
> > > > > -            s += self.host
> > > > > -        if self.port:
> > > > > -            s += ":%s" % self.port
> > > > > -        if self.path:
> > > > > -            s += "/%s" % self.path
> > > > > -        return s
> > > > > -
> > > > > -    def __eq__(self, url):
> > > > > -        return \
> > > > > -            self.scheme == url.scheme and \
> > > > > -            self.user == url.user and self.password ==
> url.password
> > > and \
> > > > > -            self.host == url.host and self.port == url.port and \
> > > > > -            self.path == url.path
> > > > > -
> > > > > -    def __ne__(self, url):
> > > > > -        return not self.__eq__(url)
> > > > > -
> > > > > -    def defaults(self):
> > > > > -        """
> > > > > -        Fill in missing values with defaults
> > > > > -        @return: self
> > > > > -        """
> > > > > -        self.scheme = self.scheme or self.AMQP
> > > > > -        self.host = self.host or '0.0.0.0'
> > > > > -        self.port = self.port or self.Port(self.scheme)
> > > > > -        return self
> > > > > +  def defaults(self):
> > > > > +    """
> > > > > +    Fill in missing values (scheme, host or port) with defaults
> > > > > +    @return: self
> > > > > +    """
> > > > > +    self.scheme = self.scheme or self.AMQP
> > > > > +    self.host = self.host or '0.0.0.0'
> > > > > +    self.port = self.port or self.Port(self.scheme)
> > > > > +    return self
> > > > >
> > > > > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> > > > > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19
> 21:00:50
> > > > > 2014
> > > > > @@ -26,8 +26,8 @@
> > > > >  #include <proton/messenger.h>
> > > > >  #include <proton/ssl.h>
> > > > >  #include <proton/driver_extras.h>
> > > > > -
> > > > >  #include <proton/types.h>
> > > > > +#include <proton/url.h>
> > > > >
> > > > >  #include <uuid/uuid.h>
> > > > >  %}
> > > > >
> > > > > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/include/proton/cproton.i (original)
> > > > > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri Sep 19
> > > > > 21:00:50 2014
> > > > > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> > > > >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return
> (pn_delivery_t
> > > *)
> > > > > x; }
> > > > >    pn_transport_t *pn_cast_pn_transport(void *x) { return
> > > (pn_transport_t
> > > > > *) x; }
> > > > >  %}
> > > > > +
> > > > > +%include "proton/url.h"
> > > > > +
> > > > >
> > > > > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > > > > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19
> 21:00:50
> > > > > 2014
> > > > > @@ -0,0 +1,83 @@
> > > > > +#ifndef PROTON_URL_H
> > > > > +#define PROTON_URL_H
> > > > > +/*
> > > > > + * 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.
> > > > > + */
> > > > > +
> > > > > +#include <proton/import_export.h>
> > > > > +
> > > > > +/** @file
> > > > > + * URL API for parsing URLs.
> > > > > + *
> > > > > + * @defgroup url URL
> > > > > + * @{
> > > > > + */
> > > > > +
> > > > > +/** A parsed URL */
> > > > > +typedef struct pn_url_t pn_url_t;
> > > > > +
> > > > > +/** Create an empty URL */
> > > > > +PN_EXTERN pn_url_t *pn_url(void);
> > > > > +
> > > > > +/** Parse a string URL as a pn_url_t.
> > > > > + *@param[in] url A URL string.
> > > > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> > > string.
> > > > > + */
> > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > > > > +
> > > > > +/** Free a URL */
> > > > > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > > > > +
> > > > > +/** Clear the contents of the URL. */
> > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > > > > +
> > > > > +/** Return the string form of a URL. Owned by the pn_url_t.*/
> > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > > > > +
> > > > > +/**
> > > > > + *@name Getters for parts of the URL.
> > > > > + *
> > > > > + *Values belong to the URL. May return NULL if the value is not
> set.
> > > > > + *
> > > > > + *@{
> > > > > + */
> > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > > > > +///@}
> > > > > +
> > > > > +/**
> > > > > + *@name Setters for parts of the URL.
> > > > > + *
> > > > > + *Values are copied. Value can be NULL to indicate the part is not
> > > set.
> > > > > + *
> > > > > + *@{
> > > > > + */
> > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> *scheme);
> > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > *username);
> > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > *password);
> > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host);
> > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port);
> > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path);
> > > > > +///@}
> > > > > +
> > > > > +///@}
> > > > > +#endif
> > > > >
> > > > > Added: qpid/proton/trunk/proton-c/src/url.c
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > > > > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50 2014
> > > > > @@ -0,0 +1,127 @@
> > > > > +/*
> > > > > + *
> > > > > + * 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.
> > > > > + *
> > > > > + */
> > > > > +
> > > > > +#include <proton/url.h>
> > > > > +#include <proton/util.h>
> > > > > +#include <stdlib.h>
> > > > > +#include <string.h>
> > > > > +#include <stdio.h>
> > > > > +
> > > > > +static char* copy(const char* str) {
> > > > > +    if (str ==  NULL) return NULL;
> > > > > +    char *str2 = (char*)malloc(strlen(str));
> > > > > +    if (str2) strcpy(str2, str);
> > > > > +    return str2;
> > > > > +}
> > > > > +
> > > > > +struct pn_url_t {
> > > > > +    char *scheme;
> > > > > +    char *username;
> > > > > +    char *password;
> > > > > +    char *host;
> > > > > +    char *port;
> > > > > +    char *path;
> > > > > +    char *str;
> > > > > +};
> > > > > +
> > > > > +PN_EXTERN pn_url_t *pn_url() {
> > > > > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > > > > +    memset(url, 0, sizeof(*url));
> > > > > +    return url;
> > > > > +}
> > > > > +
> > > > > +/** Parse a string URL as a pn_url_t.
> > > > > + *@param[in] url A URL string.
> > > > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> > > string.
> > > > > + */
> > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > > > > +    if (!str || !*str)          /* Empty string or NULL is
> illegal. */
> > > > > +        return NULL;
> > > > > +
> > > > > +    pn_url_t *url = pn_url();
> > > > > +    char *str2 = copy(str);         /* FIXME aconway 2014-09-19:
> > > clean up
> > > > > */
> > > > > +    pni_parse_url(str2, &url->scheme, &url->username,
> &url->password,
> > > > > &url->host, &url->port, &url->path);
> > > > > +    url->scheme = copy(url->scheme);
> > > > > +    url->username = copy(url->username);
> > > > > +    url->password = copy(url->password);
> > > > > +    url->host = (url->host && !*url->host) ? NULL :
> copy(url->host);
> > > > > +    url->port = copy(url->port);
> > > > > +    url->path = copy(url->path);
> > > > > +    return url;
> > > > > +}
> > > > > +
> > > > > +/** Free a URL */
> > > > > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > > > > +    pn_url_clear(url);
> > > > > +    free(url);
> > > > > +}
> > > > > +
> > > > > +/** Clear the contents of the URL. */
> > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > > > > +    pn_url_set_username(url, NULL);
> > > > > +    pn_url_set_password(url, NULL);
> > > > > +    pn_url_set_host(url, NULL);
> > > > > +    pn_url_set_port(url, NULL);
> > > > > +    pn_url_set_path(url, NULL);
> > > > > +    free(url->str); url->str = NULL;
> > > > > +}
> > > > > +
> > > > > +static inline int len(const char *str) { return str ? strlen(str)
> :
> > > 0; }
> > > > > +
> > > > > +/** Return the string form of a URL. */
> > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > > > > +    int size = len(url->scheme) + len(url->username) +
> > > len(url->password)
> > > > > +        + len(url->host) + len(url->port) + len(url->path)
> > > > > +        + len("s://u:p@[h]:p/p");
> > > > > +    free(url->str);
> > > > > +    url->str = (char*)malloc(size);
> > > > > +    if (!url->str) return NULL;
> > > > > +
> > > > > +    int i = 0;
> > > > > +    if (url->scheme) i += snprintf(url->str+i, size-i, "%s://",
> > > > > url->scheme);
> > > > > +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> > > > > url->username);
> > > > > +    if (url->password) i += snprintf(url->str+i, size-i, ":%s",
> > > > > url->password);
> > > > > +    if (url->username || url->password) i += snprintf(url->str+i,
> > > size-i,
> > > > > "@");
> > > > > +    if (url->host) {
> > > > > +        if (strchr(url->host, ':')) i += snprintf(url->str+i,
> size-i,
> > > > > "[%s]", url->host);
> > > > > +        else i += snprintf(url->str+i, size-i, "%s", url->host);
> > > > > +    }
> > > > > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
> > > url->port);
> > > > > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
> > > url->path);
> > > > > +    return url->str;
> > > > > +}
> > > > > +
> > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
> > > url->scheme; }
> > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> > > > > url->username; }
> > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> > > > > url->password; }
> > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return
> url->host; }
> > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return
> url->port; }
> > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return
> url->path; }
> > > > > +
> > > > > +#define SET(part) free(url->part); url->part = copy(part)
> > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> *scheme) {
> > > > > SET(scheme); }
> > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > *username) {
> > > > > SET(username); }
> > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > *password) {
> > > > > SET(password); }
> > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host) {
> > > > > SET(host); }
> > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port) {
> > > > > SET(port); }
> > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path) {
> > > > > SET(path); }
> > > > > +
> > > > > +
> > > > >
> > > > > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/tests/python/proton_tests/url.py (original)
> > > > > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep 19
> > > 21:00:50
> > > > > 2014
> > > > > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> > > > >      def assertNotEqual(self, a, b):
> > > > >          assert a != b, "%s == %s" % (a, b)
> > > > >
> > > > > -    def assertUrl(self, u, scheme, user, password, host, port,
> path):
> > > > > -        self.assertEqual((u.scheme, u.user, u.password, u.host,
> > > u.port,
> > > > > u.path),
> > > > > -                         (scheme, user, password, host, port,
> path))
> > > > > +    def assertUrl(self, u, scheme, username, password, host, port,
> > > path):
> > > > > +        self.assertEqual((u.scheme, u.username, u.password,
> u.host,
> > > > > u.port, u.path),
> > > > > +                         (scheme, username, password, host, port,
> > > path))
> > > > >
> > > > >      def testUrl(self):
> > > > >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > > > > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> > > > >
> > > > >      def testDefaults(self):
> > > > >          # Check that we allow None for scheme, port
> > > > > -        url = Url(user='me', password='secret', host='myhost',
> > > > > path='foobar')
> > > > > +        url = Url(username='me', password='secret', host='myhost',
> > > > > path='foobar')
> > > > >          self.assertEqual(str(url), "me:secret@myhost/foobar")
> > > > >          self.assertUrl(url, None, 'me', 'secret', 'myhost', None,
> > > > > 'foobar')
> > > > >
> > > > > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> > > > >      def testMissing(self):
> > > > >          self.assertUrl(Url(), None, None, None, None, None, None)
> > > > >          self.assertUrl(Url('amqp://'), 'amqp', None, None, None,
> None,
> > > > > None)
> > > > > -        self.assertUrl(Url('user@'), None, 'user', None, None,
> None,
> > > > > None)
> > > > > +        self.assertUrl(Url('username@'), None, 'username', None,
> > > None,
> > > > > None, None)
> > > > >          self.assertUrl(Url(':pass@'), None, '', 'pass', None,
> None,
> > > None)
> > > > >          self.assertUrl(Url('host'), None, None, None, 'host',
> None,
> > > None)
> > > > >          self.assertUrl(Url(':1234'), None, None, None, None, 1234,
> > > None)
> > > > >          self.assertUrl(Url('/path'), None, None, None, None, None,
> > > 'path')
> > > > >
> > > > > -        for s in ['amqp://', 'user@', ':pass@', ':1234',
> '/path']:
> > > > > +        for s in ['amqp://', 'username@', ':pass@', ':1234',
> > > '/path']:
> > > > >              self.assertEqual(s, str(Url(s)))
> > > > >
> > > > >          for s, full in [
> > > > >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > > > > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > > > > +                ('username@', 'amqp://username@0.0.0.0:amqp'),
> > > > >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> > > > >                  (':1234', 'amqp://0.0.0.0:1234'),
> > > > >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> > > > >              self.assertEqual(str(Url(s).defaults()), full)
> > > > > -
> > > > > -        self.assertRaises(ValueError, Url, '')
> > > > >
> > > > >
> > > > >
> > > > >
> ---------------------------------------------------------------------
> > > > > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > > > > For additional commands, e-mail: commits-help@qpid.apache.org
> > > > >
> > > > >
> > >
> > >
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > For additional commands, e-mail: dev-help@qpid.apache.org
> > >
> > >
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> For additional commands, e-mail: dev-help@qpid.apache.org
>
>

Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Robbie Gemmell <ro...@gmail.com>.
On 25 September 2014 15:00, Alan Conway <ac...@redhat.com> wrote:

> On Wed, 2014-09-24 at 12:19 +0100, Robbie Gemmell wrote:
> > The tests are now running again, but a couple of the URL tests still seem
> > to be failing on the CI job:
> >
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/
> >
>
> They are all failing with:
>  Not a valid port number or service name: 'amqps'
>
> Could this be a configuration problem on the CI machine, i.e. missing an
> 'amqps' entry in /etc/services? Can I get access to the CI machine to
> poke around and see what's up?
>

Almost certainly no, only the core maintainers are allowed shell access as
far as I've seen. You can ask on builds@apache.org for those with access to
check things out and report back and see what happens.

I think the CI instances will be running Ubuntu 12.04 or 14.04 LTS. For
giggles, I dug out an ooooold Ubuntu VM with Java 6 on it and tried the
tests, which failed, and it indeed has no amqp[s] entry in /etc/services
file so that could well be it.


>
> The URL code uses socket.getservbyname() to look up service names. Is
> there a more portable way to do it?
>

No idea I'm afraid.


>
> Cheers,
> Alan.
>
> > As mentioned in my other post about a timeline for dropping Java6
> support,
> > they seem to work on Java8 (havent tried Java7).
> >
> > Robbie
> >
> > On 22 September 2014 21:14, Alan Conway <ac...@redhat.com> wrote:
> >
> > > My bad, didn't run the java tests. Will fix ASAP and then give myself a
> > > flogging.
> > >
> > > On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> > > > This seems to have broken the Java test runs:
> > > >
> > > > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> > > >
> > > >
> > > >
> > > > On 19 September 2014 22:00, <ac...@apache.org> wrote:
> > > >
> > > > > Author: aconway
> > > > > Date: Fri Sep 19 21:00:50 2014
> > > > > New Revision: 1626329
> > > > >
> > > > > URL: http://svn.apache.org/r1626329
> > > > > Log:
> > > > > PROTON-693: Python Url class to wrap C function pni_parse_url
> > > > >
> > > > > It was pointed out that pni_parse_url is an internal function and
> the
> > > > > interface
> > > > > is not suitable for public API.
> > > > >
> > > > > Rewrote the URL parser as a proper swigable C API pn_url_*. This
> gets
> > > rid
> > > > > of the
> > > > > need for previous swig insanity and is cleaner all round.
> > > > >
> > > > > Internally still uses the pni_parse_url parser, we can clean that
> up
> > > later.
> > > > >
> > > > > Added:
> > > > >     qpid/proton/trunk/proton-c/include/proton/url.h
> > > > >     qpid/proton/trunk/proton-c/src/url.c
> > > > > Modified:
> > > > >     qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > >     qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > >     qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > >
> > > > > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > > > > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19 21:00:50
> 2014
> > > > > @@ -270,6 +270,7 @@ set (qpid-proton-core
> > > > >    src/object/iterator.c
> > > > >
> > > > >    src/util.c
> > > > > +  src/url.c
> > > > >    src/error.c
> > > > >    src/buffer.c
> > > > >    src/parser.c
> > > > >
> > > > > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> > > > > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19
> 21:00:50
> > > > > 2014
> > > > > @@ -8,6 +8,7 @@
> > > > >  #include <proton/messenger.h>
> > > > >  #include <proton/ssl.h>
> > > > >  #include <proton/driver_extras.h>
> > > > > +#include <proton/url.h>
> > > > >  %}
> > > > >
> > > > >  %include <cstring.i>
> > > > >
> > > > > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > > > > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19
> 21:00:50
> > > 2014
> > > > > @@ -29,6 +29,7 @@
> > > > >  %header %{
> > > > >  /* Include the headers needed by the code in this wrapper file */
> > > > >  #include <proton/types.h>
> > > > > +#include <proton/url.h>
> > > > >  #include <proton/message.h>
> > > > >  #include <proton/driver.h>
> > > > >  #include <proton/driver_extras.h>
> > > > >
> > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i (original)
> > > > > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri Sep 19
> > > > > 21:00:50 2014
> > > > > @@ -23,6 +23,7 @@
> > > > >  #include <winsock2.h>
> > > > >  #endif
> > > > >  #include <proton/engine.h>
> > > > > +#include <proton/url.h>
> > > > >  #include <proton/message.h>
> > > > >  #include <proton/sasl.h>
> > > > >  #include <proton/driver.h>
> > > > > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> > > > >    }
> > > > >  %}
> > > > >
> > > > > -
> > > > > -/**
> > > > > -   pni_parse_url(char* url, char **scheme, char **user, char
> **pass,
> > > char
> > > > > **host, char **port, char **path)
> > > > > -   The following type maps convert this into a python function
> that
> > > taks
> > > > > a URL string argument
> > > > > -   and returns a list of strings [scheme, user, pass, host, port,
> > > path]
> > > > > -   This probably could be done more neatly.
> > > > > -*/
> > > > > -
> > > > > -// Typemap to copy the url string as it will be modified by
> parse_url
> > > > > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char *url
> (int
> > > > > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > > > > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > > > > -  if (!SWIG_IsOK(res)) {
> > > > > -    %argument_fail(res, "char *url", $symname, $argnum);
> > > > > -  }
> > > > > -  $1 = %new_array(n, $*1_ltype);
> > > > > -  memcpy($1,t,sizeof(char)*n);
> > > > > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > > > > -  $1[n-1] = 0;
> > > > > -}
> > > > > -%typemap(freearg,match="in") char *url "free($1);";
> > > > > -%typemap(argout) char *url "";
> > > > > -
> > > > > -// Typemap for char** return strings. Don't free them.
> > > > > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0) "$1 =
> > > &temp;";
> > > > > -%typemap(freearg,match="in") char **OUTSTR "";
> > > > > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char
> **OUTSTR {
> > > > > -    %append_output(SWIG_FromCharPtr(*$1));
> > > > > -}
> > > > > -
> > > > > -// Typemap to initialize result as empty list
> > > > > -%typemap(out) void "$result = PyList_New(0);";
> > > > > -
> > > > > -
> > > > > -%apply char** OUTSTR {char **scheme, char **user, char **pass,
> char
> > > > > **host, char **port, char **path};
> > > > > -void pni_parse_url(char* url, char **scheme, char **user, char
> **pass,
> > > > > char **host, char **port, char **path);
> > > > > -%ignore pni_parse_url;
> > > > > -
> > > > >  %include "proton/cproton.i"
> > > > >
> > > > > Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
> > > > > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri Sep 19
> > > > > 21:00:50 2014
> > > > > @@ -3657,114 +3657,98 @@ __all__ = [
> > > > >
> > > > >
> > > > >  class Url(object):
> > > > > -    """
> > > > > -    Simple URL parser/constructor, handles URLs of the form:
> > > > > +  """
> > > > > +  Simple URL parser/constructor, handles URLs of the form:
> > > > >
> > > > > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > >
> > > > > -    All components can be None if not specifeid in the URL string.
> > > > > +  All components can be None if not specifeid in the URL string.
> > > > >
> > > > > -    The port can be specified as a service name, e.g. 'amqp' in
> the
> > > > > -    URL string but Url.port always gives the integer value.
> > > > > +  The port can be specified as a service name, e.g. 'amqp' in the
> > > > > +  URL string but Url.port always gives the integer value.
> > > > > +
> > > > > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > +  @ivar user: Username
> > > > > +  @ivar password: Password
> > > > > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > +  @ivar port: Integer port.
> > > > > +  @ivar host_port: Returns host:port
> > > > > +  """
> > > > > +
> > > > > +  AMQPS = "amqps"
> > > > > +  AMQP = "amqp"
> > > > > +
> > > > > +  class Port(int):
> > > > > +    """An integer port number that can be constructed from a
> service
> > > name
> > > > > string"""
> > > > > +
> > > > > +    def __new__(cls, value):
> > > > > +      port = super(Url.Port, cls).__new__(cls,
> cls.port_int(value))
> > > > > +      setattr(port, 'name', str(value))
> > > > > +      return port
> > > > > +
> > > > > +    def __eq__(self, x): return str(self) == x or int(self) == x
> > > > > +    def __ne__(self, x): return not self == x
> > > > > +    def __str__(self): return str(self.name)
> > > > > +
> > > > > +    @staticmethod
> > > > > +    def port_int(value):
> > > > > +      """Convert service, an integer or a service name, into an
> > > integer
> > > > > port number."""
> > > > > +      try:
> > > > > +        return int(value)
> > > > > +      except ValueError:
> > > > > +        try:
> > > > > +          return socket.getservbyname(value)
> > > > > +        except socket.error:
> > > > > +          raise ValueError("Not a valid port number or service
> name:
> > > > > '%s'" % value)
> > > > >
> > > > > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > > -    @ivar user: Username
> > > > > -    @ivar password: Password
> > > > > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > > -    @ivar port: Integer port.
> > > > > -    @ivar host_port: Returns host:port
> > > > > +  def __init__(self, url=None, **kwargs):
> > > > > +    """
> > > > > +    @param url: URL string to parse.
> > > > > +    @param kwargs: scheme, user, password, host, port, path.
> > > > > +      If specified, replaces corresponding part in url string.
> > > > >      """
> > > > > +    if url:
> > > > > +      self._url = pn_url_parse(str(url))
> > > > > +      if not self._url: raise ValueError("Invalid URL '%s'" % url)
> > > > > +    else:
> > > > > +      self._url = pn_url()
> > > > > +    for k in kwargs:            # Let kwargs override values
> parsed
> > > from
> > > > > url
> > > > > +      getattr(self, k)          # Check for invalid kwargs
> > > > > +      setattr(self, k, kwargs[k])
> > > > > +
> > > > > +  class PartDescriptor(object):
> > > > > +    def __init__(self, part):
> > > > > +      self.getter = globals()["pn_url_%s" % part]
> > > > > +      self.setter = globals()["pn_url_set_%s" % part]
> > > > > +    def __get__(self, obj, type=None): return
> self.getter(obj._url)
> > > > > +    def __set__(self, obj, value): return self.setter(obj._url,
> > > > > str(value))
> > > > > +
> > > > > +  scheme = PartDescriptor('scheme')
> > > > > +  username = PartDescriptor('username')
> > > > > +  password = PartDescriptor('password')
> > > > > +  host = PartDescriptor('host')
> > > > > +  path = PartDescriptor('path')
> > > > > +
> > > > > +  @property
> > > > > +  def port(self):
> > > > > +    portstr = pn_url_port(self._url)
> > > > > +    return portstr and Url.Port(portstr)
> > > > > +
> > > > > +  @port.setter
> > > > > +  def port(self, value):
> > > > > +    if value is None: pn_url_set_port(self._url, None)
> > > > > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> > > > >
> > > > > -    AMQPS = "amqps"
> > > > > -    AMQP = "amqp"
> > > > > +  def __str__(self): return pn_url_str(self._url)
> > > > >
> > > > > -    class Port(int):
> > > > > -      """An integer port number that can also have an associated
> > > service
> > > > > name string"""
> > > > > +  def __repr__(self): return "Url(%r)" % str(self)
> > > > >
> > > > > -      def __new__(cls, value):
> > > > > -        port = super(Url.Port, cls).__new__(cls,
> cls.port_int(value))
> > > > > -        setattr(port, 'name', str(value))
> > > > > -        return port
> > > > > -
> > > > > -      def __eq__(self, x): return str(self) == x or int(self) == x
> > > > > -      def __ne__(self, x): return not self == x
> > > > > -      def __str__(self): return str(self.name)
> > > > > -
> > > > > -      @staticmethod
> > > > > -      def port_int(value):
> > > > > -        """Convert service, an integer or a service name, into an
> > > integer
> > > > > port number."""
> > > > > -        try:
> > > > > -          return int(value)
> > > > > -        except ValueError:
> > > > > -          try:
> > > > > -            return socket.getservbyname(value)
> > > > > -          except socket.error:
> > > > > -            raise ValueError("Not a valid port number or service
> name:
> > > > > '%s'" % value)
> > > > > -
> > > > > -    def __init__(self, url=None, **kwargs):
> > > > > -        """
> > > > > -        @param url: String or Url instance to parse or copy.
> > > > > -        @param kwargs: URL fields: scheme, user, password, host,
> port,
> > > > > path.
> > > > > -            If specified, replaces corresponding component in url.
> > > > > -        """
> > > > > -
> > > > > -        fields = ['scheme', 'user', 'password', 'host', 'port',
> > > 'path']
> > > > > -
> > > > > -        for f in fields: setattr(self, f, None)
> > > > > -        for k in kwargs: getattr(self, k) # Check for invalid
> kwargs
> > > > > -
> > > > > -        if isinstance(url, Url): # Copy from another Url instance.
> > > > > -            self.__dict__.update(url.__dict__)
> > > > > -        elif url is not None:   # Parse from url
> > > > > -            parts = pni_parse_url(str(url))
> > > > > -            if not filter(None, parts): raise ValueError("Invalid
> AMQP
> > > > > URL: '%s'" % url)
> > > > > -            self.scheme, self.user, self.password, self.host,
> port,
> > > > > self.path = parts
> > > > > -            if not self.host: self.host = None
> > > > > -            self.port = port and self.Port(port)
> > > > > -
> > > > > -        # Let kwargs override values previously set from url
> > > > > -        for field in fields:
> > > > > -            setattr(self, field, kwargs.get(field, getattr(self,
> > > field)))
> > > > > -
> > > > > -    def __repr__(self):
> > > > > -        return "Url(%r)" % str(self)
> > > > > -
> > > > > -    def __str__(self):
> > > > > -        s = ""
> > > > > -        if self.scheme:
> > > > > -            s += "%s://" % self.scheme
> > > > > -        if self.user:
> > > > > -            s += self.user
> > > > > -        if self.password:
> > > > > -            s += ":%s" % self.password
> > > > > -        if self.user or self.password:
> > > > > -            s += '@'
> > > > > -        if self.host and ':' in self.host:
> > > > > -            s += "[%s]" % self.host
> > > > > -        elif self.host:
> > > > > -            s += self.host
> > > > > -        if self.port:
> > > > > -            s += ":%s" % self.port
> > > > > -        if self.path:
> > > > > -            s += "/%s" % self.path
> > > > > -        return s
> > > > > -
> > > > > -    def __eq__(self, url):
> > > > > -        return \
> > > > > -            self.scheme == url.scheme and \
> > > > > -            self.user == url.user and self.password ==
> url.password
> > > and \
> > > > > -            self.host == url.host and self.port == url.port and \
> > > > > -            self.path == url.path
> > > > > -
> > > > > -    def __ne__(self, url):
> > > > > -        return not self.__eq__(url)
> > > > > -
> > > > > -    def defaults(self):
> > > > > -        """
> > > > > -        Fill in missing values with defaults
> > > > > -        @return: self
> > > > > -        """
> > > > > -        self.scheme = self.scheme or self.AMQP
> > > > > -        self.host = self.host or '0.0.0.0'
> > > > > -        self.port = self.port or self.Port(self.scheme)
> > > > > -        return self
> > > > > +  def defaults(self):
> > > > > +    """
> > > > > +    Fill in missing values (scheme, host or port) with defaults
> > > > > +    @return: self
> > > > > +    """
> > > > > +    self.scheme = self.scheme or self.AMQP
> > > > > +    self.host = self.host or '0.0.0.0'
> > > > > +    self.port = self.port or self.Port(self.scheme)
> > > > > +    return self
> > > > >
> > > > > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> > > > > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19
> 21:00:50
> > > > > 2014
> > > > > @@ -26,8 +26,8 @@
> > > > >  #include <proton/messenger.h>
> > > > >  #include <proton/ssl.h>
> > > > >  #include <proton/driver_extras.h>
> > > > > -
> > > > >  #include <proton/types.h>
> > > > > +#include <proton/url.h>
> > > > >
> > > > >  #include <uuid/uuid.h>
> > > > >  %}
> > > > >
> > > > > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/include/proton/cproton.i (original)
> > > > > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri Sep 19
> > > > > 21:00:50 2014
> > > > > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> > > > >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return
> (pn_delivery_t
> > > *)
> > > > > x; }
> > > > >    pn_transport_t *pn_cast_pn_transport(void *x) { return
> > > (pn_transport_t
> > > > > *) x; }
> > > > >  %}
> > > > > +
> > > > > +%include "proton/url.h"
> > > > > +
> > > > >
> > > > > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > > > > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19
> 21:00:50
> > > > > 2014
> > > > > @@ -0,0 +1,83 @@
> > > > > +#ifndef PROTON_URL_H
> > > > > +#define PROTON_URL_H
> > > > > +/*
> > > > > + * 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.
> > > > > + */
> > > > > +
> > > > > +#include <proton/import_export.h>
> > > > > +
> > > > > +/** @file
> > > > > + * URL API for parsing URLs.
> > > > > + *
> > > > > + * @defgroup url URL
> > > > > + * @{
> > > > > + */
> > > > > +
> > > > > +/** A parsed URL */
> > > > > +typedef struct pn_url_t pn_url_t;
> > > > > +
> > > > > +/** Create an empty URL */
> > > > > +PN_EXTERN pn_url_t *pn_url(void);
> > > > > +
> > > > > +/** Parse a string URL as a pn_url_t.
> > > > > + *@param[in] url A URL string.
> > > > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> > > string.
> > > > > + */
> > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > > > > +
> > > > > +/** Free a URL */
> > > > > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > > > > +
> > > > > +/** Clear the contents of the URL. */
> > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > > > > +
> > > > > +/** Return the string form of a URL. Owned by the pn_url_t.*/
> > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > > > > +
> > > > > +/**
> > > > > + *@name Getters for parts of the URL.
> > > > > + *
> > > > > + *Values belong to the URL. May return NULL if the value is not
> set.
> > > > > + *
> > > > > + *@{
> > > > > + */
> > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > > > > +///@}
> > > > > +
> > > > > +/**
> > > > > + *@name Setters for parts of the URL.
> > > > > + *
> > > > > + *Values are copied. Value can be NULL to indicate the part is not
> > > set.
> > > > > + *
> > > > > + *@{
> > > > > + */
> > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> *scheme);
> > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > *username);
> > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > *password);
> > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host);
> > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port);
> > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path);
> > > > > +///@}
> > > > > +
> > > > > +///@}
> > > > > +#endif
> > > > >
> > > > > Added: qpid/proton/trunk/proton-c/src/url.c
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > > > > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50 2014
> > > > > @@ -0,0 +1,127 @@
> > > > > +/*
> > > > > + *
> > > > > + * 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.
> > > > > + *
> > > > > + */
> > > > > +
> > > > > +#include <proton/url.h>
> > > > > +#include <proton/util.h>
> > > > > +#include <stdlib.h>
> > > > > +#include <string.h>
> > > > > +#include <stdio.h>
> > > > > +
> > > > > +static char* copy(const char* str) {
> > > > > +    if (str ==  NULL) return NULL;
> > > > > +    char *str2 = (char*)malloc(strlen(str));
> > > > > +    if (str2) strcpy(str2, str);
> > > > > +    return str2;
> > > > > +}
> > > > > +
> > > > > +struct pn_url_t {
> > > > > +    char *scheme;
> > > > > +    char *username;
> > > > > +    char *password;
> > > > > +    char *host;
> > > > > +    char *port;
> > > > > +    char *path;
> > > > > +    char *str;
> > > > > +};
> > > > > +
> > > > > +PN_EXTERN pn_url_t *pn_url() {
> > > > > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > > > > +    memset(url, 0, sizeof(*url));
> > > > > +    return url;
> > > > > +}
> > > > > +
> > > > > +/** Parse a string URL as a pn_url_t.
> > > > > + *@param[in] url A URL string.
> > > > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> > > string.
> > > > > + */
> > > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > > > > +    if (!str || !*str)          /* Empty string or NULL is
> illegal. */
> > > > > +        return NULL;
> > > > > +
> > > > > +    pn_url_t *url = pn_url();
> > > > > +    char *str2 = copy(str);         /* FIXME aconway 2014-09-19:
> > > clean up
> > > > > */
> > > > > +    pni_parse_url(str2, &url->scheme, &url->username,
> &url->password,
> > > > > &url->host, &url->port, &url->path);
> > > > > +    url->scheme = copy(url->scheme);
> > > > > +    url->username = copy(url->username);
> > > > > +    url->password = copy(url->password);
> > > > > +    url->host = (url->host && !*url->host) ? NULL :
> copy(url->host);
> > > > > +    url->port = copy(url->port);
> > > > > +    url->path = copy(url->path);
> > > > > +    return url;
> > > > > +}
> > > > > +
> > > > > +/** Free a URL */
> > > > > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > > > > +    pn_url_clear(url);
> > > > > +    free(url);
> > > > > +}
> > > > > +
> > > > > +/** Clear the contents of the URL. */
> > > > > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > > > > +    pn_url_set_username(url, NULL);
> > > > > +    pn_url_set_password(url, NULL);
> > > > > +    pn_url_set_host(url, NULL);
> > > > > +    pn_url_set_port(url, NULL);
> > > > > +    pn_url_set_path(url, NULL);
> > > > > +    free(url->str); url->str = NULL;
> > > > > +}
> > > > > +
> > > > > +static inline int len(const char *str) { return str ? strlen(str)
> :
> > > 0; }
> > > > > +
> > > > > +/** Return the string form of a URL. */
> > > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > > > > +    int size = len(url->scheme) + len(url->username) +
> > > len(url->password)
> > > > > +        + len(url->host) + len(url->port) + len(url->path)
> > > > > +        + len("s://u:p@[h]:p/p");
> > > > > +    free(url->str);
> > > > > +    url->str = (char*)malloc(size);
> > > > > +    if (!url->str) return NULL;
> > > > > +
> > > > > +    int i = 0;
> > > > > +    if (url->scheme) i += snprintf(url->str+i, size-i, "%s://",
> > > > > url->scheme);
> > > > > +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> > > > > url->username);
> > > > > +    if (url->password) i += snprintf(url->str+i, size-i, ":%s",
> > > > > url->password);
> > > > > +    if (url->username || url->password) i += snprintf(url->str+i,
> > > size-i,
> > > > > "@");
> > > > > +    if (url->host) {
> > > > > +        if (strchr(url->host, ':')) i += snprintf(url->str+i,
> size-i,
> > > > > "[%s]", url->host);
> > > > > +        else i += snprintf(url->str+i, size-i, "%s", url->host);
> > > > > +    }
> > > > > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
> > > url->port);
> > > > > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
> > > url->path);
> > > > > +    return url->str;
> > > > > +}
> > > > > +
> > > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
> > > url->scheme; }
> > > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> > > > > url->username; }
> > > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> > > > > url->password; }
> > > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return
> url->host; }
> > > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return
> url->port; }
> > > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return
> url->path; }
> > > > > +
> > > > > +#define SET(part) free(url->part); url->part = copy(part)
> > > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char
> *scheme) {
> > > > > SET(scheme); }
> > > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > > *username) {
> > > > > SET(username); }
> > > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > > *password) {
> > > > > SET(password); }
> > > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host) {
> > > > > SET(host); }
> > > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port) {
> > > > > SET(port); }
> > > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path) {
> > > > > SET(path); }
> > > > > +
> > > > > +
> > > > >
> > > > > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > > URL:
> > > > >
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > > >
> > > > >
> > >
> ==============================================================================
> > > > > --- qpid/proton/trunk/tests/python/proton_tests/url.py (original)
> > > > > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep 19
> > > 21:00:50
> > > > > 2014
> > > > > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> > > > >      def assertNotEqual(self, a, b):
> > > > >          assert a != b, "%s == %s" % (a, b)
> > > > >
> > > > > -    def assertUrl(self, u, scheme, user, password, host, port,
> path):
> > > > > -        self.assertEqual((u.scheme, u.user, u.password, u.host,
> > > u.port,
> > > > > u.path),
> > > > > -                         (scheme, user, password, host, port,
> path))
> > > > > +    def assertUrl(self, u, scheme, username, password, host, port,
> > > path):
> > > > > +        self.assertEqual((u.scheme, u.username, u.password,
> u.host,
> > > > > u.port, u.path),
> > > > > +                         (scheme, username, password, host, port,
> > > path))
> > > > >
> > > > >      def testUrl(self):
> > > > >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > > > > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> > > > >
> > > > >      def testDefaults(self):
> > > > >          # Check that we allow None for scheme, port
> > > > > -        url = Url(user='me', password='secret', host='myhost',
> > > > > path='foobar')
> > > > > +        url = Url(username='me', password='secret', host='myhost',
> > > > > path='foobar')
> > > > >          self.assertEqual(str(url), "me:secret@myhost/foobar")
> > > > >          self.assertUrl(url, None, 'me', 'secret', 'myhost', None,
> > > > > 'foobar')
> > > > >
> > > > > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> > > > >      def testMissing(self):
> > > > >          self.assertUrl(Url(), None, None, None, None, None, None)
> > > > >          self.assertUrl(Url('amqp://'), 'amqp', None, None, None,
> None,
> > > > > None)
> > > > > -        self.assertUrl(Url('user@'), None, 'user', None, None,
> None,
> > > > > None)
> > > > > +        self.assertUrl(Url('username@'), None, 'username', None,
> > > None,
> > > > > None, None)
> > > > >          self.assertUrl(Url(':pass@'), None, '', 'pass', None,
> None,
> > > None)
> > > > >          self.assertUrl(Url('host'), None, None, None, 'host',
> None,
> > > None)
> > > > >          self.assertUrl(Url(':1234'), None, None, None, None, 1234,
> > > None)
> > > > >          self.assertUrl(Url('/path'), None, None, None, None, None,
> > > 'path')
> > > > >
> > > > > -        for s in ['amqp://', 'user@', ':pass@', ':1234',
> '/path']:
> > > > > +        for s in ['amqp://', 'username@', ':pass@', ':1234',
> > > '/path']:
> > > > >              self.assertEqual(s, str(Url(s)))
> > > > >
> > > > >          for s, full in [
> > > > >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > > > > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > > > > +                ('username@', 'amqp://username@0.0.0.0:amqp'),
> > > > >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> > > > >                  (':1234', 'amqp://0.0.0.0:1234'),
> > > > >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> > > > >              self.assertEqual(str(Url(s).defaults()), full)
> > > > > -
> > > > > -        self.assertRaises(ValueError, Url, '')
> > > > >
> > > > >
> > > > >
> > > > >
> ---------------------------------------------------------------------
> > > > > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > > > > For additional commands, e-mail: commits-help@qpid.apache.org
> > > > >
> > > > >
> > >
> > >
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > > For additional commands, e-mail: dev-help@qpid.apache.org
> > >
> > >
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> For additional commands, e-mail: dev-help@qpid.apache.org
>
>

Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Alan Conway <ac...@redhat.com>.
On Wed, 2014-09-24 at 12:19 +0100, Robbie Gemmell wrote:
> The tests are now running again, but a couple of the URL tests still seem
> to be failing on the CI job:
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/
> 

They are all failing with:
 Not a valid port number or service name: 'amqps'

Could this be a configuration problem on the CI machine, i.e. missing an
'amqps' entry in /etc/services? Can I get access to the CI machine to
poke around and see what's up?

The URL code uses socket.getservbyname() to look up service names. Is
there a more portable way to do it?

Cheers,
Alan.

> As mentioned in my other post about a timeline for dropping Java6 support,
> they seem to work on Java8 (havent tried Java7).
> 
> Robbie
> 
> On 22 September 2014 21:14, Alan Conway <ac...@redhat.com> wrote:
> 
> > My bad, didn't run the java tests. Will fix ASAP and then give myself a
> > flogging.
> >
> > On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> > > This seems to have broken the Java test runs:
> > >
> > > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> > >
> > >
> > >
> > > On 19 September 2014 22:00, <ac...@apache.org> wrote:
> > >
> > > > Author: aconway
> > > > Date: Fri Sep 19 21:00:50 2014
> > > > New Revision: 1626329
> > > >
> > > > URL: http://svn.apache.org/r1626329
> > > > Log:
> > > > PROTON-693: Python Url class to wrap C function pni_parse_url
> > > >
> > > > It was pointed out that pni_parse_url is an internal function and the
> > > > interface
> > > > is not suitable for public API.
> > > >
> > > > Rewrote the URL parser as a proper swigable C API pn_url_*. This gets
> > rid
> > > > of the
> > > > need for previous swig insanity and is cleaner all round.
> > > >
> > > > Internally still uses the pni_parse_url parser, we can clean that up
> > later.
> > > >
> > > > Added:
> > > >     qpid/proton/trunk/proton-c/include/proton/url.h
> > > >     qpid/proton/trunk/proton-c/src/url.c
> > > > Modified:
> > > >     qpid/proton/trunk/proton-c/CMakeLists.txt
> > > >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > >     qpid/proton/trunk/proton-c/bindings/php/php.i
> > > >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > >     qpid/proton/trunk/tests/python/proton_tests/url.py
> > > >
> > > > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > > > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19 21:00:50 2014
> > > > @@ -270,6 +270,7 @@ set (qpid-proton-core
> > > >    src/object/iterator.c
> > > >
> > > >    src/util.c
> > > > +  src/url.c
> > > >    src/error.c
> > > >    src/buffer.c
> > > >    src/parser.c
> > > >
> > > > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> > > > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19 21:00:50
> > > > 2014
> > > > @@ -8,6 +8,7 @@
> > > >  #include <proton/messenger.h>
> > > >  #include <proton/ssl.h>
> > > >  #include <proton/driver_extras.h>
> > > > +#include <proton/url.h>
> > > >  %}
> > > >
> > > >  %include <cstring.i>
> > > >
> > > > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > > > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19 21:00:50
> > 2014
> > > > @@ -29,6 +29,7 @@
> > > >  %header %{
> > > >  /* Include the headers needed by the code in this wrapper file */
> > > >  #include <proton/types.h>
> > > > +#include <proton/url.h>
> > > >  #include <proton/message.h>
> > > >  #include <proton/driver.h>
> > > >  #include <proton/driver_extras.h>
> > > >
> > > > Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i (original)
> > > > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri Sep 19
> > > > 21:00:50 2014
> > > > @@ -23,6 +23,7 @@
> > > >  #include <winsock2.h>
> > > >  #endif
> > > >  #include <proton/engine.h>
> > > > +#include <proton/url.h>
> > > >  #include <proton/message.h>
> > > >  #include <proton/sasl.h>
> > > >  #include <proton/driver.h>
> > > > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> > > >    }
> > > >  %}
> > > >
> > > > -
> > > > -/**
> > > > -   pni_parse_url(char* url, char **scheme, char **user, char **pass,
> > char
> > > > **host, char **port, char **path)
> > > > -   The following type maps convert this into a python function that
> > taks
> > > > a URL string argument
> > > > -   and returns a list of strings [scheme, user, pass, host, port,
> > path]
> > > > -   This probably could be done more neatly.
> > > > -*/
> > > > -
> > > > -// Typemap to copy the url string as it will be modified by parse_url
> > > > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char *url (int
> > > > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > > > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > > > -  if (!SWIG_IsOK(res)) {
> > > > -    %argument_fail(res, "char *url", $symname, $argnum);
> > > > -  }
> > > > -  $1 = %new_array(n, $*1_ltype);
> > > > -  memcpy($1,t,sizeof(char)*n);
> > > > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > > > -  $1[n-1] = 0;
> > > > -}
> > > > -%typemap(freearg,match="in") char *url "free($1);";
> > > > -%typemap(argout) char *url "";
> > > > -
> > > > -// Typemap for char** return strings. Don't free them.
> > > > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0) "$1 =
> > &temp;";
> > > > -%typemap(freearg,match="in") char **OUTSTR "";
> > > > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char **OUTSTR {
> > > > -    %append_output(SWIG_FromCharPtr(*$1));
> > > > -}
> > > > -
> > > > -// Typemap to initialize result as empty list
> > > > -%typemap(out) void "$result = PyList_New(0);";
> > > > -
> > > > -
> > > > -%apply char** OUTSTR {char **scheme, char **user, char **pass, char
> > > > **host, char **port, char **path};
> > > > -void pni_parse_url(char* url, char **scheme, char **user, char **pass,
> > > > char **host, char **port, char **path);
> > > > -%ignore pni_parse_url;
> > > > -
> > > >  %include "proton/cproton.i"
> > > >
> > > > Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
> > > > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri Sep 19
> > > > 21:00:50 2014
> > > > @@ -3657,114 +3657,98 @@ __all__ = [
> > > >
> > > >
> > > >  class Url(object):
> > > > -    """
> > > > -    Simple URL parser/constructor, handles URLs of the form:
> > > > +  """
> > > > +  Simple URL parser/constructor, handles URLs of the form:
> > > >
> > > > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> > > >
> > > > -    All components can be None if not specifeid in the URL string.
> > > > +  All components can be None if not specifeid in the URL string.
> > > >
> > > > -    The port can be specified as a service name, e.g. 'amqp' in the
> > > > -    URL string but Url.port always gives the integer value.
> > > > +  The port can be specified as a service name, e.g. 'amqp' in the
> > > > +  URL string but Url.port always gives the integer value.
> > > > +
> > > > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > +  @ivar user: Username
> > > > +  @ivar password: Password
> > > > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > +  @ivar port: Integer port.
> > > > +  @ivar host_port: Returns host:port
> > > > +  """
> > > > +
> > > > +  AMQPS = "amqps"
> > > > +  AMQP = "amqp"
> > > > +
> > > > +  class Port(int):
> > > > +    """An integer port number that can be constructed from a service
> > name
> > > > string"""
> > > > +
> > > > +    def __new__(cls, value):
> > > > +      port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
> > > > +      setattr(port, 'name', str(value))
> > > > +      return port
> > > > +
> > > > +    def __eq__(self, x): return str(self) == x or int(self) == x
> > > > +    def __ne__(self, x): return not self == x
> > > > +    def __str__(self): return str(self.name)
> > > > +
> > > > +    @staticmethod
> > > > +    def port_int(value):
> > > > +      """Convert service, an integer or a service name, into an
> > integer
> > > > port number."""
> > > > +      try:
> > > > +        return int(value)
> > > > +      except ValueError:
> > > > +        try:
> > > > +          return socket.getservbyname(value)
> > > > +        except socket.error:
> > > > +          raise ValueError("Not a valid port number or service name:
> > > > '%s'" % value)
> > > >
> > > > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > -    @ivar user: Username
> > > > -    @ivar password: Password
> > > > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > -    @ivar port: Integer port.
> > > > -    @ivar host_port: Returns host:port
> > > > +  def __init__(self, url=None, **kwargs):
> > > > +    """
> > > > +    @param url: URL string to parse.
> > > > +    @param kwargs: scheme, user, password, host, port, path.
> > > > +      If specified, replaces corresponding part in url string.
> > > >      """
> > > > +    if url:
> > > > +      self._url = pn_url_parse(str(url))
> > > > +      if not self._url: raise ValueError("Invalid URL '%s'" % url)
> > > > +    else:
> > > > +      self._url = pn_url()
> > > > +    for k in kwargs:            # Let kwargs override values parsed
> > from
> > > > url
> > > > +      getattr(self, k)          # Check for invalid kwargs
> > > > +      setattr(self, k, kwargs[k])
> > > > +
> > > > +  class PartDescriptor(object):
> > > > +    def __init__(self, part):
> > > > +      self.getter = globals()["pn_url_%s" % part]
> > > > +      self.setter = globals()["pn_url_set_%s" % part]
> > > > +    def __get__(self, obj, type=None): return self.getter(obj._url)
> > > > +    def __set__(self, obj, value): return self.setter(obj._url,
> > > > str(value))
> > > > +
> > > > +  scheme = PartDescriptor('scheme')
> > > > +  username = PartDescriptor('username')
> > > > +  password = PartDescriptor('password')
> > > > +  host = PartDescriptor('host')
> > > > +  path = PartDescriptor('path')
> > > > +
> > > > +  @property
> > > > +  def port(self):
> > > > +    portstr = pn_url_port(self._url)
> > > > +    return portstr and Url.Port(portstr)
> > > > +
> > > > +  @port.setter
> > > > +  def port(self, value):
> > > > +    if value is None: pn_url_set_port(self._url, None)
> > > > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> > > >
> > > > -    AMQPS = "amqps"
> > > > -    AMQP = "amqp"
> > > > +  def __str__(self): return pn_url_str(self._url)
> > > >
> > > > -    class Port(int):
> > > > -      """An integer port number that can also have an associated
> > service
> > > > name string"""
> > > > +  def __repr__(self): return "Url(%r)" % str(self)
> > > >
> > > > -      def __new__(cls, value):
> > > > -        port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
> > > > -        setattr(port, 'name', str(value))
> > > > -        return port
> > > > -
> > > > -      def __eq__(self, x): return str(self) == x or int(self) == x
> > > > -      def __ne__(self, x): return not self == x
> > > > -      def __str__(self): return str(self.name)
> > > > -
> > > > -      @staticmethod
> > > > -      def port_int(value):
> > > > -        """Convert service, an integer or a service name, into an
> > integer
> > > > port number."""
> > > > -        try:
> > > > -          return int(value)
> > > > -        except ValueError:
> > > > -          try:
> > > > -            return socket.getservbyname(value)
> > > > -          except socket.error:
> > > > -            raise ValueError("Not a valid port number or service name:
> > > > '%s'" % value)
> > > > -
> > > > -    def __init__(self, url=None, **kwargs):
> > > > -        """
> > > > -        @param url: String or Url instance to parse or copy.
> > > > -        @param kwargs: URL fields: scheme, user, password, host, port,
> > > > path.
> > > > -            If specified, replaces corresponding component in url.
> > > > -        """
> > > > -
> > > > -        fields = ['scheme', 'user', 'password', 'host', 'port',
> > 'path']
> > > > -
> > > > -        for f in fields: setattr(self, f, None)
> > > > -        for k in kwargs: getattr(self, k) # Check for invalid kwargs
> > > > -
> > > > -        if isinstance(url, Url): # Copy from another Url instance.
> > > > -            self.__dict__.update(url.__dict__)
> > > > -        elif url is not None:   # Parse from url
> > > > -            parts = pni_parse_url(str(url))
> > > > -            if not filter(None, parts): raise ValueError("Invalid AMQP
> > > > URL: '%s'" % url)
> > > > -            self.scheme, self.user, self.password, self.host, port,
> > > > self.path = parts
> > > > -            if not self.host: self.host = None
> > > > -            self.port = port and self.Port(port)
> > > > -
> > > > -        # Let kwargs override values previously set from url
> > > > -        for field in fields:
> > > > -            setattr(self, field, kwargs.get(field, getattr(self,
> > field)))
> > > > -
> > > > -    def __repr__(self):
> > > > -        return "Url(%r)" % str(self)
> > > > -
> > > > -    def __str__(self):
> > > > -        s = ""
> > > > -        if self.scheme:
> > > > -            s += "%s://" % self.scheme
> > > > -        if self.user:
> > > > -            s += self.user
> > > > -        if self.password:
> > > > -            s += ":%s" % self.password
> > > > -        if self.user or self.password:
> > > > -            s += '@'
> > > > -        if self.host and ':' in self.host:
> > > > -            s += "[%s]" % self.host
> > > > -        elif self.host:
> > > > -            s += self.host
> > > > -        if self.port:
> > > > -            s += ":%s" % self.port
> > > > -        if self.path:
> > > > -            s += "/%s" % self.path
> > > > -        return s
> > > > -
> > > > -    def __eq__(self, url):
> > > > -        return \
> > > > -            self.scheme == url.scheme and \
> > > > -            self.user == url.user and self.password == url.password
> > and \
> > > > -            self.host == url.host and self.port == url.port and \
> > > > -            self.path == url.path
> > > > -
> > > > -    def __ne__(self, url):
> > > > -        return not self.__eq__(url)
> > > > -
> > > > -    def defaults(self):
> > > > -        """
> > > > -        Fill in missing values with defaults
> > > > -        @return: self
> > > > -        """
> > > > -        self.scheme = self.scheme or self.AMQP
> > > > -        self.host = self.host or '0.0.0.0'
> > > > -        self.port = self.port or self.Port(self.scheme)
> > > > -        return self
> > > > +  def defaults(self):
> > > > +    """
> > > > +    Fill in missing values (scheme, host or port) with defaults
> > > > +    @return: self
> > > > +    """
> > > > +    self.scheme = self.scheme or self.AMQP
> > > > +    self.host = self.host or '0.0.0.0'
> > > > +    self.port = self.port or self.Port(self.scheme)
> > > > +    return self
> > > >
> > > > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> > > > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19 21:00:50
> > > > 2014
> > > > @@ -26,8 +26,8 @@
> > > >  #include <proton/messenger.h>
> > > >  #include <proton/ssl.h>
> > > >  #include <proton/driver_extras.h>
> > > > -
> > > >  #include <proton/types.h>
> > > > +#include <proton/url.h>
> > > >
> > > >  #include <uuid/uuid.h>
> > > >  %}
> > > >
> > > > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/include/proton/cproton.i (original)
> > > > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri Sep 19
> > > > 21:00:50 2014
> > > > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> > > >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return (pn_delivery_t
> > *)
> > > > x; }
> > > >    pn_transport_t *pn_cast_pn_transport(void *x) { return
> > (pn_transport_t
> > > > *) x; }
> > > >  %}
> > > > +
> > > > +%include "proton/url.h"
> > > > +
> > > >
> > > > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > > > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19 21:00:50
> > > > 2014
> > > > @@ -0,0 +1,83 @@
> > > > +#ifndef PROTON_URL_H
> > > > +#define PROTON_URL_H
> > > > +/*
> > > > + * 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.
> > > > + */
> > > > +
> > > > +#include <proton/import_export.h>
> > > > +
> > > > +/** @file
> > > > + * URL API for parsing URLs.
> > > > + *
> > > > + * @defgroup url URL
> > > > + * @{
> > > > + */
> > > > +
> > > > +/** A parsed URL */
> > > > +typedef struct pn_url_t pn_url_t;
> > > > +
> > > > +/** Create an empty URL */
> > > > +PN_EXTERN pn_url_t *pn_url(void);
> > > > +
> > > > +/** Parse a string URL as a pn_url_t.
> > > > + *@param[in] url A URL string.
> > > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> > string.
> > > > + */
> > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > > > +
> > > > +/** Free a URL */
> > > > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > > > +
> > > > +/** Clear the contents of the URL. */
> > > > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > > > +
> > > > +/** Return the string form of a URL. Owned by the pn_url_t.*/
> > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > > > +
> > > > +/**
> > > > + *@name Getters for parts of the URL.
> > > > + *
> > > > + *Values belong to the URL. May return NULL if the value is not set.
> > > > + *
> > > > + *@{
> > > > + */
> > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > > > +///@}
> > > > +
> > > > +/**
> > > > + *@name Setters for parts of the URL.
> > > > + *
> > > > + *Values are copied. Value can be NULL to indicate the part is not
> > set.
> > > > + *
> > > > + *@{
> > > > + */
> > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme);
> > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > *username);
> > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > *password);
> > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host);
> > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port);
> > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path);
> > > > +///@}
> > > > +
> > > > +///@}
> > > > +#endif
> > > >
> > > > Added: qpid/proton/trunk/proton-c/src/url.c
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > > > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50 2014
> > > > @@ -0,0 +1,127 @@
> > > > +/*
> > > > + *
> > > > + * 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.
> > > > + *
> > > > + */
> > > > +
> > > > +#include <proton/url.h>
> > > > +#include <proton/util.h>
> > > > +#include <stdlib.h>
> > > > +#include <string.h>
> > > > +#include <stdio.h>
> > > > +
> > > > +static char* copy(const char* str) {
> > > > +    if (str ==  NULL) return NULL;
> > > > +    char *str2 = (char*)malloc(strlen(str));
> > > > +    if (str2) strcpy(str2, str);
> > > > +    return str2;
> > > > +}
> > > > +
> > > > +struct pn_url_t {
> > > > +    char *scheme;
> > > > +    char *username;
> > > > +    char *password;
> > > > +    char *host;
> > > > +    char *port;
> > > > +    char *path;
> > > > +    char *str;
> > > > +};
> > > > +
> > > > +PN_EXTERN pn_url_t *pn_url() {
> > > > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > > > +    memset(url, 0, sizeof(*url));
> > > > +    return url;
> > > > +}
> > > > +
> > > > +/** Parse a string URL as a pn_url_t.
> > > > + *@param[in] url A URL string.
> > > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> > string.
> > > > + */
> > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > > > +    if (!str || !*str)          /* Empty string or NULL is illegal. */
> > > > +        return NULL;
> > > > +
> > > > +    pn_url_t *url = pn_url();
> > > > +    char *str2 = copy(str);         /* FIXME aconway 2014-09-19:
> > clean up
> > > > */
> > > > +    pni_parse_url(str2, &url->scheme, &url->username, &url->password,
> > > > &url->host, &url->port, &url->path);
> > > > +    url->scheme = copy(url->scheme);
> > > > +    url->username = copy(url->username);
> > > > +    url->password = copy(url->password);
> > > > +    url->host = (url->host && !*url->host) ? NULL : copy(url->host);
> > > > +    url->port = copy(url->port);
> > > > +    url->path = copy(url->path);
> > > > +    return url;
> > > > +}
> > > > +
> > > > +/** Free a URL */
> > > > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > > > +    pn_url_clear(url);
> > > > +    free(url);
> > > > +}
> > > > +
> > > > +/** Clear the contents of the URL. */
> > > > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > > > +    pn_url_set_username(url, NULL);
> > > > +    pn_url_set_password(url, NULL);
> > > > +    pn_url_set_host(url, NULL);
> > > > +    pn_url_set_port(url, NULL);
> > > > +    pn_url_set_path(url, NULL);
> > > > +    free(url->str); url->str = NULL;
> > > > +}
> > > > +
> > > > +static inline int len(const char *str) { return str ? strlen(str) :
> > 0; }
> > > > +
> > > > +/** Return the string form of a URL. */
> > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > > > +    int size = len(url->scheme) + len(url->username) +
> > len(url->password)
> > > > +        + len(url->host) + len(url->port) + len(url->path)
> > > > +        + len("s://u:p@[h]:p/p");
> > > > +    free(url->str);
> > > > +    url->str = (char*)malloc(size);
> > > > +    if (!url->str) return NULL;
> > > > +
> > > > +    int i = 0;
> > > > +    if (url->scheme) i += snprintf(url->str+i, size-i, "%s://",
> > > > url->scheme);
> > > > +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> > > > url->username);
> > > > +    if (url->password) i += snprintf(url->str+i, size-i, ":%s",
> > > > url->password);
> > > > +    if (url->username || url->password) i += snprintf(url->str+i,
> > size-i,
> > > > "@");
> > > > +    if (url->host) {
> > > > +        if (strchr(url->host, ':')) i += snprintf(url->str+i, size-i,
> > > > "[%s]", url->host);
> > > > +        else i += snprintf(url->str+i, size-i, "%s", url->host);
> > > > +    }
> > > > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
> > url->port);
> > > > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
> > url->path);
> > > > +    return url->str;
> > > > +}
> > > > +
> > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
> > url->scheme; }
> > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> > > > url->username; }
> > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> > > > url->password; }
> > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return url->host; }
> > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return url->port; }
> > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return url->path; }
> > > > +
> > > > +#define SET(part) free(url->part); url->part = copy(part)
> > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme) {
> > > > SET(scheme); }
> > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > *username) {
> > > > SET(username); }
> > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > *password) {
> > > > SET(password); }
> > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host) {
> > > > SET(host); }
> > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port) {
> > > > SET(port); }
> > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path) {
> > > > SET(path); }
> > > > +
> > > > +
> > > >
> > > > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/tests/python/proton_tests/url.py (original)
> > > > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep 19
> > 21:00:50
> > > > 2014
> > > > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> > > >      def assertNotEqual(self, a, b):
> > > >          assert a != b, "%s == %s" % (a, b)
> > > >
> > > > -    def assertUrl(self, u, scheme, user, password, host, port, path):
> > > > -        self.assertEqual((u.scheme, u.user, u.password, u.host,
> > u.port,
> > > > u.path),
> > > > -                         (scheme, user, password, host, port, path))
> > > > +    def assertUrl(self, u, scheme, username, password, host, port,
> > path):
> > > > +        self.assertEqual((u.scheme, u.username, u.password, u.host,
> > > > u.port, u.path),
> > > > +                         (scheme, username, password, host, port,
> > path))
> > > >
> > > >      def testUrl(self):
> > > >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > > > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> > > >
> > > >      def testDefaults(self):
> > > >          # Check that we allow None for scheme, port
> > > > -        url = Url(user='me', password='secret', host='myhost',
> > > > path='foobar')
> > > > +        url = Url(username='me', password='secret', host='myhost',
> > > > path='foobar')
> > > >          self.assertEqual(str(url), "me:secret@myhost/foobar")
> > > >          self.assertUrl(url, None, 'me', 'secret', 'myhost', None,
> > > > 'foobar')
> > > >
> > > > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> > > >      def testMissing(self):
> > > >          self.assertUrl(Url(), None, None, None, None, None, None)
> > > >          self.assertUrl(Url('amqp://'), 'amqp', None, None, None, None,
> > > > None)
> > > > -        self.assertUrl(Url('user@'), None, 'user', None, None, None,
> > > > None)
> > > > +        self.assertUrl(Url('username@'), None, 'username', None,
> > None,
> > > > None, None)
> > > >          self.assertUrl(Url(':pass@'), None, '', 'pass', None, None,
> > None)
> > > >          self.assertUrl(Url('host'), None, None, None, 'host', None,
> > None)
> > > >          self.assertUrl(Url(':1234'), None, None, None, None, 1234,
> > None)
> > > >          self.assertUrl(Url('/path'), None, None, None, None, None,
> > 'path')
> > > >
> > > > -        for s in ['amqp://', 'user@', ':pass@', ':1234', '/path']:
> > > > +        for s in ['amqp://', 'username@', ':pass@', ':1234',
> > '/path']:
> > > >              self.assertEqual(s, str(Url(s)))
> > > >
> > > >          for s, full in [
> > > >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > > > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > > > +                ('username@', 'amqp://username@0.0.0.0:amqp'),
> > > >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> > > >                  (':1234', 'amqp://0.0.0.0:1234'),
> > > >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> > > >              self.assertEqual(str(Url(s).defaults()), full)
> > > > -
> > > > -        self.assertRaises(ValueError, Url, '')
> > > >
> > > >
> > > >
> > > > ---------------------------------------------------------------------
> > > > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > > > For additional commands, e-mail: commits-help@qpid.apache.org
> > > >
> > > >
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > For additional commands, e-mail: dev-help@qpid.apache.org
> >
> >



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
For additional commands, e-mail: dev-help@qpid.apache.org


Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Alan Conway <ac...@redhat.com>.
On Wed, 2014-09-24 at 12:19 +0100, Robbie Gemmell wrote:
> The tests are now running again, but a couple of the URL tests still seem
> to be failing on the CI job:
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/
> 

They are all failing with:
 Not a valid port number or service name: 'amqps'

Could this be a configuration problem on the CI machine, i.e. missing an
'amqps' entry in /etc/services? Can I get access to the CI machine to
poke around and see what's up?

The URL code uses socket.getservbyname() to look up service names. Is
there a more portable way to do it?

Cheers,
Alan.

> As mentioned in my other post about a timeline for dropping Java6 support,
> they seem to work on Java8 (havent tried Java7).
> 
> Robbie
> 
> On 22 September 2014 21:14, Alan Conway <ac...@redhat.com> wrote:
> 
> > My bad, didn't run the java tests. Will fix ASAP and then give myself a
> > flogging.
> >
> > On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> > > This seems to have broken the Java test runs:
> > >
> > > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> > >
> > >
> > >
> > > On 19 September 2014 22:00, <ac...@apache.org> wrote:
> > >
> > > > Author: aconway
> > > > Date: Fri Sep 19 21:00:50 2014
> > > > New Revision: 1626329
> > > >
> > > > URL: http://svn.apache.org/r1626329
> > > > Log:
> > > > PROTON-693: Python Url class to wrap C function pni_parse_url
> > > >
> > > > It was pointed out that pni_parse_url is an internal function and the
> > > > interface
> > > > is not suitable for public API.
> > > >
> > > > Rewrote the URL parser as a proper swigable C API pn_url_*. This gets
> > rid
> > > > of the
> > > > need for previous swig insanity and is cleaner all round.
> > > >
> > > > Internally still uses the pni_parse_url parser, we can clean that up
> > later.
> > > >
> > > > Added:
> > > >     qpid/proton/trunk/proton-c/include/proton/url.h
> > > >     qpid/proton/trunk/proton-c/src/url.c
> > > > Modified:
> > > >     qpid/proton/trunk/proton-c/CMakeLists.txt
> > > >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > >     qpid/proton/trunk/proton-c/bindings/php/php.i
> > > >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > >     qpid/proton/trunk/tests/python/proton_tests/url.py
> > > >
> > > > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > > > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19 21:00:50 2014
> > > > @@ -270,6 +270,7 @@ set (qpid-proton-core
> > > >    src/object/iterator.c
> > > >
> > > >    src/util.c
> > > > +  src/url.c
> > > >    src/error.c
> > > >    src/buffer.c
> > > >    src/parser.c
> > > >
> > > > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> > > > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19 21:00:50
> > > > 2014
> > > > @@ -8,6 +8,7 @@
> > > >  #include <proton/messenger.h>
> > > >  #include <proton/ssl.h>
> > > >  #include <proton/driver_extras.h>
> > > > +#include <proton/url.h>
> > > >  %}
> > > >
> > > >  %include <cstring.i>
> > > >
> > > > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > > > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19 21:00:50
> > 2014
> > > > @@ -29,6 +29,7 @@
> > > >  %header %{
> > > >  /* Include the headers needed by the code in this wrapper file */
> > > >  #include <proton/types.h>
> > > > +#include <proton/url.h>
> > > >  #include <proton/message.h>
> > > >  #include <proton/driver.h>
> > > >  #include <proton/driver_extras.h>
> > > >
> > > > Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i (original)
> > > > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri Sep 19
> > > > 21:00:50 2014
> > > > @@ -23,6 +23,7 @@
> > > >  #include <winsock2.h>
> > > >  #endif
> > > >  #include <proton/engine.h>
> > > > +#include <proton/url.h>
> > > >  #include <proton/message.h>
> > > >  #include <proton/sasl.h>
> > > >  #include <proton/driver.h>
> > > > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> > > >    }
> > > >  %}
> > > >
> > > > -
> > > > -/**
> > > > -   pni_parse_url(char* url, char **scheme, char **user, char **pass,
> > char
> > > > **host, char **port, char **path)
> > > > -   The following type maps convert this into a python function that
> > taks
> > > > a URL string argument
> > > > -   and returns a list of strings [scheme, user, pass, host, port,
> > path]
> > > > -   This probably could be done more neatly.
> > > > -*/
> > > > -
> > > > -// Typemap to copy the url string as it will be modified by parse_url
> > > > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char *url (int
> > > > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > > > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > > > -  if (!SWIG_IsOK(res)) {
> > > > -    %argument_fail(res, "char *url", $symname, $argnum);
> > > > -  }
> > > > -  $1 = %new_array(n, $*1_ltype);
> > > > -  memcpy($1,t,sizeof(char)*n);
> > > > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > > > -  $1[n-1] = 0;
> > > > -}
> > > > -%typemap(freearg,match="in") char *url "free($1);";
> > > > -%typemap(argout) char *url "";
> > > > -
> > > > -// Typemap for char** return strings. Don't free them.
> > > > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0) "$1 =
> > &temp;";
> > > > -%typemap(freearg,match="in") char **OUTSTR "";
> > > > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char **OUTSTR {
> > > > -    %append_output(SWIG_FromCharPtr(*$1));
> > > > -}
> > > > -
> > > > -// Typemap to initialize result as empty list
> > > > -%typemap(out) void "$result = PyList_New(0);";
> > > > -
> > > > -
> > > > -%apply char** OUTSTR {char **scheme, char **user, char **pass, char
> > > > **host, char **port, char **path};
> > > > -void pni_parse_url(char* url, char **scheme, char **user, char **pass,
> > > > char **host, char **port, char **path);
> > > > -%ignore pni_parse_url;
> > > > -
> > > >  %include "proton/cproton.i"
> > > >
> > > > Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
> > > > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri Sep 19
> > > > 21:00:50 2014
> > > > @@ -3657,114 +3657,98 @@ __all__ = [
> > > >
> > > >
> > > >  class Url(object):
> > > > -    """
> > > > -    Simple URL parser/constructor, handles URLs of the form:
> > > > +  """
> > > > +  Simple URL parser/constructor, handles URLs of the form:
> > > >
> > > > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > > > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> > > >
> > > > -    All components can be None if not specifeid in the URL string.
> > > > +  All components can be None if not specifeid in the URL string.
> > > >
> > > > -    The port can be specified as a service name, e.g. 'amqp' in the
> > > > -    URL string but Url.port always gives the integer value.
> > > > +  The port can be specified as a service name, e.g. 'amqp' in the
> > > > +  URL string but Url.port always gives the integer value.
> > > > +
> > > > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > +  @ivar user: Username
> > > > +  @ivar password: Password
> > > > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > +  @ivar port: Integer port.
> > > > +  @ivar host_port: Returns host:port
> > > > +  """
> > > > +
> > > > +  AMQPS = "amqps"
> > > > +  AMQP = "amqp"
> > > > +
> > > > +  class Port(int):
> > > > +    """An integer port number that can be constructed from a service
> > name
> > > > string"""
> > > > +
> > > > +    def __new__(cls, value):
> > > > +      port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
> > > > +      setattr(port, 'name', str(value))
> > > > +      return port
> > > > +
> > > > +    def __eq__(self, x): return str(self) == x or int(self) == x
> > > > +    def __ne__(self, x): return not self == x
> > > > +    def __str__(self): return str(self.name)
> > > > +
> > > > +    @staticmethod
> > > > +    def port_int(value):
> > > > +      """Convert service, an integer or a service name, into an
> > integer
> > > > port number."""
> > > > +      try:
> > > > +        return int(value)
> > > > +      except ValueError:
> > > > +        try:
> > > > +          return socket.getservbyname(value)
> > > > +        except socket.error:
> > > > +          raise ValueError("Not a valid port number or service name:
> > > > '%s'" % value)
> > > >
> > > > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > > -    @ivar user: Username
> > > > -    @ivar password: Password
> > > > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > > -    @ivar port: Integer port.
> > > > -    @ivar host_port: Returns host:port
> > > > +  def __init__(self, url=None, **kwargs):
> > > > +    """
> > > > +    @param url: URL string to parse.
> > > > +    @param kwargs: scheme, user, password, host, port, path.
> > > > +      If specified, replaces corresponding part in url string.
> > > >      """
> > > > +    if url:
> > > > +      self._url = pn_url_parse(str(url))
> > > > +      if not self._url: raise ValueError("Invalid URL '%s'" % url)
> > > > +    else:
> > > > +      self._url = pn_url()
> > > > +    for k in kwargs:            # Let kwargs override values parsed
> > from
> > > > url
> > > > +      getattr(self, k)          # Check for invalid kwargs
> > > > +      setattr(self, k, kwargs[k])
> > > > +
> > > > +  class PartDescriptor(object):
> > > > +    def __init__(self, part):
> > > > +      self.getter = globals()["pn_url_%s" % part]
> > > > +      self.setter = globals()["pn_url_set_%s" % part]
> > > > +    def __get__(self, obj, type=None): return self.getter(obj._url)
> > > > +    def __set__(self, obj, value): return self.setter(obj._url,
> > > > str(value))
> > > > +
> > > > +  scheme = PartDescriptor('scheme')
> > > > +  username = PartDescriptor('username')
> > > > +  password = PartDescriptor('password')
> > > > +  host = PartDescriptor('host')
> > > > +  path = PartDescriptor('path')
> > > > +
> > > > +  @property
> > > > +  def port(self):
> > > > +    portstr = pn_url_port(self._url)
> > > > +    return portstr and Url.Port(portstr)
> > > > +
> > > > +  @port.setter
> > > > +  def port(self, value):
> > > > +    if value is None: pn_url_set_port(self._url, None)
> > > > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> > > >
> > > > -    AMQPS = "amqps"
> > > > -    AMQP = "amqp"
> > > > +  def __str__(self): return pn_url_str(self._url)
> > > >
> > > > -    class Port(int):
> > > > -      """An integer port number that can also have an associated
> > service
> > > > name string"""
> > > > +  def __repr__(self): return "Url(%r)" % str(self)
> > > >
> > > > -      def __new__(cls, value):
> > > > -        port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
> > > > -        setattr(port, 'name', str(value))
> > > > -        return port
> > > > -
> > > > -      def __eq__(self, x): return str(self) == x or int(self) == x
> > > > -      def __ne__(self, x): return not self == x
> > > > -      def __str__(self): return str(self.name)
> > > > -
> > > > -      @staticmethod
> > > > -      def port_int(value):
> > > > -        """Convert service, an integer or a service name, into an
> > integer
> > > > port number."""
> > > > -        try:
> > > > -          return int(value)
> > > > -        except ValueError:
> > > > -          try:
> > > > -            return socket.getservbyname(value)
> > > > -          except socket.error:
> > > > -            raise ValueError("Not a valid port number or service name:
> > > > '%s'" % value)
> > > > -
> > > > -    def __init__(self, url=None, **kwargs):
> > > > -        """
> > > > -        @param url: String or Url instance to parse or copy.
> > > > -        @param kwargs: URL fields: scheme, user, password, host, port,
> > > > path.
> > > > -            If specified, replaces corresponding component in url.
> > > > -        """
> > > > -
> > > > -        fields = ['scheme', 'user', 'password', 'host', 'port',
> > 'path']
> > > > -
> > > > -        for f in fields: setattr(self, f, None)
> > > > -        for k in kwargs: getattr(self, k) # Check for invalid kwargs
> > > > -
> > > > -        if isinstance(url, Url): # Copy from another Url instance.
> > > > -            self.__dict__.update(url.__dict__)
> > > > -        elif url is not None:   # Parse from url
> > > > -            parts = pni_parse_url(str(url))
> > > > -            if not filter(None, parts): raise ValueError("Invalid AMQP
> > > > URL: '%s'" % url)
> > > > -            self.scheme, self.user, self.password, self.host, port,
> > > > self.path = parts
> > > > -            if not self.host: self.host = None
> > > > -            self.port = port and self.Port(port)
> > > > -
> > > > -        # Let kwargs override values previously set from url
> > > > -        for field in fields:
> > > > -            setattr(self, field, kwargs.get(field, getattr(self,
> > field)))
> > > > -
> > > > -    def __repr__(self):
> > > > -        return "Url(%r)" % str(self)
> > > > -
> > > > -    def __str__(self):
> > > > -        s = ""
> > > > -        if self.scheme:
> > > > -            s += "%s://" % self.scheme
> > > > -        if self.user:
> > > > -            s += self.user
> > > > -        if self.password:
> > > > -            s += ":%s" % self.password
> > > > -        if self.user or self.password:
> > > > -            s += '@'
> > > > -        if self.host and ':' in self.host:
> > > > -            s += "[%s]" % self.host
> > > > -        elif self.host:
> > > > -            s += self.host
> > > > -        if self.port:
> > > > -            s += ":%s" % self.port
> > > > -        if self.path:
> > > > -            s += "/%s" % self.path
> > > > -        return s
> > > > -
> > > > -    def __eq__(self, url):
> > > > -        return \
> > > > -            self.scheme == url.scheme and \
> > > > -            self.user == url.user and self.password == url.password
> > and \
> > > > -            self.host == url.host and self.port == url.port and \
> > > > -            self.path == url.path
> > > > -
> > > > -    def __ne__(self, url):
> > > > -        return not self.__eq__(url)
> > > > -
> > > > -    def defaults(self):
> > > > -        """
> > > > -        Fill in missing values with defaults
> > > > -        @return: self
> > > > -        """
> > > > -        self.scheme = self.scheme or self.AMQP
> > > > -        self.host = self.host or '0.0.0.0'
> > > > -        self.port = self.port or self.Port(self.scheme)
> > > > -        return self
> > > > +  def defaults(self):
> > > > +    """
> > > > +    Fill in missing values (scheme, host or port) with defaults
> > > > +    @return: self
> > > > +    """
> > > > +    self.scheme = self.scheme or self.AMQP
> > > > +    self.host = self.host or '0.0.0.0'
> > > > +    self.port = self.port or self.Port(self.scheme)
> > > > +    return self
> > > >
> > > > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> > > > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19 21:00:50
> > > > 2014
> > > > @@ -26,8 +26,8 @@
> > > >  #include <proton/messenger.h>
> > > >  #include <proton/ssl.h>
> > > >  #include <proton/driver_extras.h>
> > > > -
> > > >  #include <proton/types.h>
> > > > +#include <proton/url.h>
> > > >
> > > >  #include <uuid/uuid.h>
> > > >  %}
> > > >
> > > > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/include/proton/cproton.i (original)
> > > > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri Sep 19
> > > > 21:00:50 2014
> > > > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> > > >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return (pn_delivery_t
> > *)
> > > > x; }
> > > >    pn_transport_t *pn_cast_pn_transport(void *x) { return
> > (pn_transport_t
> > > > *) x; }
> > > >  %}
> > > > +
> > > > +%include "proton/url.h"
> > > > +
> > > >
> > > > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > > > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19 21:00:50
> > > > 2014
> > > > @@ -0,0 +1,83 @@
> > > > +#ifndef PROTON_URL_H
> > > > +#define PROTON_URL_H
> > > > +/*
> > > > + * 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.
> > > > + */
> > > > +
> > > > +#include <proton/import_export.h>
> > > > +
> > > > +/** @file
> > > > + * URL API for parsing URLs.
> > > > + *
> > > > + * @defgroup url URL
> > > > + * @{
> > > > + */
> > > > +
> > > > +/** A parsed URL */
> > > > +typedef struct pn_url_t pn_url_t;
> > > > +
> > > > +/** Create an empty URL */
> > > > +PN_EXTERN pn_url_t *pn_url(void);
> > > > +
> > > > +/** Parse a string URL as a pn_url_t.
> > > > + *@param[in] url A URL string.
> > > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> > string.
> > > > + */
> > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > > > +
> > > > +/** Free a URL */
> > > > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > > > +
> > > > +/** Clear the contents of the URL. */
> > > > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > > > +
> > > > +/** Return the string form of a URL. Owned by the pn_url_t.*/
> > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > > > +
> > > > +/**
> > > > + *@name Getters for parts of the URL.
> > > > + *
> > > > + *Values belong to the URL. May return NULL if the value is not set.
> > > > + *
> > > > + *@{
> > > > + */
> > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > > > +///@}
> > > > +
> > > > +/**
> > > > + *@name Setters for parts of the URL.
> > > > + *
> > > > + *Values are copied. Value can be NULL to indicate the part is not
> > set.
> > > > + *
> > > > + *@{
> > > > + */
> > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme);
> > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > *username);
> > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > *password);
> > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host);
> > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port);
> > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path);
> > > > +///@}
> > > > +
> > > > +///@}
> > > > +#endif
> > > >
> > > > Added: qpid/proton/trunk/proton-c/src/url.c
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > > > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50 2014
> > > > @@ -0,0 +1,127 @@
> > > > +/*
> > > > + *
> > > > + * 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.
> > > > + *
> > > > + */
> > > > +
> > > > +#include <proton/url.h>
> > > > +#include <proton/util.h>
> > > > +#include <stdlib.h>
> > > > +#include <string.h>
> > > > +#include <stdio.h>
> > > > +
> > > > +static char* copy(const char* str) {
> > > > +    if (str ==  NULL) return NULL;
> > > > +    char *str2 = (char*)malloc(strlen(str));
> > > > +    if (str2) strcpy(str2, str);
> > > > +    return str2;
> > > > +}
> > > > +
> > > > +struct pn_url_t {
> > > > +    char *scheme;
> > > > +    char *username;
> > > > +    char *password;
> > > > +    char *host;
> > > > +    char *port;
> > > > +    char *path;
> > > > +    char *str;
> > > > +};
> > > > +
> > > > +PN_EXTERN pn_url_t *pn_url() {
> > > > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > > > +    memset(url, 0, sizeof(*url));
> > > > +    return url;
> > > > +}
> > > > +
> > > > +/** Parse a string URL as a pn_url_t.
> > > > + *@param[in] url A URL string.
> > > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> > string.
> > > > + */
> > > > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > > > +    if (!str || !*str)          /* Empty string or NULL is illegal. */
> > > > +        return NULL;
> > > > +
> > > > +    pn_url_t *url = pn_url();
> > > > +    char *str2 = copy(str);         /* FIXME aconway 2014-09-19:
> > clean up
> > > > */
> > > > +    pni_parse_url(str2, &url->scheme, &url->username, &url->password,
> > > > &url->host, &url->port, &url->path);
> > > > +    url->scheme = copy(url->scheme);
> > > > +    url->username = copy(url->username);
> > > > +    url->password = copy(url->password);
> > > > +    url->host = (url->host && !*url->host) ? NULL : copy(url->host);
> > > > +    url->port = copy(url->port);
> > > > +    url->path = copy(url->path);
> > > > +    return url;
> > > > +}
> > > > +
> > > > +/** Free a URL */
> > > > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > > > +    pn_url_clear(url);
> > > > +    free(url);
> > > > +}
> > > > +
> > > > +/** Clear the contents of the URL. */
> > > > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > > > +    pn_url_set_username(url, NULL);
> > > > +    pn_url_set_password(url, NULL);
> > > > +    pn_url_set_host(url, NULL);
> > > > +    pn_url_set_port(url, NULL);
> > > > +    pn_url_set_path(url, NULL);
> > > > +    free(url->str); url->str = NULL;
> > > > +}
> > > > +
> > > > +static inline int len(const char *str) { return str ? strlen(str) :
> > 0; }
> > > > +
> > > > +/** Return the string form of a URL. */
> > > > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > > > +    int size = len(url->scheme) + len(url->username) +
> > len(url->password)
> > > > +        + len(url->host) + len(url->port) + len(url->path)
> > > > +        + len("s://u:p@[h]:p/p");
> > > > +    free(url->str);
> > > > +    url->str = (char*)malloc(size);
> > > > +    if (!url->str) return NULL;
> > > > +
> > > > +    int i = 0;
> > > > +    if (url->scheme) i += snprintf(url->str+i, size-i, "%s://",
> > > > url->scheme);
> > > > +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> > > > url->username);
> > > > +    if (url->password) i += snprintf(url->str+i, size-i, ":%s",
> > > > url->password);
> > > > +    if (url->username || url->password) i += snprintf(url->str+i,
> > size-i,
> > > > "@");
> > > > +    if (url->host) {
> > > > +        if (strchr(url->host, ':')) i += snprintf(url->str+i, size-i,
> > > > "[%s]", url->host);
> > > > +        else i += snprintf(url->str+i, size-i, "%s", url->host);
> > > > +    }
> > > > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
> > url->port);
> > > > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
> > url->path);
> > > > +    return url->str;
> > > > +}
> > > > +
> > > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
> > url->scheme; }
> > > > +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> > > > url->username; }
> > > > +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> > > > url->password; }
> > > > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return url->host; }
> > > > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return url->port; }
> > > > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return url->path; }
> > > > +
> > > > +#define SET(part) free(url->part); url->part = copy(part)
> > > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme) {
> > > > SET(scheme); }
> > > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> > *username) {
> > > > SET(username); }
> > > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> > *password) {
> > > > SET(password); }
> > > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host) {
> > > > SET(host); }
> > > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port) {
> > > > SET(port); }
> > > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path) {
> > > > SET(path); }
> > > > +
> > > > +
> > > >
> > > > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > > > URL:
> > > >
> > http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > > >
> > > >
> > ==============================================================================
> > > > --- qpid/proton/trunk/tests/python/proton_tests/url.py (original)
> > > > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep 19
> > 21:00:50
> > > > 2014
> > > > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> > > >      def assertNotEqual(self, a, b):
> > > >          assert a != b, "%s == %s" % (a, b)
> > > >
> > > > -    def assertUrl(self, u, scheme, user, password, host, port, path):
> > > > -        self.assertEqual((u.scheme, u.user, u.password, u.host,
> > u.port,
> > > > u.path),
> > > > -                         (scheme, user, password, host, port, path))
> > > > +    def assertUrl(self, u, scheme, username, password, host, port,
> > path):
> > > > +        self.assertEqual((u.scheme, u.username, u.password, u.host,
> > > > u.port, u.path),
> > > > +                         (scheme, username, password, host, port,
> > path))
> > > >
> > > >      def testUrl(self):
> > > >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > > > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> > > >
> > > >      def testDefaults(self):
> > > >          # Check that we allow None for scheme, port
> > > > -        url = Url(user='me', password='secret', host='myhost',
> > > > path='foobar')
> > > > +        url = Url(username='me', password='secret', host='myhost',
> > > > path='foobar')
> > > >          self.assertEqual(str(url), "me:secret@myhost/foobar")
> > > >          self.assertUrl(url, None, 'me', 'secret', 'myhost', None,
> > > > 'foobar')
> > > >
> > > > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> > > >      def testMissing(self):
> > > >          self.assertUrl(Url(), None, None, None, None, None, None)
> > > >          self.assertUrl(Url('amqp://'), 'amqp', None, None, None, None,
> > > > None)
> > > > -        self.assertUrl(Url('user@'), None, 'user', None, None, None,
> > > > None)
> > > > +        self.assertUrl(Url('username@'), None, 'username', None,
> > None,
> > > > None, None)
> > > >          self.assertUrl(Url(':pass@'), None, '', 'pass', None, None,
> > None)
> > > >          self.assertUrl(Url('host'), None, None, None, 'host', None,
> > None)
> > > >          self.assertUrl(Url(':1234'), None, None, None, None, 1234,
> > None)
> > > >          self.assertUrl(Url('/path'), None, None, None, None, None,
> > 'path')
> > > >
> > > > -        for s in ['amqp://', 'user@', ':pass@', ':1234', '/path']:
> > > > +        for s in ['amqp://', 'username@', ':pass@', ':1234',
> > '/path']:
> > > >              self.assertEqual(s, str(Url(s)))
> > > >
> > > >          for s, full in [
> > > >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > > > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > > > +                ('username@', 'amqp://username@0.0.0.0:amqp'),
> > > >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> > > >                  (':1234', 'amqp://0.0.0.0:1234'),
> > > >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> > > >              self.assertEqual(str(Url(s).defaults()), full)
> > > > -
> > > > -        self.assertRaises(ValueError, Url, '')
> > > >
> > > >
> > > >
> > > > ---------------------------------------------------------------------
> > > > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > > > For additional commands, e-mail: commits-help@qpid.apache.org
> > > >
> > > >
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> > For additional commands, e-mail: dev-help@qpid.apache.org
> >
> >



Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Robbie Gemmell <ro...@gmail.com>.
The tests are now running again, but a couple of the URL tests still seem
to be failing on the CI job:
https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/

As mentioned in my other post about a timeline for dropping Java6 support,
they seem to work on Java8 (havent tried Java7).

Robbie

On 22 September 2014 21:14, Alan Conway <ac...@redhat.com> wrote:

> My bad, didn't run the java tests. Will fix ASAP and then give myself a
> flogging.
>
> On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> > This seems to have broken the Java test runs:
> >
> > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> >
> >
> >
> > On 19 September 2014 22:00, <ac...@apache.org> wrote:
> >
> > > Author: aconway
> > > Date: Fri Sep 19 21:00:50 2014
> > > New Revision: 1626329
> > >
> > > URL: http://svn.apache.org/r1626329
> > > Log:
> > > PROTON-693: Python Url class to wrap C function pni_parse_url
> > >
> > > It was pointed out that pni_parse_url is an internal function and the
> > > interface
> > > is not suitable for public API.
> > >
> > > Rewrote the URL parser as a proper swigable C API pn_url_*. This gets
> rid
> > > of the
> > > need for previous swig insanity and is cleaner all round.
> > >
> > > Internally still uses the pni_parse_url parser, we can clean that up
> later.
> > >
> > > Added:
> > >     qpid/proton/trunk/proton-c/include/proton/url.h
> > >     qpid/proton/trunk/proton-c/src/url.c
> > > Modified:
> > >     qpid/proton/trunk/proton-c/CMakeLists.txt
> > >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > >     qpid/proton/trunk/proton-c/bindings/php/php.i
> > >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> > >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> > >     qpid/proton/trunk/tests/python/proton_tests/url.py
> > >
> > > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19 21:00:50 2014
> > > @@ -270,6 +270,7 @@ set (qpid-proton-core
> > >    src/object/iterator.c
> > >
> > >    src/util.c
> > > +  src/url.c
> > >    src/error.c
> > >    src/buffer.c
> > >    src/parser.c
> > >
> > > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> > > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19 21:00:50
> > > 2014
> > > @@ -8,6 +8,7 @@
> > >  #include <proton/messenger.h>
> > >  #include <proton/ssl.h>
> > >  #include <proton/driver_extras.h>
> > > +#include <proton/url.h>
> > >  %}
> > >
> > >  %include <cstring.i>
> > >
> > > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19 21:00:50
> 2014
> > > @@ -29,6 +29,7 @@
> > >  %header %{
> > >  /* Include the headers needed by the code in this wrapper file */
> > >  #include <proton/types.h>
> > > +#include <proton/url.h>
> > >  #include <proton/message.h>
> > >  #include <proton/driver.h>
> > >  #include <proton/driver_extras.h>
> > >
> > > Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i (original)
> > > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri Sep 19
> > > 21:00:50 2014
> > > @@ -23,6 +23,7 @@
> > >  #include <winsock2.h>
> > >  #endif
> > >  #include <proton/engine.h>
> > > +#include <proton/url.h>
> > >  #include <proton/message.h>
> > >  #include <proton/sasl.h>
> > >  #include <proton/driver.h>
> > > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> > >    }
> > >  %}
> > >
> > > -
> > > -/**
> > > -   pni_parse_url(char* url, char **scheme, char **user, char **pass,
> char
> > > **host, char **port, char **path)
> > > -   The following type maps convert this into a python function that
> taks
> > > a URL string argument
> > > -   and returns a list of strings [scheme, user, pass, host, port,
> path]
> > > -   This probably could be done more neatly.
> > > -*/
> > > -
> > > -// Typemap to copy the url string as it will be modified by parse_url
> > > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char *url (int
> > > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > > -  if (!SWIG_IsOK(res)) {
> > > -    %argument_fail(res, "char *url", $symname, $argnum);
> > > -  }
> > > -  $1 = %new_array(n, $*1_ltype);
> > > -  memcpy($1,t,sizeof(char)*n);
> > > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > > -  $1[n-1] = 0;
> > > -}
> > > -%typemap(freearg,match="in") char *url "free($1);";
> > > -%typemap(argout) char *url "";
> > > -
> > > -// Typemap for char** return strings. Don't free them.
> > > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0) "$1 =
> &temp;";
> > > -%typemap(freearg,match="in") char **OUTSTR "";
> > > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char **OUTSTR {
> > > -    %append_output(SWIG_FromCharPtr(*$1));
> > > -}
> > > -
> > > -// Typemap to initialize result as empty list
> > > -%typemap(out) void "$result = PyList_New(0);";
> > > -
> > > -
> > > -%apply char** OUTSTR {char **scheme, char **user, char **pass, char
> > > **host, char **port, char **path};
> > > -void pni_parse_url(char* url, char **scheme, char **user, char **pass,
> > > char **host, char **port, char **path);
> > > -%ignore pni_parse_url;
> > > -
> > >  %include "proton/cproton.i"
> > >
> > > Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
> > > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri Sep 19
> > > 21:00:50 2014
> > > @@ -3657,114 +3657,98 @@ __all__ = [
> > >
> > >
> > >  class Url(object):
> > > -    """
> > > -    Simple URL parser/constructor, handles URLs of the form:
> > > +  """
> > > +  Simple URL parser/constructor, handles URLs of the form:
> > >
> > > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> > >
> > > -    All components can be None if not specifeid in the URL string.
> > > +  All components can be None if not specifeid in the URL string.
> > >
> > > -    The port can be specified as a service name, e.g. 'amqp' in the
> > > -    URL string but Url.port always gives the integer value.
> > > +  The port can be specified as a service name, e.g. 'amqp' in the
> > > +  URL string but Url.port always gives the integer value.
> > > +
> > > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > +  @ivar user: Username
> > > +  @ivar password: Password
> > > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > +  @ivar port: Integer port.
> > > +  @ivar host_port: Returns host:port
> > > +  """
> > > +
> > > +  AMQPS = "amqps"
> > > +  AMQP = "amqp"
> > > +
> > > +  class Port(int):
> > > +    """An integer port number that can be constructed from a service
> name
> > > string"""
> > > +
> > > +    def __new__(cls, value):
> > > +      port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
> > > +      setattr(port, 'name', str(value))
> > > +      return port
> > > +
> > > +    def __eq__(self, x): return str(self) == x or int(self) == x
> > > +    def __ne__(self, x): return not self == x
> > > +    def __str__(self): return str(self.name)
> > > +
> > > +    @staticmethod
> > > +    def port_int(value):
> > > +      """Convert service, an integer or a service name, into an
> integer
> > > port number."""
> > > +      try:
> > > +        return int(value)
> > > +      except ValueError:
> > > +        try:
> > > +          return socket.getservbyname(value)
> > > +        except socket.error:
> > > +          raise ValueError("Not a valid port number or service name:
> > > '%s'" % value)
> > >
> > > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > -    @ivar user: Username
> > > -    @ivar password: Password
> > > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > -    @ivar port: Integer port.
> > > -    @ivar host_port: Returns host:port
> > > +  def __init__(self, url=None, **kwargs):
> > > +    """
> > > +    @param url: URL string to parse.
> > > +    @param kwargs: scheme, user, password, host, port, path.
> > > +      If specified, replaces corresponding part in url string.
> > >      """
> > > +    if url:
> > > +      self._url = pn_url_parse(str(url))
> > > +      if not self._url: raise ValueError("Invalid URL '%s'" % url)
> > > +    else:
> > > +      self._url = pn_url()
> > > +    for k in kwargs:            # Let kwargs override values parsed
> from
> > > url
> > > +      getattr(self, k)          # Check for invalid kwargs
> > > +      setattr(self, k, kwargs[k])
> > > +
> > > +  class PartDescriptor(object):
> > > +    def __init__(self, part):
> > > +      self.getter = globals()["pn_url_%s" % part]
> > > +      self.setter = globals()["pn_url_set_%s" % part]
> > > +    def __get__(self, obj, type=None): return self.getter(obj._url)
> > > +    def __set__(self, obj, value): return self.setter(obj._url,
> > > str(value))
> > > +
> > > +  scheme = PartDescriptor('scheme')
> > > +  username = PartDescriptor('username')
> > > +  password = PartDescriptor('password')
> > > +  host = PartDescriptor('host')
> > > +  path = PartDescriptor('path')
> > > +
> > > +  @property
> > > +  def port(self):
> > > +    portstr = pn_url_port(self._url)
> > > +    return portstr and Url.Port(portstr)
> > > +
> > > +  @port.setter
> > > +  def port(self, value):
> > > +    if value is None: pn_url_set_port(self._url, None)
> > > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> > >
> > > -    AMQPS = "amqps"
> > > -    AMQP = "amqp"
> > > +  def __str__(self): return pn_url_str(self._url)
> > >
> > > -    class Port(int):
> > > -      """An integer port number that can also have an associated
> service
> > > name string"""
> > > +  def __repr__(self): return "Url(%r)" % str(self)
> > >
> > > -      def __new__(cls, value):
> > > -        port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
> > > -        setattr(port, 'name', str(value))
> > > -        return port
> > > -
> > > -      def __eq__(self, x): return str(self) == x or int(self) == x
> > > -      def __ne__(self, x): return not self == x
> > > -      def __str__(self): return str(self.name)
> > > -
> > > -      @staticmethod
> > > -      def port_int(value):
> > > -        """Convert service, an integer or a service name, into an
> integer
> > > port number."""
> > > -        try:
> > > -          return int(value)
> > > -        except ValueError:
> > > -          try:
> > > -            return socket.getservbyname(value)
> > > -          except socket.error:
> > > -            raise ValueError("Not a valid port number or service name:
> > > '%s'" % value)
> > > -
> > > -    def __init__(self, url=None, **kwargs):
> > > -        """
> > > -        @param url: String or Url instance to parse or copy.
> > > -        @param kwargs: URL fields: scheme, user, password, host, port,
> > > path.
> > > -            If specified, replaces corresponding component in url.
> > > -        """
> > > -
> > > -        fields = ['scheme', 'user', 'password', 'host', 'port',
> 'path']
> > > -
> > > -        for f in fields: setattr(self, f, None)
> > > -        for k in kwargs: getattr(self, k) # Check for invalid kwargs
> > > -
> > > -        if isinstance(url, Url): # Copy from another Url instance.
> > > -            self.__dict__.update(url.__dict__)
> > > -        elif url is not None:   # Parse from url
> > > -            parts = pni_parse_url(str(url))
> > > -            if not filter(None, parts): raise ValueError("Invalid AMQP
> > > URL: '%s'" % url)
> > > -            self.scheme, self.user, self.password, self.host, port,
> > > self.path = parts
> > > -            if not self.host: self.host = None
> > > -            self.port = port and self.Port(port)
> > > -
> > > -        # Let kwargs override values previously set from url
> > > -        for field in fields:
> > > -            setattr(self, field, kwargs.get(field, getattr(self,
> field)))
> > > -
> > > -    def __repr__(self):
> > > -        return "Url(%r)" % str(self)
> > > -
> > > -    def __str__(self):
> > > -        s = ""
> > > -        if self.scheme:
> > > -            s += "%s://" % self.scheme
> > > -        if self.user:
> > > -            s += self.user
> > > -        if self.password:
> > > -            s += ":%s" % self.password
> > > -        if self.user or self.password:
> > > -            s += '@'
> > > -        if self.host and ':' in self.host:
> > > -            s += "[%s]" % self.host
> > > -        elif self.host:
> > > -            s += self.host
> > > -        if self.port:
> > > -            s += ":%s" % self.port
> > > -        if self.path:
> > > -            s += "/%s" % self.path
> > > -        return s
> > > -
> > > -    def __eq__(self, url):
> > > -        return \
> > > -            self.scheme == url.scheme and \
> > > -            self.user == url.user and self.password == url.password
> and \
> > > -            self.host == url.host and self.port == url.port and \
> > > -            self.path == url.path
> > > -
> > > -    def __ne__(self, url):
> > > -        return not self.__eq__(url)
> > > -
> > > -    def defaults(self):
> > > -        """
> > > -        Fill in missing values with defaults
> > > -        @return: self
> > > -        """
> > > -        self.scheme = self.scheme or self.AMQP
> > > -        self.host = self.host or '0.0.0.0'
> > > -        self.port = self.port or self.Port(self.scheme)
> > > -        return self
> > > +  def defaults(self):
> > > +    """
> > > +    Fill in missing values (scheme, host or port) with defaults
> > > +    @return: self
> > > +    """
> > > +    self.scheme = self.scheme or self.AMQP
> > > +    self.host = self.host or '0.0.0.0'
> > > +    self.port = self.port or self.Port(self.scheme)
> > > +    return self
> > >
> > > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> > > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19 21:00:50
> > > 2014
> > > @@ -26,8 +26,8 @@
> > >  #include <proton/messenger.h>
> > >  #include <proton/ssl.h>
> > >  #include <proton/driver_extras.h>
> > > -
> > >  #include <proton/types.h>
> > > +#include <proton/url.h>
> > >
> > >  #include <uuid/uuid.h>
> > >  %}
> > >
> > > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/include/proton/cproton.i (original)
> > > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri Sep 19
> > > 21:00:50 2014
> > > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> > >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return (pn_delivery_t
> *)
> > > x; }
> > >    pn_transport_t *pn_cast_pn_transport(void *x) { return
> (pn_transport_t
> > > *) x; }
> > >  %}
> > > +
> > > +%include "proton/url.h"
> > > +
> > >
> > > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19 21:00:50
> > > 2014
> > > @@ -0,0 +1,83 @@
> > > +#ifndef PROTON_URL_H
> > > +#define PROTON_URL_H
> > > +/*
> > > + * 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.
> > > + */
> > > +
> > > +#include <proton/import_export.h>
> > > +
> > > +/** @file
> > > + * URL API for parsing URLs.
> > > + *
> > > + * @defgroup url URL
> > > + * @{
> > > + */
> > > +
> > > +/** A parsed URL */
> > > +typedef struct pn_url_t pn_url_t;
> > > +
> > > +/** Create an empty URL */
> > > +PN_EXTERN pn_url_t *pn_url(void);
> > > +
> > > +/** Parse a string URL as a pn_url_t.
> > > + *@param[in] url A URL string.
> > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> string.
> > > + */
> > > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > > +
> > > +/** Free a URL */
> > > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > > +
> > > +/** Clear the contents of the URL. */
> > > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > > +
> > > +/** Return the string form of a URL. Owned by the pn_url_t.*/
> > > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > > +
> > > +/**
> > > + *@name Getters for parts of the URL.
> > > + *
> > > + *Values belong to the URL. May return NULL if the value is not set.
> > > + *
> > > + *@{
> > > + */
> > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > > +///@}
> > > +
> > > +/**
> > > + *@name Setters for parts of the URL.
> > > + *
> > > + *Values are copied. Value can be NULL to indicate the part is not
> set.
> > > + *
> > > + *@{
> > > + */
> > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme);
> > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> *username);
> > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> *password);
> > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host);
> > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port);
> > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path);
> > > +///@}
> > > +
> > > +///@}
> > > +#endif
> > >
> > > Added: qpid/proton/trunk/proton-c/src/url.c
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50 2014
> > > @@ -0,0 +1,127 @@
> > > +/*
> > > + *
> > > + * 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.
> > > + *
> > > + */
> > > +
> > > +#include <proton/url.h>
> > > +#include <proton/util.h>
> > > +#include <stdlib.h>
> > > +#include <string.h>
> > > +#include <stdio.h>
> > > +
> > > +static char* copy(const char* str) {
> > > +    if (str ==  NULL) return NULL;
> > > +    char *str2 = (char*)malloc(strlen(str));
> > > +    if (str2) strcpy(str2, str);
> > > +    return str2;
> > > +}
> > > +
> > > +struct pn_url_t {
> > > +    char *scheme;
> > > +    char *username;
> > > +    char *password;
> > > +    char *host;
> > > +    char *port;
> > > +    char *path;
> > > +    char *str;
> > > +};
> > > +
> > > +PN_EXTERN pn_url_t *pn_url() {
> > > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > > +    memset(url, 0, sizeof(*url));
> > > +    return url;
> > > +}
> > > +
> > > +/** Parse a string URL as a pn_url_t.
> > > + *@param[in] url A URL string.
> > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> string.
> > > + */
> > > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > > +    if (!str || !*str)          /* Empty string or NULL is illegal. */
> > > +        return NULL;
> > > +
> > > +    pn_url_t *url = pn_url();
> > > +    char *str2 = copy(str);         /* FIXME aconway 2014-09-19:
> clean up
> > > */
> > > +    pni_parse_url(str2, &url->scheme, &url->username, &url->password,
> > > &url->host, &url->port, &url->path);
> > > +    url->scheme = copy(url->scheme);
> > > +    url->username = copy(url->username);
> > > +    url->password = copy(url->password);
> > > +    url->host = (url->host && !*url->host) ? NULL : copy(url->host);
> > > +    url->port = copy(url->port);
> > > +    url->path = copy(url->path);
> > > +    return url;
> > > +}
> > > +
> > > +/** Free a URL */
> > > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > > +    pn_url_clear(url);
> > > +    free(url);
> > > +}
> > > +
> > > +/** Clear the contents of the URL. */
> > > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > > +    pn_url_set_username(url, NULL);
> > > +    pn_url_set_password(url, NULL);
> > > +    pn_url_set_host(url, NULL);
> > > +    pn_url_set_port(url, NULL);
> > > +    pn_url_set_path(url, NULL);
> > > +    free(url->str); url->str = NULL;
> > > +}
> > > +
> > > +static inline int len(const char *str) { return str ? strlen(str) :
> 0; }
> > > +
> > > +/** Return the string form of a URL. */
> > > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > > +    int size = len(url->scheme) + len(url->username) +
> len(url->password)
> > > +        + len(url->host) + len(url->port) + len(url->path)
> > > +        + len("s://u:p@[h]:p/p");
> > > +    free(url->str);
> > > +    url->str = (char*)malloc(size);
> > > +    if (!url->str) return NULL;
> > > +
> > > +    int i = 0;
> > > +    if (url->scheme) i += snprintf(url->str+i, size-i, "%s://",
> > > url->scheme);
> > > +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> > > url->username);
> > > +    if (url->password) i += snprintf(url->str+i, size-i, ":%s",
> > > url->password);
> > > +    if (url->username || url->password) i += snprintf(url->str+i,
> size-i,
> > > "@");
> > > +    if (url->host) {
> > > +        if (strchr(url->host, ':')) i += snprintf(url->str+i, size-i,
> > > "[%s]", url->host);
> > > +        else i += snprintf(url->str+i, size-i, "%s", url->host);
> > > +    }
> > > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
> url->port);
> > > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
> url->path);
> > > +    return url->str;
> > > +}
> > > +
> > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
> url->scheme; }
> > > +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> > > url->username; }
> > > +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> > > url->password; }
> > > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return url->host; }
> > > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return url->port; }
> > > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return url->path; }
> > > +
> > > +#define SET(part) free(url->part); url->part = copy(part)
> > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme) {
> > > SET(scheme); }
> > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> *username) {
> > > SET(username); }
> > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> *password) {
> > > SET(password); }
> > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host) {
> > > SET(host); }
> > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port) {
> > > SET(port); }
> > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path) {
> > > SET(path); }
> > > +
> > > +
> > >
> > > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/tests/python/proton_tests/url.py (original)
> > > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep 19
> 21:00:50
> > > 2014
> > > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> > >      def assertNotEqual(self, a, b):
> > >          assert a != b, "%s == %s" % (a, b)
> > >
> > > -    def assertUrl(self, u, scheme, user, password, host, port, path):
> > > -        self.assertEqual((u.scheme, u.user, u.password, u.host,
> u.port,
> > > u.path),
> > > -                         (scheme, user, password, host, port, path))
> > > +    def assertUrl(self, u, scheme, username, password, host, port,
> path):
> > > +        self.assertEqual((u.scheme, u.username, u.password, u.host,
> > > u.port, u.path),
> > > +                         (scheme, username, password, host, port,
> path))
> > >
> > >      def testUrl(self):
> > >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> > >
> > >      def testDefaults(self):
> > >          # Check that we allow None for scheme, port
> > > -        url = Url(user='me', password='secret', host='myhost',
> > > path='foobar')
> > > +        url = Url(username='me', password='secret', host='myhost',
> > > path='foobar')
> > >          self.assertEqual(str(url), "me:secret@myhost/foobar")
> > >          self.assertUrl(url, None, 'me', 'secret', 'myhost', None,
> > > 'foobar')
> > >
> > > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> > >      def testMissing(self):
> > >          self.assertUrl(Url(), None, None, None, None, None, None)
> > >          self.assertUrl(Url('amqp://'), 'amqp', None, None, None, None,
> > > None)
> > > -        self.assertUrl(Url('user@'), None, 'user', None, None, None,
> > > None)
> > > +        self.assertUrl(Url('username@'), None, 'username', None,
> None,
> > > None, None)
> > >          self.assertUrl(Url(':pass@'), None, '', 'pass', None, None,
> None)
> > >          self.assertUrl(Url('host'), None, None, None, 'host', None,
> None)
> > >          self.assertUrl(Url(':1234'), None, None, None, None, 1234,
> None)
> > >          self.assertUrl(Url('/path'), None, None, None, None, None,
> 'path')
> > >
> > > -        for s in ['amqp://', 'user@', ':pass@', ':1234', '/path']:
> > > +        for s in ['amqp://', 'username@', ':pass@', ':1234',
> '/path']:
> > >              self.assertEqual(s, str(Url(s)))
> > >
> > >          for s, full in [
> > >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > > +                ('username@', 'amqp://username@0.0.0.0:amqp'),
> > >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> > >                  (':1234', 'amqp://0.0.0.0:1234'),
> > >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> > >              self.assertEqual(str(Url(s).defaults()), full)
> > > -
> > > -        self.assertRaises(ValueError, Url, '')
> > >
> > >
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > > For additional commands, e-mail: commits-help@qpid.apache.org
> > >
> > >
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> For additional commands, e-mail: dev-help@qpid.apache.org
>
>

Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Robbie Gemmell <ro...@gmail.com>.
The tests are now running again, but a couple of the URL tests still seem
to be failing on the CI job:
https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/lastBuild/org.apache.qpid$proton-tests/testReport/

As mentioned in my other post about a timeline for dropping Java6 support,
they seem to work on Java8 (havent tried Java7).

Robbie

On 22 September 2014 21:14, Alan Conway <ac...@redhat.com> wrote:

> My bad, didn't run the java tests. Will fix ASAP and then give myself a
> flogging.
>
> On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> > This seems to have broken the Java test runs:
> >
> > https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> >
> >
> >
> > On 19 September 2014 22:00, <ac...@apache.org> wrote:
> >
> > > Author: aconway
> > > Date: Fri Sep 19 21:00:50 2014
> > > New Revision: 1626329
> > >
> > > URL: http://svn.apache.org/r1626329
> > > Log:
> > > PROTON-693: Python Url class to wrap C function pni_parse_url
> > >
> > > It was pointed out that pni_parse_url is an internal function and the
> > > interface
> > > is not suitable for public API.
> > >
> > > Rewrote the URL parser as a proper swigable C API pn_url_*. This gets
> rid
> > > of the
> > > need for previous swig insanity and is cleaner all round.
> > >
> > > Internally still uses the pni_parse_url parser, we can clean that up
> later.
> > >
> > > Added:
> > >     qpid/proton/trunk/proton-c/include/proton/url.h
> > >     qpid/proton/trunk/proton-c/src/url.c
> > > Modified:
> > >     qpid/proton/trunk/proton-c/CMakeLists.txt
> > >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > >     qpid/proton/trunk/proton-c/bindings/php/php.i
> > >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> > >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> > >     qpid/proton/trunk/tests/python/proton_tests/url.py
> > >
> > > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19 21:00:50 2014
> > > @@ -270,6 +270,7 @@ set (qpid-proton-core
> > >    src/object/iterator.c
> > >
> > >    src/util.c
> > > +  src/url.c
> > >    src/error.c
> > >    src/buffer.c
> > >    src/parser.c
> > >
> > > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> > > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19 21:00:50
> > > 2014
> > > @@ -8,6 +8,7 @@
> > >  #include <proton/messenger.h>
> > >  #include <proton/ssl.h>
> > >  #include <proton/driver_extras.h>
> > > +#include <proton/url.h>
> > >  %}
> > >
> > >  %include <cstring.i>
> > >
> > > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19 21:00:50
> 2014
> > > @@ -29,6 +29,7 @@
> > >  %header %{
> > >  /* Include the headers needed by the code in this wrapper file */
> > >  #include <proton/types.h>
> > > +#include <proton/url.h>
> > >  #include <proton/message.h>
> > >  #include <proton/driver.h>
> > >  #include <proton/driver_extras.h>
> > >
> > > Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i (original)
> > > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri Sep 19
> > > 21:00:50 2014
> > > @@ -23,6 +23,7 @@
> > >  #include <winsock2.h>
> > >  #endif
> > >  #include <proton/engine.h>
> > > +#include <proton/url.h>
> > >  #include <proton/message.h>
> > >  #include <proton/sasl.h>
> > >  #include <proton/driver.h>
> > > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> > >    }
> > >  %}
> > >
> > > -
> > > -/**
> > > -   pni_parse_url(char* url, char **scheme, char **user, char **pass,
> char
> > > **host, char **port, char **path)
> > > -   The following type maps convert this into a python function that
> taks
> > > a URL string argument
> > > -   and returns a list of strings [scheme, user, pass, host, port,
> path]
> > > -   This probably could be done more neatly.
> > > -*/
> > > -
> > > -// Typemap to copy the url string as it will be modified by parse_url
> > > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char *url (int
> > > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > > -  if (!SWIG_IsOK(res)) {
> > > -    %argument_fail(res, "char *url", $symname, $argnum);
> > > -  }
> > > -  $1 = %new_array(n, $*1_ltype);
> > > -  memcpy($1,t,sizeof(char)*n);
> > > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > > -  $1[n-1] = 0;
> > > -}
> > > -%typemap(freearg,match="in") char *url "free($1);";
> > > -%typemap(argout) char *url "";
> > > -
> > > -// Typemap for char** return strings. Don't free them.
> > > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0) "$1 =
> &temp;";
> > > -%typemap(freearg,match="in") char **OUTSTR "";
> > > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char **OUTSTR {
> > > -    %append_output(SWIG_FromCharPtr(*$1));
> > > -}
> > > -
> > > -// Typemap to initialize result as empty list
> > > -%typemap(out) void "$result = PyList_New(0);";
> > > -
> > > -
> > > -%apply char** OUTSTR {char **scheme, char **user, char **pass, char
> > > **host, char **port, char **path};
> > > -void pni_parse_url(char* url, char **scheme, char **user, char **pass,
> > > char **host, char **port, char **path);
> > > -%ignore pni_parse_url;
> > > -
> > >  %include "proton/cproton.i"
> > >
> > > Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
> > > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri Sep 19
> > > 21:00:50 2014
> > > @@ -3657,114 +3657,98 @@ __all__ = [
> > >
> > >
> > >  class Url(object):
> > > -    """
> > > -    Simple URL parser/constructor, handles URLs of the form:
> > > +  """
> > > +  Simple URL parser/constructor, handles URLs of the form:
> > >
> > > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> > >
> > > -    All components can be None if not specifeid in the URL string.
> > > +  All components can be None if not specifeid in the URL string.
> > >
> > > -    The port can be specified as a service name, e.g. 'amqp' in the
> > > -    URL string but Url.port always gives the integer value.
> > > +  The port can be specified as a service name, e.g. 'amqp' in the
> > > +  URL string but Url.port always gives the integer value.
> > > +
> > > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > +  @ivar user: Username
> > > +  @ivar password: Password
> > > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > +  @ivar port: Integer port.
> > > +  @ivar host_port: Returns host:port
> > > +  """
> > > +
> > > +  AMQPS = "amqps"
> > > +  AMQP = "amqp"
> > > +
> > > +  class Port(int):
> > > +    """An integer port number that can be constructed from a service
> name
> > > string"""
> > > +
> > > +    def __new__(cls, value):
> > > +      port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
> > > +      setattr(port, 'name', str(value))
> > > +      return port
> > > +
> > > +    def __eq__(self, x): return str(self) == x or int(self) == x
> > > +    def __ne__(self, x): return not self == x
> > > +    def __str__(self): return str(self.name)
> > > +
> > > +    @staticmethod
> > > +    def port_int(value):
> > > +      """Convert service, an integer or a service name, into an
> integer
> > > port number."""
> > > +      try:
> > > +        return int(value)
> > > +      except ValueError:
> > > +        try:
> > > +          return socket.getservbyname(value)
> > > +        except socket.error:
> > > +          raise ValueError("Not a valid port number or service name:
> > > '%s'" % value)
> > >
> > > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > > -    @ivar user: Username
> > > -    @ivar password: Password
> > > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > > -    @ivar port: Integer port.
> > > -    @ivar host_port: Returns host:port
> > > +  def __init__(self, url=None, **kwargs):
> > > +    """
> > > +    @param url: URL string to parse.
> > > +    @param kwargs: scheme, user, password, host, port, path.
> > > +      If specified, replaces corresponding part in url string.
> > >      """
> > > +    if url:
> > > +      self._url = pn_url_parse(str(url))
> > > +      if not self._url: raise ValueError("Invalid URL '%s'" % url)
> > > +    else:
> > > +      self._url = pn_url()
> > > +    for k in kwargs:            # Let kwargs override values parsed
> from
> > > url
> > > +      getattr(self, k)          # Check for invalid kwargs
> > > +      setattr(self, k, kwargs[k])
> > > +
> > > +  class PartDescriptor(object):
> > > +    def __init__(self, part):
> > > +      self.getter = globals()["pn_url_%s" % part]
> > > +      self.setter = globals()["pn_url_set_%s" % part]
> > > +    def __get__(self, obj, type=None): return self.getter(obj._url)
> > > +    def __set__(self, obj, value): return self.setter(obj._url,
> > > str(value))
> > > +
> > > +  scheme = PartDescriptor('scheme')
> > > +  username = PartDescriptor('username')
> > > +  password = PartDescriptor('password')
> > > +  host = PartDescriptor('host')
> > > +  path = PartDescriptor('path')
> > > +
> > > +  @property
> > > +  def port(self):
> > > +    portstr = pn_url_port(self._url)
> > > +    return portstr and Url.Port(portstr)
> > > +
> > > +  @port.setter
> > > +  def port(self, value):
> > > +    if value is None: pn_url_set_port(self._url, None)
> > > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> > >
> > > -    AMQPS = "amqps"
> > > -    AMQP = "amqp"
> > > +  def __str__(self): return pn_url_str(self._url)
> > >
> > > -    class Port(int):
> > > -      """An integer port number that can also have an associated
> service
> > > name string"""
> > > +  def __repr__(self): return "Url(%r)" % str(self)
> > >
> > > -      def __new__(cls, value):
> > > -        port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
> > > -        setattr(port, 'name', str(value))
> > > -        return port
> > > -
> > > -      def __eq__(self, x): return str(self) == x or int(self) == x
> > > -      def __ne__(self, x): return not self == x
> > > -      def __str__(self): return str(self.name)
> > > -
> > > -      @staticmethod
> > > -      def port_int(value):
> > > -        """Convert service, an integer or a service name, into an
> integer
> > > port number."""
> > > -        try:
> > > -          return int(value)
> > > -        except ValueError:
> > > -          try:
> > > -            return socket.getservbyname(value)
> > > -          except socket.error:
> > > -            raise ValueError("Not a valid port number or service name:
> > > '%s'" % value)
> > > -
> > > -    def __init__(self, url=None, **kwargs):
> > > -        """
> > > -        @param url: String or Url instance to parse or copy.
> > > -        @param kwargs: URL fields: scheme, user, password, host, port,
> > > path.
> > > -            If specified, replaces corresponding component in url.
> > > -        """
> > > -
> > > -        fields = ['scheme', 'user', 'password', 'host', 'port',
> 'path']
> > > -
> > > -        for f in fields: setattr(self, f, None)
> > > -        for k in kwargs: getattr(self, k) # Check for invalid kwargs
> > > -
> > > -        if isinstance(url, Url): # Copy from another Url instance.
> > > -            self.__dict__.update(url.__dict__)
> > > -        elif url is not None:   # Parse from url
> > > -            parts = pni_parse_url(str(url))
> > > -            if not filter(None, parts): raise ValueError("Invalid AMQP
> > > URL: '%s'" % url)
> > > -            self.scheme, self.user, self.password, self.host, port,
> > > self.path = parts
> > > -            if not self.host: self.host = None
> > > -            self.port = port and self.Port(port)
> > > -
> > > -        # Let kwargs override values previously set from url
> > > -        for field in fields:
> > > -            setattr(self, field, kwargs.get(field, getattr(self,
> field)))
> > > -
> > > -    def __repr__(self):
> > > -        return "Url(%r)" % str(self)
> > > -
> > > -    def __str__(self):
> > > -        s = ""
> > > -        if self.scheme:
> > > -            s += "%s://" % self.scheme
> > > -        if self.user:
> > > -            s += self.user
> > > -        if self.password:
> > > -            s += ":%s" % self.password
> > > -        if self.user or self.password:
> > > -            s += '@'
> > > -        if self.host and ':' in self.host:
> > > -            s += "[%s]" % self.host
> > > -        elif self.host:
> > > -            s += self.host
> > > -        if self.port:
> > > -            s += ":%s" % self.port
> > > -        if self.path:
> > > -            s += "/%s" % self.path
> > > -        return s
> > > -
> > > -    def __eq__(self, url):
> > > -        return \
> > > -            self.scheme == url.scheme and \
> > > -            self.user == url.user and self.password == url.password
> and \
> > > -            self.host == url.host and self.port == url.port and \
> > > -            self.path == url.path
> > > -
> > > -    def __ne__(self, url):
> > > -        return not self.__eq__(url)
> > > -
> > > -    def defaults(self):
> > > -        """
> > > -        Fill in missing values with defaults
> > > -        @return: self
> > > -        """
> > > -        self.scheme = self.scheme or self.AMQP
> > > -        self.host = self.host or '0.0.0.0'
> > > -        self.port = self.port or self.Port(self.scheme)
> > > -        return self
> > > +  def defaults(self):
> > > +    """
> > > +    Fill in missing values (scheme, host or port) with defaults
> > > +    @return: self
> > > +    """
> > > +    self.scheme = self.scheme or self.AMQP
> > > +    self.host = self.host or '0.0.0.0'
> > > +    self.port = self.port or self.Port(self.scheme)
> > > +    return self
> > >
> > > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> > > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19 21:00:50
> > > 2014
> > > @@ -26,8 +26,8 @@
> > >  #include <proton/messenger.h>
> > >  #include <proton/ssl.h>
> > >  #include <proton/driver_extras.h>
> > > -
> > >  #include <proton/types.h>
> > > +#include <proton/url.h>
> > >
> > >  #include <uuid/uuid.h>
> > >  %}
> > >
> > > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/include/proton/cproton.i (original)
> > > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri Sep 19
> > > 21:00:50 2014
> > > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> > >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return (pn_delivery_t
> *)
> > > x; }
> > >    pn_transport_t *pn_cast_pn_transport(void *x) { return
> (pn_transport_t
> > > *) x; }
> > >  %}
> > > +
> > > +%include "proton/url.h"
> > > +
> > >
> > > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19 21:00:50
> > > 2014
> > > @@ -0,0 +1,83 @@
> > > +#ifndef PROTON_URL_H
> > > +#define PROTON_URL_H
> > > +/*
> > > + * 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.
> > > + */
> > > +
> > > +#include <proton/import_export.h>
> > > +
> > > +/** @file
> > > + * URL API for parsing URLs.
> > > + *
> > > + * @defgroup url URL
> > > + * @{
> > > + */
> > > +
> > > +/** A parsed URL */
> > > +typedef struct pn_url_t pn_url_t;
> > > +
> > > +/** Create an empty URL */
> > > +PN_EXTERN pn_url_t *pn_url(void);
> > > +
> > > +/** Parse a string URL as a pn_url_t.
> > > + *@param[in] url A URL string.
> > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> string.
> > > + */
> > > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > > +
> > > +/** Free a URL */
> > > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > > +
> > > +/** Clear the contents of the URL. */
> > > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > > +
> > > +/** Return the string form of a URL. Owned by the pn_url_t.*/
> > > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > > +
> > > +/**
> > > + *@name Getters for parts of the URL.
> > > + *
> > > + *Values belong to the URL. May return NULL if the value is not set.
> > > + *
> > > + *@{
> > > + */
> > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > > +///@}
> > > +
> > > +/**
> > > + *@name Setters for parts of the URL.
> > > + *
> > > + *Values are copied. Value can be NULL to indicate the part is not
> set.
> > > + *
> > > + *@{
> > > + */
> > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme);
> > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> *username);
> > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> *password);
> > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host);
> > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port);
> > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path);
> > > +///@}
> > > +
> > > +///@}
> > > +#endif
> > >
> > > Added: qpid/proton/trunk/proton-c/src/url.c
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50 2014
> > > @@ -0,0 +1,127 @@
> > > +/*
> > > + *
> > > + * 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.
> > > + *
> > > + */
> > > +
> > > +#include <proton/url.h>
> > > +#include <proton/util.h>
> > > +#include <stdlib.h>
> > > +#include <string.h>
> > > +#include <stdio.h>
> > > +
> > > +static char* copy(const char* str) {
> > > +    if (str ==  NULL) return NULL;
> > > +    char *str2 = (char*)malloc(strlen(str));
> > > +    if (str2) strcpy(str2, str);
> > > +    return str2;
> > > +}
> > > +
> > > +struct pn_url_t {
> > > +    char *scheme;
> > > +    char *username;
> > > +    char *password;
> > > +    char *host;
> > > +    char *port;
> > > +    char *path;
> > > +    char *str;
> > > +};
> > > +
> > > +PN_EXTERN pn_url_t *pn_url() {
> > > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > > +    memset(url, 0, sizeof(*url));
> > > +    return url;
> > > +}
> > > +
> > > +/** Parse a string URL as a pn_url_t.
> > > + *@param[in] url A URL string.
> > > + *@return The parsed pn_url_t or NULL if url is not a valid URL
> string.
> > > + */
> > > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > > +    if (!str || !*str)          /* Empty string or NULL is illegal. */
> > > +        return NULL;
> > > +
> > > +    pn_url_t *url = pn_url();
> > > +    char *str2 = copy(str);         /* FIXME aconway 2014-09-19:
> clean up
> > > */
> > > +    pni_parse_url(str2, &url->scheme, &url->username, &url->password,
> > > &url->host, &url->port, &url->path);
> > > +    url->scheme = copy(url->scheme);
> > > +    url->username = copy(url->username);
> > > +    url->password = copy(url->password);
> > > +    url->host = (url->host && !*url->host) ? NULL : copy(url->host);
> > > +    url->port = copy(url->port);
> > > +    url->path = copy(url->path);
> > > +    return url;
> > > +}
> > > +
> > > +/** Free a URL */
> > > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > > +    pn_url_clear(url);
> > > +    free(url);
> > > +}
> > > +
> > > +/** Clear the contents of the URL. */
> > > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > > +    pn_url_set_username(url, NULL);
> > > +    pn_url_set_password(url, NULL);
> > > +    pn_url_set_host(url, NULL);
> > > +    pn_url_set_port(url, NULL);
> > > +    pn_url_set_path(url, NULL);
> > > +    free(url->str); url->str = NULL;
> > > +}
> > > +
> > > +static inline int len(const char *str) { return str ? strlen(str) :
> 0; }
> > > +
> > > +/** Return the string form of a URL. */
> > > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > > +    int size = len(url->scheme) + len(url->username) +
> len(url->password)
> > > +        + len(url->host) + len(url->port) + len(url->path)
> > > +        + len("s://u:p@[h]:p/p");
> > > +    free(url->str);
> > > +    url->str = (char*)malloc(size);
> > > +    if (!url->str) return NULL;
> > > +
> > > +    int i = 0;
> > > +    if (url->scheme) i += snprintf(url->str+i, size-i, "%s://",
> > > url->scheme);
> > > +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> > > url->username);
> > > +    if (url->password) i += snprintf(url->str+i, size-i, ":%s",
> > > url->password);
> > > +    if (url->username || url->password) i += snprintf(url->str+i,
> size-i,
> > > "@");
> > > +    if (url->host) {
> > > +        if (strchr(url->host, ':')) i += snprintf(url->str+i, size-i,
> > > "[%s]", url->host);
> > > +        else i += snprintf(url->str+i, size-i, "%s", url->host);
> > > +    }
> > > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s",
> url->port);
> > > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s",
> url->path);
> > > +    return url->str;
> > > +}
> > > +
> > > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return
> url->scheme; }
> > > +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> > > url->username; }
> > > +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> > > url->password; }
> > > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return url->host; }
> > > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return url->port; }
> > > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return url->path; }
> > > +
> > > +#define SET(part) free(url->part); url->part = copy(part)
> > > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme) {
> > > SET(scheme); }
> > > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char
> *username) {
> > > SET(username); }
> > > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char
> *password) {
> > > SET(password); }
> > > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host) {
> > > SET(host); }
> > > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port) {
> > > SET(port); }
> > > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path) {
> > > SET(path); }
> > > +
> > > +
> > >
> > > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > > URL:
> > >
> http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> > >
> > >
> ==============================================================================
> > > --- qpid/proton/trunk/tests/python/proton_tests/url.py (original)
> > > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep 19
> 21:00:50
> > > 2014
> > > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> > >      def assertNotEqual(self, a, b):
> > >          assert a != b, "%s == %s" % (a, b)
> > >
> > > -    def assertUrl(self, u, scheme, user, password, host, port, path):
> > > -        self.assertEqual((u.scheme, u.user, u.password, u.host,
> u.port,
> > > u.path),
> > > -                         (scheme, user, password, host, port, path))
> > > +    def assertUrl(self, u, scheme, username, password, host, port,
> path):
> > > +        self.assertEqual((u.scheme, u.username, u.password, u.host,
> > > u.port, u.path),
> > > +                         (scheme, username, password, host, port,
> path))
> > >
> > >      def testUrl(self):
> > >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> > >
> > >      def testDefaults(self):
> > >          # Check that we allow None for scheme, port
> > > -        url = Url(user='me', password='secret', host='myhost',
> > > path='foobar')
> > > +        url = Url(username='me', password='secret', host='myhost',
> > > path='foobar')
> > >          self.assertEqual(str(url), "me:secret@myhost/foobar")
> > >          self.assertUrl(url, None, 'me', 'secret', 'myhost', None,
> > > 'foobar')
> > >
> > > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> > >      def testMissing(self):
> > >          self.assertUrl(Url(), None, None, None, None, None, None)
> > >          self.assertUrl(Url('amqp://'), 'amqp', None, None, None, None,
> > > None)
> > > -        self.assertUrl(Url('user@'), None, 'user', None, None, None,
> > > None)
> > > +        self.assertUrl(Url('username@'), None, 'username', None,
> None,
> > > None, None)
> > >          self.assertUrl(Url(':pass@'), None, '', 'pass', None, None,
> None)
> > >          self.assertUrl(Url('host'), None, None, None, 'host', None,
> None)
> > >          self.assertUrl(Url(':1234'), None, None, None, None, 1234,
> None)
> > >          self.assertUrl(Url('/path'), None, None, None, None, None,
> 'path')
> > >
> > > -        for s in ['amqp://', 'user@', ':pass@', ':1234', '/path']:
> > > +        for s in ['amqp://', 'username@', ':pass@', ':1234',
> '/path']:
> > >              self.assertEqual(s, str(Url(s)))
> > >
> > >          for s, full in [
> > >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > > +                ('username@', 'amqp://username@0.0.0.0:amqp'),
> > >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> > >                  (':1234', 'amqp://0.0.0.0:1234'),
> > >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> > >              self.assertEqual(str(Url(s).defaults()), full)
> > > -
> > > -        self.assertRaises(ValueError, Url, '')
> > >
> > >
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > > For additional commands, e-mail: commits-help@qpid.apache.org
> > >
> > >
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
> For additional commands, e-mail: dev-help@qpid.apache.org
>
>

Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Alan Conway <ac...@redhat.com>.
My bad, didn't run the java tests. Will fix ASAP and then give myself a
flogging.

On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> This seems to have broken the Java test runs:
> 
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> 
> 
> 
> On 19 September 2014 22:00, <ac...@apache.org> wrote:
> 
> > Author: aconway
> > Date: Fri Sep 19 21:00:50 2014
> > New Revision: 1626329
> >
> > URL: http://svn.apache.org/r1626329
> > Log:
> > PROTON-693: Python Url class to wrap C function pni_parse_url
> >
> > It was pointed out that pni_parse_url is an internal function and the
> > interface
> > is not suitable for public API.
> >
> > Rewrote the URL parser as a proper swigable C API pn_url_*. This gets rid
> > of the
> > need for previous swig insanity and is cleaner all round.
> >
> > Internally still uses the pni_parse_url parser, we can clean that up later.
> >
> > Added:
> >     qpid/proton/trunk/proton-c/include/proton/url.h
> >     qpid/proton/trunk/proton-c/src/url.c
> > Modified:
> >     qpid/proton/trunk/proton-c/CMakeLists.txt
> >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> >     qpid/proton/trunk/proton-c/bindings/php/php.i
> >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> >     qpid/proton/trunk/tests/python/proton_tests/url.py
> >
> > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19 21:00:50 2014
> > @@ -270,6 +270,7 @@ set (qpid-proton-core
> >    src/object/iterator.c
> >
> >    src/util.c
> > +  src/url.c
> >    src/error.c
> >    src/buffer.c
> >    src/parser.c
> >
> > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19 21:00:50
> > 2014
> > @@ -8,6 +8,7 @@
> >  #include <proton/messenger.h>
> >  #include <proton/ssl.h>
> >  #include <proton/driver_extras.h>
> > +#include <proton/url.h>
> >  %}
> >
> >  %include <cstring.i>
> >
> > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19 21:00:50 2014
> > @@ -29,6 +29,7 @@
> >  %header %{
> >  /* Include the headers needed by the code in this wrapper file */
> >  #include <proton/types.h>
> > +#include <proton/url.h>
> >  #include <proton/message.h>
> >  #include <proton/driver.h>
> >  #include <proton/driver_extras.h>
> >
> > Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i (original)
> > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri Sep 19
> > 21:00:50 2014
> > @@ -23,6 +23,7 @@
> >  #include <winsock2.h>
> >  #endif
> >  #include <proton/engine.h>
> > +#include <proton/url.h>
> >  #include <proton/message.h>
> >  #include <proton/sasl.h>
> >  #include <proton/driver.h>
> > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> >    }
> >  %}
> >
> > -
> > -/**
> > -   pni_parse_url(char* url, char **scheme, char **user, char **pass, char
> > **host, char **port, char **path)
> > -   The following type maps convert this into a python function that taks
> > a URL string argument
> > -   and returns a list of strings [scheme, user, pass, host, port, path]
> > -   This probably could be done more neatly.
> > -*/
> > -
> > -// Typemap to copy the url string as it will be modified by parse_url
> > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char *url (int
> > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > -  if (!SWIG_IsOK(res)) {
> > -    %argument_fail(res, "char *url", $symname, $argnum);
> > -  }
> > -  $1 = %new_array(n, $*1_ltype);
> > -  memcpy($1,t,sizeof(char)*n);
> > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > -  $1[n-1] = 0;
> > -}
> > -%typemap(freearg,match="in") char *url "free($1);";
> > -%typemap(argout) char *url "";
> > -
> > -// Typemap for char** return strings. Don't free them.
> > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0) "$1 = &temp;";
> > -%typemap(freearg,match="in") char **OUTSTR "";
> > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char **OUTSTR {
> > -    %append_output(SWIG_FromCharPtr(*$1));
> > -}
> > -
> > -// Typemap to initialize result as empty list
> > -%typemap(out) void "$result = PyList_New(0);";
> > -
> > -
> > -%apply char** OUTSTR {char **scheme, char **user, char **pass, char
> > **host, char **port, char **path};
> > -void pni_parse_url(char* url, char **scheme, char **user, char **pass,
> > char **host, char **port, char **path);
> > -%ignore pni_parse_url;
> > -
> >  %include "proton/cproton.i"
> >
> > Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
> > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri Sep 19
> > 21:00:50 2014
> > @@ -3657,114 +3657,98 @@ __all__ = [
> >
> >
> >  class Url(object):
> > -    """
> > -    Simple URL parser/constructor, handles URLs of the form:
> > +  """
> > +  Simple URL parser/constructor, handles URLs of the form:
> >
> > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> >
> > -    All components can be None if not specifeid in the URL string.
> > +  All components can be None if not specifeid in the URL string.
> >
> > -    The port can be specified as a service name, e.g. 'amqp' in the
> > -    URL string but Url.port always gives the integer value.
> > +  The port can be specified as a service name, e.g. 'amqp' in the
> > +  URL string but Url.port always gives the integer value.
> > +
> > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > +  @ivar user: Username
> > +  @ivar password: Password
> > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > +  @ivar port: Integer port.
> > +  @ivar host_port: Returns host:port
> > +  """
> > +
> > +  AMQPS = "amqps"
> > +  AMQP = "amqp"
> > +
> > +  class Port(int):
> > +    """An integer port number that can be constructed from a service name
> > string"""
> > +
> > +    def __new__(cls, value):
> > +      port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
> > +      setattr(port, 'name', str(value))
> > +      return port
> > +
> > +    def __eq__(self, x): return str(self) == x or int(self) == x
> > +    def __ne__(self, x): return not self == x
> > +    def __str__(self): return str(self.name)
> > +
> > +    @staticmethod
> > +    def port_int(value):
> > +      """Convert service, an integer or a service name, into an integer
> > port number."""
> > +      try:
> > +        return int(value)
> > +      except ValueError:
> > +        try:
> > +          return socket.getservbyname(value)
> > +        except socket.error:
> > +          raise ValueError("Not a valid port number or service name:
> > '%s'" % value)
> >
> > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > -    @ivar user: Username
> > -    @ivar password: Password
> > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > -    @ivar port: Integer port.
> > -    @ivar host_port: Returns host:port
> > +  def __init__(self, url=None, **kwargs):
> > +    """
> > +    @param url: URL string to parse.
> > +    @param kwargs: scheme, user, password, host, port, path.
> > +      If specified, replaces corresponding part in url string.
> >      """
> > +    if url:
> > +      self._url = pn_url_parse(str(url))
> > +      if not self._url: raise ValueError("Invalid URL '%s'" % url)
> > +    else:
> > +      self._url = pn_url()
> > +    for k in kwargs:            # Let kwargs override values parsed from
> > url
> > +      getattr(self, k)          # Check for invalid kwargs
> > +      setattr(self, k, kwargs[k])
> > +
> > +  class PartDescriptor(object):
> > +    def __init__(self, part):
> > +      self.getter = globals()["pn_url_%s" % part]
> > +      self.setter = globals()["pn_url_set_%s" % part]
> > +    def __get__(self, obj, type=None): return self.getter(obj._url)
> > +    def __set__(self, obj, value): return self.setter(obj._url,
> > str(value))
> > +
> > +  scheme = PartDescriptor('scheme')
> > +  username = PartDescriptor('username')
> > +  password = PartDescriptor('password')
> > +  host = PartDescriptor('host')
> > +  path = PartDescriptor('path')
> > +
> > +  @property
> > +  def port(self):
> > +    portstr = pn_url_port(self._url)
> > +    return portstr and Url.Port(portstr)
> > +
> > +  @port.setter
> > +  def port(self, value):
> > +    if value is None: pn_url_set_port(self._url, None)
> > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> >
> > -    AMQPS = "amqps"
> > -    AMQP = "amqp"
> > +  def __str__(self): return pn_url_str(self._url)
> >
> > -    class Port(int):
> > -      """An integer port number that can also have an associated service
> > name string"""
> > +  def __repr__(self): return "Url(%r)" % str(self)
> >
> > -      def __new__(cls, value):
> > -        port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
> > -        setattr(port, 'name', str(value))
> > -        return port
> > -
> > -      def __eq__(self, x): return str(self) == x or int(self) == x
> > -      def __ne__(self, x): return not self == x
> > -      def __str__(self): return str(self.name)
> > -
> > -      @staticmethod
> > -      def port_int(value):
> > -        """Convert service, an integer or a service name, into an integer
> > port number."""
> > -        try:
> > -          return int(value)
> > -        except ValueError:
> > -          try:
> > -            return socket.getservbyname(value)
> > -          except socket.error:
> > -            raise ValueError("Not a valid port number or service name:
> > '%s'" % value)
> > -
> > -    def __init__(self, url=None, **kwargs):
> > -        """
> > -        @param url: String or Url instance to parse or copy.
> > -        @param kwargs: URL fields: scheme, user, password, host, port,
> > path.
> > -            If specified, replaces corresponding component in url.
> > -        """
> > -
> > -        fields = ['scheme', 'user', 'password', 'host', 'port', 'path']
> > -
> > -        for f in fields: setattr(self, f, None)
> > -        for k in kwargs: getattr(self, k) # Check for invalid kwargs
> > -
> > -        if isinstance(url, Url): # Copy from another Url instance.
> > -            self.__dict__.update(url.__dict__)
> > -        elif url is not None:   # Parse from url
> > -            parts = pni_parse_url(str(url))
> > -            if not filter(None, parts): raise ValueError("Invalid AMQP
> > URL: '%s'" % url)
> > -            self.scheme, self.user, self.password, self.host, port,
> > self.path = parts
> > -            if not self.host: self.host = None
> > -            self.port = port and self.Port(port)
> > -
> > -        # Let kwargs override values previously set from url
> > -        for field in fields:
> > -            setattr(self, field, kwargs.get(field, getattr(self, field)))
> > -
> > -    def __repr__(self):
> > -        return "Url(%r)" % str(self)
> > -
> > -    def __str__(self):
> > -        s = ""
> > -        if self.scheme:
> > -            s += "%s://" % self.scheme
> > -        if self.user:
> > -            s += self.user
> > -        if self.password:
> > -            s += ":%s" % self.password
> > -        if self.user or self.password:
> > -            s += '@'
> > -        if self.host and ':' in self.host:
> > -            s += "[%s]" % self.host
> > -        elif self.host:
> > -            s += self.host
> > -        if self.port:
> > -            s += ":%s" % self.port
> > -        if self.path:
> > -            s += "/%s" % self.path
> > -        return s
> > -
> > -    def __eq__(self, url):
> > -        return \
> > -            self.scheme == url.scheme and \
> > -            self.user == url.user and self.password == url.password and \
> > -            self.host == url.host and self.port == url.port and \
> > -            self.path == url.path
> > -
> > -    def __ne__(self, url):
> > -        return not self.__eq__(url)
> > -
> > -    def defaults(self):
> > -        """
> > -        Fill in missing values with defaults
> > -        @return: self
> > -        """
> > -        self.scheme = self.scheme or self.AMQP
> > -        self.host = self.host or '0.0.0.0'
> > -        self.port = self.port or self.Port(self.scheme)
> > -        return self
> > +  def defaults(self):
> > +    """
> > +    Fill in missing values (scheme, host or port) with defaults
> > +    @return: self
> > +    """
> > +    self.scheme = self.scheme or self.AMQP
> > +    self.host = self.host or '0.0.0.0'
> > +    self.port = self.port or self.Port(self.scheme)
> > +    return self
> >
> > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19 21:00:50
> > 2014
> > @@ -26,8 +26,8 @@
> >  #include <proton/messenger.h>
> >  #include <proton/ssl.h>
> >  #include <proton/driver_extras.h>
> > -
> >  #include <proton/types.h>
> > +#include <proton/url.h>
> >
> >  #include <uuid/uuid.h>
> >  %}
> >
> > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/include/proton/cproton.i (original)
> > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri Sep 19
> > 21:00:50 2014
> > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return (pn_delivery_t *)
> > x; }
> >    pn_transport_t *pn_cast_pn_transport(void *x) { return (pn_transport_t
> > *) x; }
> >  %}
> > +
> > +%include "proton/url.h"
> > +
> >
> > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19 21:00:50
> > 2014
> > @@ -0,0 +1,83 @@
> > +#ifndef PROTON_URL_H
> > +#define PROTON_URL_H
> > +/*
> > + * 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.
> > + */
> > +
> > +#include <proton/import_export.h>
> > +
> > +/** @file
> > + * URL API for parsing URLs.
> > + *
> > + * @defgroup url URL
> > + * @{
> > + */
> > +
> > +/** A parsed URL */
> > +typedef struct pn_url_t pn_url_t;
> > +
> > +/** Create an empty URL */
> > +PN_EXTERN pn_url_t *pn_url(void);
> > +
> > +/** Parse a string URL as a pn_url_t.
> > + *@param[in] url A URL string.
> > + *@return The parsed pn_url_t or NULL if url is not a valid URL string.
> > + */
> > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > +
> > +/** Free a URL */
> > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > +
> > +/** Clear the contents of the URL. */
> > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > +
> > +/** Return the string form of a URL. Owned by the pn_url_t.*/
> > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > +
> > +/**
> > + *@name Getters for parts of the URL.
> > + *
> > + *Values belong to the URL. May return NULL if the value is not set.
> > + *
> > + *@{
> > + */
> > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > +///@}
> > +
> > +/**
> > + *@name Setters for parts of the URL.
> > + *
> > + *Values are copied. Value can be NULL to indicate the part is not set.
> > + *
> > + *@{
> > + */
> > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme);
> > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char *username);
> > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char *password);
> > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host);
> > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port);
> > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path);
> > +///@}
> > +
> > +///@}
> > +#endif
> >
> > Added: qpid/proton/trunk/proton-c/src/url.c
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50 2014
> > @@ -0,0 +1,127 @@
> > +/*
> > + *
> > + * 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.
> > + *
> > + */
> > +
> > +#include <proton/url.h>
> > +#include <proton/util.h>
> > +#include <stdlib.h>
> > +#include <string.h>
> > +#include <stdio.h>
> > +
> > +static char* copy(const char* str) {
> > +    if (str ==  NULL) return NULL;
> > +    char *str2 = (char*)malloc(strlen(str));
> > +    if (str2) strcpy(str2, str);
> > +    return str2;
> > +}
> > +
> > +struct pn_url_t {
> > +    char *scheme;
> > +    char *username;
> > +    char *password;
> > +    char *host;
> > +    char *port;
> > +    char *path;
> > +    char *str;
> > +};
> > +
> > +PN_EXTERN pn_url_t *pn_url() {
> > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > +    memset(url, 0, sizeof(*url));
> > +    return url;
> > +}
> > +
> > +/** Parse a string URL as a pn_url_t.
> > + *@param[in] url A URL string.
> > + *@return The parsed pn_url_t or NULL if url is not a valid URL string.
> > + */
> > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > +    if (!str || !*str)          /* Empty string or NULL is illegal. */
> > +        return NULL;
> > +
> > +    pn_url_t *url = pn_url();
> > +    char *str2 = copy(str);         /* FIXME aconway 2014-09-19: clean up
> > */
> > +    pni_parse_url(str2, &url->scheme, &url->username, &url->password,
> > &url->host, &url->port, &url->path);
> > +    url->scheme = copy(url->scheme);
> > +    url->username = copy(url->username);
> > +    url->password = copy(url->password);
> > +    url->host = (url->host && !*url->host) ? NULL : copy(url->host);
> > +    url->port = copy(url->port);
> > +    url->path = copy(url->path);
> > +    return url;
> > +}
> > +
> > +/** Free a URL */
> > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > +    pn_url_clear(url);
> > +    free(url);
> > +}
> > +
> > +/** Clear the contents of the URL. */
> > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > +    pn_url_set_username(url, NULL);
> > +    pn_url_set_password(url, NULL);
> > +    pn_url_set_host(url, NULL);
> > +    pn_url_set_port(url, NULL);
> > +    pn_url_set_path(url, NULL);
> > +    free(url->str); url->str = NULL;
> > +}
> > +
> > +static inline int len(const char *str) { return str ? strlen(str) : 0; }
> > +
> > +/** Return the string form of a URL. */
> > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > +    int size = len(url->scheme) + len(url->username) + len(url->password)
> > +        + len(url->host) + len(url->port) + len(url->path)
> > +        + len("s://u:p@[h]:p/p");
> > +    free(url->str);
> > +    url->str = (char*)malloc(size);
> > +    if (!url->str) return NULL;
> > +
> > +    int i = 0;
> > +    if (url->scheme) i += snprintf(url->str+i, size-i, "%s://",
> > url->scheme);
> > +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> > url->username);
> > +    if (url->password) i += snprintf(url->str+i, size-i, ":%s",
> > url->password);
> > +    if (url->username || url->password) i += snprintf(url->str+i, size-i,
> > "@");
> > +    if (url->host) {
> > +        if (strchr(url->host, ':')) i += snprintf(url->str+i, size-i,
> > "[%s]", url->host);
> > +        else i += snprintf(url->str+i, size-i, "%s", url->host);
> > +    }
> > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s", url->port);
> > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s", url->path);
> > +    return url->str;
> > +}
> > +
> > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return url->scheme; }
> > +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> > url->username; }
> > +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> > url->password; }
> > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return url->host; }
> > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return url->port; }
> > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return url->path; }
> > +
> > +#define SET(part) free(url->part); url->part = copy(part)
> > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme) {
> > SET(scheme); }
> > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char *username) {
> > SET(username); }
> > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char *password) {
> > SET(password); }
> > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host) {
> > SET(host); }
> > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port) {
> > SET(port); }
> > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path) {
> > SET(path); }
> > +
> > +
> >
> > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> >
> > ==============================================================================
> > --- qpid/proton/trunk/tests/python/proton_tests/url.py (original)
> > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep 19 21:00:50
> > 2014
> > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> >      def assertNotEqual(self, a, b):
> >          assert a != b, "%s == %s" % (a, b)
> >
> > -    def assertUrl(self, u, scheme, user, password, host, port, path):
> > -        self.assertEqual((u.scheme, u.user, u.password, u.host, u.port,
> > u.path),
> > -                         (scheme, user, password, host, port, path))
> > +    def assertUrl(self, u, scheme, username, password, host, port, path):
> > +        self.assertEqual((u.scheme, u.username, u.password, u.host,
> > u.port, u.path),
> > +                         (scheme, username, password, host, port, path))
> >
> >      def testUrl(self):
> >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> >
> >      def testDefaults(self):
> >          # Check that we allow None for scheme, port
> > -        url = Url(user='me', password='secret', host='myhost',
> > path='foobar')
> > +        url = Url(username='me', password='secret', host='myhost',
> > path='foobar')
> >          self.assertEqual(str(url), "me:secret@myhost/foobar")
> >          self.assertUrl(url, None, 'me', 'secret', 'myhost', None,
> > 'foobar')
> >
> > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> >      def testMissing(self):
> >          self.assertUrl(Url(), None, None, None, None, None, None)
> >          self.assertUrl(Url('amqp://'), 'amqp', None, None, None, None,
> > None)
> > -        self.assertUrl(Url('user@'), None, 'user', None, None, None,
> > None)
> > +        self.assertUrl(Url('username@'), None, 'username', None, None,
> > None, None)
> >          self.assertUrl(Url(':pass@'), None, '', 'pass', None, None, None)
> >          self.assertUrl(Url('host'), None, None, None, 'host', None, None)
> >          self.assertUrl(Url(':1234'), None, None, None, None, 1234, None)
> >          self.assertUrl(Url('/path'), None, None, None, None, None, 'path')
> >
> > -        for s in ['amqp://', 'user@', ':pass@', ':1234', '/path']:
> > +        for s in ['amqp://', 'username@', ':pass@', ':1234', '/path']:
> >              self.assertEqual(s, str(Url(s)))
> >
> >          for s, full in [
> >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > +                ('username@', 'amqp://username@0.0.0.0:amqp'),
> >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> >                  (':1234', 'amqp://0.0.0.0:1234'),
> >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> >              self.assertEqual(str(Url(s).defaults()), full)
> > -
> > -        self.assertRaises(ValueError, Url, '')
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > For additional commands, e-mail: commits-help@qpid.apache.org
> >
> >



Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Alan Conway <ac...@redhat.com>.
My bad, didn't run the java tests. Will fix ASAP and then give myself a
flogging.

On Mon, 2014-09-22 at 19:50 +0100, Robbie Gemmell wrote:
> This seems to have broken the Java test runs:
> 
> https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/
> 
> 
> 
> On 19 September 2014 22:00, <ac...@apache.org> wrote:
> 
> > Author: aconway
> > Date: Fri Sep 19 21:00:50 2014
> > New Revision: 1626329
> >
> > URL: http://svn.apache.org/r1626329
> > Log:
> > PROTON-693: Python Url class to wrap C function pni_parse_url
> >
> > It was pointed out that pni_parse_url is an internal function and the
> > interface
> > is not suitable for public API.
> >
> > Rewrote the URL parser as a proper swigable C API pn_url_*. This gets rid
> > of the
> > need for previous swig insanity and is cleaner all round.
> >
> > Internally still uses the pni_parse_url parser, we can clean that up later.
> >
> > Added:
> >     qpid/proton/trunk/proton-c/include/proton/url.h
> >     qpid/proton/trunk/proton-c/src/url.c
> > Modified:
> >     qpid/proton/trunk/proton-c/CMakeLists.txt
> >     qpid/proton/trunk/proton-c/bindings/perl/perl.i
> >     qpid/proton/trunk/proton-c/bindings/php/php.i
> >     qpid/proton/trunk/proton-c/bindings/python/cproton.i
> >     qpid/proton/trunk/proton-c/bindings/python/proton.py
> >     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> >     qpid/proton/trunk/proton-c/include/proton/cproton.i
> >     qpid/proton/trunk/tests/python/proton_tests/url.py
> >
> > Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> > +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19 21:00:50 2014
> > @@ -270,6 +270,7 @@ set (qpid-proton-core
> >    src/object/iterator.c
> >
> >    src/util.c
> > +  src/url.c
> >    src/error.c
> >    src/buffer.c
> >    src/parser.c
> >
> > Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> > +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19 21:00:50
> > 2014
> > @@ -8,6 +8,7 @@
> >  #include <proton/messenger.h>
> >  #include <proton/ssl.h>
> >  #include <proton/driver_extras.h>
> > +#include <proton/url.h>
> >  %}
> >
> >  %include <cstring.i>
> >
> > Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> > +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19 21:00:50 2014
> > @@ -29,6 +29,7 @@
> >  %header %{
> >  /* Include the headers needed by the code in this wrapper file */
> >  #include <proton/types.h>
> > +#include <proton/url.h>
> >  #include <proton/message.h>
> >  #include <proton/driver.h>
> >  #include <proton/driver_extras.h>
> >
> > Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/bindings/python/cproton.i (original)
> > +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri Sep 19
> > 21:00:50 2014
> > @@ -23,6 +23,7 @@
> >  #include <winsock2.h>
> >  #endif
> >  #include <proton/engine.h>
> > +#include <proton/url.h>
> >  #include <proton/message.h>
> >  #include <proton/sasl.h>
> >  #include <proton/driver.h>
> > @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
> >    }
> >  %}
> >
> > -
> > -/**
> > -   pni_parse_url(char* url, char **scheme, char **user, char **pass, char
> > **host, char **port, char **path)
> > -   The following type maps convert this into a python function that taks
> > a URL string argument
> > -   and returns a list of strings [scheme, user, pass, host, port, path]
> > -   This probably could be done more neatly.
> > -*/
> > -
> > -// Typemap to copy the url string as it will be modified by parse_url
> > -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char *url (int
> > res, char *t = 0, size_t n = 0, int alloc = 0) {
> > -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> > -  if (!SWIG_IsOK(res)) {
> > -    %argument_fail(res, "char *url", $symname, $argnum);
> > -  }
> > -  $1 = %new_array(n, $*1_ltype);
> > -  memcpy($1,t,sizeof(char)*n);
> > -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> > -  $1[n-1] = 0;
> > -}
> > -%typemap(freearg,match="in") char *url "free($1);";
> > -%typemap(argout) char *url "";
> > -
> > -// Typemap for char** return strings. Don't free them.
> > -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0) "$1 = &temp;";
> > -%typemap(freearg,match="in") char **OUTSTR "";
> > -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char **OUTSTR {
> > -    %append_output(SWIG_FromCharPtr(*$1));
> > -}
> > -
> > -// Typemap to initialize result as empty list
> > -%typemap(out) void "$result = PyList_New(0);";
> > -
> > -
> > -%apply char** OUTSTR {char **scheme, char **user, char **pass, char
> > **host, char **port, char **path};
> > -void pni_parse_url(char* url, char **scheme, char **user, char **pass,
> > char **host, char **port, char **path);
> > -%ignore pni_parse_url;
> > -
> >  %include "proton/cproton.i"
> >
> > Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
> > +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri Sep 19
> > 21:00:50 2014
> > @@ -3657,114 +3657,98 @@ __all__ = [
> >
> >
> >  class Url(object):
> > -    """
> > -    Simple URL parser/constructor, handles URLs of the form:
> > +  """
> > +  Simple URL parser/constructor, handles URLs of the form:
> >
> > -      <scheme>://<user>:<password>@<host>:<port>/<path>
> > +    <scheme>://<user>:<password>@<host>:<port>/<path>
> >
> > -    All components can be None if not specifeid in the URL string.
> > +  All components can be None if not specifeid in the URL string.
> >
> > -    The port can be specified as a service name, e.g. 'amqp' in the
> > -    URL string but Url.port always gives the integer value.
> > +  The port can be specified as a service name, e.g. 'amqp' in the
> > +  URL string but Url.port always gives the integer value.
> > +
> > +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > +  @ivar user: Username
> > +  @ivar password: Password
> > +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > +  @ivar port: Integer port.
> > +  @ivar host_port: Returns host:port
> > +  """
> > +
> > +  AMQPS = "amqps"
> > +  AMQP = "amqp"
> > +
> > +  class Port(int):
> > +    """An integer port number that can be constructed from a service name
> > string"""
> > +
> > +    def __new__(cls, value):
> > +      port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
> > +      setattr(port, 'name', str(value))
> > +      return port
> > +
> > +    def __eq__(self, x): return str(self) == x or int(self) == x
> > +    def __ne__(self, x): return not self == x
> > +    def __str__(self): return str(self.name)
> > +
> > +    @staticmethod
> > +    def port_int(value):
> > +      """Convert service, an integer or a service name, into an integer
> > port number."""
> > +      try:
> > +        return int(value)
> > +      except ValueError:
> > +        try:
> > +          return socket.getservbyname(value)
> > +        except socket.error:
> > +          raise ValueError("Not a valid port number or service name:
> > '%s'" % value)
> >
> > -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> > -    @ivar user: Username
> > -    @ivar password: Password
> > -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> > -    @ivar port: Integer port.
> > -    @ivar host_port: Returns host:port
> > +  def __init__(self, url=None, **kwargs):
> > +    """
> > +    @param url: URL string to parse.
> > +    @param kwargs: scheme, user, password, host, port, path.
> > +      If specified, replaces corresponding part in url string.
> >      """
> > +    if url:
> > +      self._url = pn_url_parse(str(url))
> > +      if not self._url: raise ValueError("Invalid URL '%s'" % url)
> > +    else:
> > +      self._url = pn_url()
> > +    for k in kwargs:            # Let kwargs override values parsed from
> > url
> > +      getattr(self, k)          # Check for invalid kwargs
> > +      setattr(self, k, kwargs[k])
> > +
> > +  class PartDescriptor(object):
> > +    def __init__(self, part):
> > +      self.getter = globals()["pn_url_%s" % part]
> > +      self.setter = globals()["pn_url_set_%s" % part]
> > +    def __get__(self, obj, type=None): return self.getter(obj._url)
> > +    def __set__(self, obj, value): return self.setter(obj._url,
> > str(value))
> > +
> > +  scheme = PartDescriptor('scheme')
> > +  username = PartDescriptor('username')
> > +  password = PartDescriptor('password')
> > +  host = PartDescriptor('host')
> > +  path = PartDescriptor('path')
> > +
> > +  @property
> > +  def port(self):
> > +    portstr = pn_url_port(self._url)
> > +    return portstr and Url.Port(portstr)
> > +
> > +  @port.setter
> > +  def port(self, value):
> > +    if value is None: pn_url_set_port(self._url, None)
> > +    else: pn_url_set_port(self._url, str(Url.Port(value)))
> >
> > -    AMQPS = "amqps"
> > -    AMQP = "amqp"
> > +  def __str__(self): return pn_url_str(self._url)
> >
> > -    class Port(int):
> > -      """An integer port number that can also have an associated service
> > name string"""
> > +  def __repr__(self): return "Url(%r)" % str(self)
> >
> > -      def __new__(cls, value):
> > -        port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
> > -        setattr(port, 'name', str(value))
> > -        return port
> > -
> > -      def __eq__(self, x): return str(self) == x or int(self) == x
> > -      def __ne__(self, x): return not self == x
> > -      def __str__(self): return str(self.name)
> > -
> > -      @staticmethod
> > -      def port_int(value):
> > -        """Convert service, an integer or a service name, into an integer
> > port number."""
> > -        try:
> > -          return int(value)
> > -        except ValueError:
> > -          try:
> > -            return socket.getservbyname(value)
> > -          except socket.error:
> > -            raise ValueError("Not a valid port number or service name:
> > '%s'" % value)
> > -
> > -    def __init__(self, url=None, **kwargs):
> > -        """
> > -        @param url: String or Url instance to parse or copy.
> > -        @param kwargs: URL fields: scheme, user, password, host, port,
> > path.
> > -            If specified, replaces corresponding component in url.
> > -        """
> > -
> > -        fields = ['scheme', 'user', 'password', 'host', 'port', 'path']
> > -
> > -        for f in fields: setattr(self, f, None)
> > -        for k in kwargs: getattr(self, k) # Check for invalid kwargs
> > -
> > -        if isinstance(url, Url): # Copy from another Url instance.
> > -            self.__dict__.update(url.__dict__)
> > -        elif url is not None:   # Parse from url
> > -            parts = pni_parse_url(str(url))
> > -            if not filter(None, parts): raise ValueError("Invalid AMQP
> > URL: '%s'" % url)
> > -            self.scheme, self.user, self.password, self.host, port,
> > self.path = parts
> > -            if not self.host: self.host = None
> > -            self.port = port and self.Port(port)
> > -
> > -        # Let kwargs override values previously set from url
> > -        for field in fields:
> > -            setattr(self, field, kwargs.get(field, getattr(self, field)))
> > -
> > -    def __repr__(self):
> > -        return "Url(%r)" % str(self)
> > -
> > -    def __str__(self):
> > -        s = ""
> > -        if self.scheme:
> > -            s += "%s://" % self.scheme
> > -        if self.user:
> > -            s += self.user
> > -        if self.password:
> > -            s += ":%s" % self.password
> > -        if self.user or self.password:
> > -            s += '@'
> > -        if self.host and ':' in self.host:
> > -            s += "[%s]" % self.host
> > -        elif self.host:
> > -            s += self.host
> > -        if self.port:
> > -            s += ":%s" % self.port
> > -        if self.path:
> > -            s += "/%s" % self.path
> > -        return s
> > -
> > -    def __eq__(self, url):
> > -        return \
> > -            self.scheme == url.scheme and \
> > -            self.user == url.user and self.password == url.password and \
> > -            self.host == url.host and self.port == url.port and \
> > -            self.path == url.path
> > -
> > -    def __ne__(self, url):
> > -        return not self.__eq__(url)
> > -
> > -    def defaults(self):
> > -        """
> > -        Fill in missing values with defaults
> > -        @return: self
> > -        """
> > -        self.scheme = self.scheme or self.AMQP
> > -        self.host = self.host or '0.0.0.0'
> > -        self.port = self.port or self.Port(self.scheme)
> > -        return self
> > +  def defaults(self):
> > +    """
> > +    Fill in missing values (scheme, host or port) with defaults
> > +    @return: self
> > +    """
> > +    self.scheme = self.scheme or self.AMQP
> > +    self.host = self.host or '0.0.0.0'
> > +    self.port = self.port or self.Port(self.scheme)
> > +    return self
> >
> > Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> > +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19 21:00:50
> > 2014
> > @@ -26,8 +26,8 @@
> >  #include <proton/messenger.h>
> >  #include <proton/ssl.h>
> >  #include <proton/driver_extras.h>
> > -
> >  #include <proton/types.h>
> > +#include <proton/url.h>
> >
> >  #include <uuid/uuid.h>
> >  %}
> >
> > Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/include/proton/cproton.i (original)
> > +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri Sep 19
> > 21:00:50 2014
> > @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
> >    pn_delivery_t *pn_cast_pn_delivery(void *x) { return (pn_delivery_t *)
> > x; }
> >    pn_transport_t *pn_cast_pn_transport(void *x) { return (pn_transport_t
> > *) x; }
> >  %}
> > +
> > +%include "proton/url.h"
> > +
> >
> > Added: qpid/proton/trunk/proton-c/include/proton/url.h
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> > +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19 21:00:50
> > 2014
> > @@ -0,0 +1,83 @@
> > +#ifndef PROTON_URL_H
> > +#define PROTON_URL_H
> > +/*
> > + * 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.
> > + */
> > +
> > +#include <proton/import_export.h>
> > +
> > +/** @file
> > + * URL API for parsing URLs.
> > + *
> > + * @defgroup url URL
> > + * @{
> > + */
> > +
> > +/** A parsed URL */
> > +typedef struct pn_url_t pn_url_t;
> > +
> > +/** Create an empty URL */
> > +PN_EXTERN pn_url_t *pn_url(void);
> > +
> > +/** Parse a string URL as a pn_url_t.
> > + *@param[in] url A URL string.
> > + *@return The parsed pn_url_t or NULL if url is not a valid URL string.
> > + */
> > +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> > +
> > +/** Free a URL */
> > +PN_EXTERN void pn_url_free(pn_url_t *url);
> > +
> > +/** Clear the contents of the URL. */
> > +PN_EXTERN void pn_url_clear(pn_url_t *url);
> > +
> > +/** Return the string form of a URL. Owned by the pn_url_t.*/
> > +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> > +
> > +/**
> > + *@name Getters for parts of the URL.
> > + *
> > + *Values belong to the URL. May return NULL if the value is not set.
> > + *
> > + *@{
> > + */
> > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> > +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> > +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> > +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> > +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> > +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> > +///@}
> > +
> > +/**
> > + *@name Setters for parts of the URL.
> > + *
> > + *Values are copied. Value can be NULL to indicate the part is not set.
> > + *
> > + *@{
> > + */
> > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme);
> > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char *username);
> > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char *password);
> > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host);
> > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port);
> > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path);
> > +///@}
> > +
> > +///@}
> > +#endif
> >
> > Added: qpid/proton/trunk/proton-c/src/url.c
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
> >
> > ==============================================================================
> > --- qpid/proton/trunk/proton-c/src/url.c (added)
> > +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50 2014
> > @@ -0,0 +1,127 @@
> > +/*
> > + *
> > + * 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.
> > + *
> > + */
> > +
> > +#include <proton/url.h>
> > +#include <proton/util.h>
> > +#include <stdlib.h>
> > +#include <string.h>
> > +#include <stdio.h>
> > +
> > +static char* copy(const char* str) {
> > +    if (str ==  NULL) return NULL;
> > +    char *str2 = (char*)malloc(strlen(str));
> > +    if (str2) strcpy(str2, str);
> > +    return str2;
> > +}
> > +
> > +struct pn_url_t {
> > +    char *scheme;
> > +    char *username;
> > +    char *password;
> > +    char *host;
> > +    char *port;
> > +    char *path;
> > +    char *str;
> > +};
> > +
> > +PN_EXTERN pn_url_t *pn_url() {
> > +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> > +    memset(url, 0, sizeof(*url));
> > +    return url;
> > +}
> > +
> > +/** Parse a string URL as a pn_url_t.
> > + *@param[in] url A URL string.
> > + *@return The parsed pn_url_t or NULL if url is not a valid URL string.
> > + */
> > +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> > +    if (!str || !*str)          /* Empty string or NULL is illegal. */
> > +        return NULL;
> > +
> > +    pn_url_t *url = pn_url();
> > +    char *str2 = copy(str);         /* FIXME aconway 2014-09-19: clean up
> > */
> > +    pni_parse_url(str2, &url->scheme, &url->username, &url->password,
> > &url->host, &url->port, &url->path);
> > +    url->scheme = copy(url->scheme);
> > +    url->username = copy(url->username);
> > +    url->password = copy(url->password);
> > +    url->host = (url->host && !*url->host) ? NULL : copy(url->host);
> > +    url->port = copy(url->port);
> > +    url->path = copy(url->path);
> > +    return url;
> > +}
> > +
> > +/** Free a URL */
> > +PN_EXTERN void pn_url_free(pn_url_t *url) {
> > +    pn_url_clear(url);
> > +    free(url);
> > +}
> > +
> > +/** Clear the contents of the URL. */
> > +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> > +    pn_url_set_username(url, NULL);
> > +    pn_url_set_password(url, NULL);
> > +    pn_url_set_host(url, NULL);
> > +    pn_url_set_port(url, NULL);
> > +    pn_url_set_path(url, NULL);
> > +    free(url->str); url->str = NULL;
> > +}
> > +
> > +static inline int len(const char *str) { return str ? strlen(str) : 0; }
> > +
> > +/** Return the string form of a URL. */
> > +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> > +    int size = len(url->scheme) + len(url->username) + len(url->password)
> > +        + len(url->host) + len(url->port) + len(url->path)
> > +        + len("s://u:p@[h]:p/p");
> > +    free(url->str);
> > +    url->str = (char*)malloc(size);
> > +    if (!url->str) return NULL;
> > +
> > +    int i = 0;
> > +    if (url->scheme) i += snprintf(url->str+i, size-i, "%s://",
> > url->scheme);
> > +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> > url->username);
> > +    if (url->password) i += snprintf(url->str+i, size-i, ":%s",
> > url->password);
> > +    if (url->username || url->password) i += snprintf(url->str+i, size-i,
> > "@");
> > +    if (url->host) {
> > +        if (strchr(url->host, ':')) i += snprintf(url->str+i, size-i,
> > "[%s]", url->host);
> > +        else i += snprintf(url->str+i, size-i, "%s", url->host);
> > +    }
> > +    if (url->port) i += snprintf(url->str+i, size-i, ":%s", url->port);
> > +    if (url->path) i += snprintf(url->str+i, size-i, "/%s", url->path);
> > +    return url->str;
> > +}
> > +
> > +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return url->scheme; }
> > +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> > url->username; }
> > +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> > url->password; }
> > +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return url->host; }
> > +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return url->port; }
> > +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return url->path; }
> > +
> > +#define SET(part) free(url->part); url->part = copy(part)
> > +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme) {
> > SET(scheme); }
> > +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char *username) {
> > SET(username); }
> > +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char *password) {
> > SET(password); }
> > +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host) {
> > SET(host); }
> > +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port) {
> > SET(port); }
> > +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path) {
> > SET(path); }
> > +
> > +
> >
> > Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> > URL:
> > http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
> >
> > ==============================================================================
> > --- qpid/proton/trunk/tests/python/proton_tests/url.py (original)
> > +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep 19 21:00:50
> > 2014
> > @@ -28,9 +28,9 @@ class UrlTest(common.Test):
> >      def assertNotEqual(self, a, b):
> >          assert a != b, "%s == %s" % (a, b)
> >
> > -    def assertUrl(self, u, scheme, user, password, host, port, path):
> > -        self.assertEqual((u.scheme, u.user, u.password, u.host, u.port,
> > u.path),
> > -                         (scheme, user, password, host, port, path))
> > +    def assertUrl(self, u, scheme, username, password, host, port, path):
> > +        self.assertEqual((u.scheme, u.username, u.password, u.host,
> > u.port, u.path),
> > +                         (scheme, username, password, host, port, path))
> >
> >      def testUrl(self):
> >          url = Url('amqp://me:secret@myhost:1234/foobar')
> > @@ -40,7 +40,7 @@ class UrlTest(common.Test):
> >
> >      def testDefaults(self):
> >          # Check that we allow None for scheme, port
> > -        url = Url(user='me', password='secret', host='myhost',
> > path='foobar')
> > +        url = Url(username='me', password='secret', host='myhost',
> > path='foobar')
> >          self.assertEqual(str(url), "me:secret@myhost/foobar")
> >          self.assertUrl(url, None, 'me', 'secret', 'myhost', None,
> > 'foobar')
> >
> > @@ -97,21 +97,19 @@ class UrlTest(common.Test):
> >      def testMissing(self):
> >          self.assertUrl(Url(), None, None, None, None, None, None)
> >          self.assertUrl(Url('amqp://'), 'amqp', None, None, None, None,
> > None)
> > -        self.assertUrl(Url('user@'), None, 'user', None, None, None,
> > None)
> > +        self.assertUrl(Url('username@'), None, 'username', None, None,
> > None, None)
> >          self.assertUrl(Url(':pass@'), None, '', 'pass', None, None, None)
> >          self.assertUrl(Url('host'), None, None, None, 'host', None, None)
> >          self.assertUrl(Url(':1234'), None, None, None, None, 1234, None)
> >          self.assertUrl(Url('/path'), None, None, None, None, None, 'path')
> >
> > -        for s in ['amqp://', 'user@', ':pass@', ':1234', '/path']:
> > +        for s in ['amqp://', 'username@', ':pass@', ':1234', '/path']:
> >              self.assertEqual(s, str(Url(s)))
> >
> >          for s, full in [
> >                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> > -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> > +                ('username@', 'amqp://username@0.0.0.0:amqp'),
> >                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
> >                  (':1234', 'amqp://0.0.0.0:1234'),
> >                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
> >              self.assertEqual(str(Url(s).defaults()), full)
> > -
> > -        self.assertRaises(ValueError, Url, '')
> >
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> > For additional commands, e-mail: commits-help@qpid.apache.org
> >
> >



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@qpid.apache.org
For additional commands, e-mail: dev-help@qpid.apache.org


Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Robbie Gemmell <ro...@gmail.com>.
This seems to have broken the Java test runs:

https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/



On 19 September 2014 22:00, <ac...@apache.org> wrote:

> Author: aconway
> Date: Fri Sep 19 21:00:50 2014
> New Revision: 1626329
>
> URL: http://svn.apache.org/r1626329
> Log:
> PROTON-693: Python Url class to wrap C function pni_parse_url
>
> It was pointed out that pni_parse_url is an internal function and the
> interface
> is not suitable for public API.
>
> Rewrote the URL parser as a proper swigable C API pn_url_*. This gets rid
> of the
> need for previous swig insanity and is cleaner all round.
>
> Internally still uses the pni_parse_url parser, we can clean that up later.
>
> Added:
>     qpid/proton/trunk/proton-c/include/proton/url.h
>     qpid/proton/trunk/proton-c/src/url.c
> Modified:
>     qpid/proton/trunk/proton-c/CMakeLists.txt
>     qpid/proton/trunk/proton-c/bindings/perl/perl.i
>     qpid/proton/trunk/proton-c/bindings/php/php.i
>     qpid/proton/trunk/proton-c/bindings/python/cproton.i
>     qpid/proton/trunk/proton-c/bindings/python/proton.py
>     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
>     qpid/proton/trunk/proton-c/include/proton/cproton.i
>     qpid/proton/trunk/tests/python/proton_tests/url.py
>
> Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19 21:00:50 2014
> @@ -270,6 +270,7 @@ set (qpid-proton-core
>    src/object/iterator.c
>
>    src/util.c
> +  src/url.c
>    src/error.c
>    src/buffer.c
>    src/parser.c
>
> Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19 21:00:50
> 2014
> @@ -8,6 +8,7 @@
>  #include <proton/messenger.h>
>  #include <proton/ssl.h>
>  #include <proton/driver_extras.h>
> +#include <proton/url.h>
>  %}
>
>  %include <cstring.i>
>
> Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19 21:00:50 2014
> @@ -29,6 +29,7 @@
>  %header %{
>  /* Include the headers needed by the code in this wrapper file */
>  #include <proton/types.h>
> +#include <proton/url.h>
>  #include <proton/message.h>
>  #include <proton/driver.h>
>  #include <proton/driver_extras.h>
>
> Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/bindings/python/cproton.i (original)
> +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri Sep 19
> 21:00:50 2014
> @@ -23,6 +23,7 @@
>  #include <winsock2.h>
>  #endif
>  #include <proton/engine.h>
> +#include <proton/url.h>
>  #include <proton/message.h>
>  #include <proton/sasl.h>
>  #include <proton/driver.h>
> @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
>    }
>  %}
>
> -
> -/**
> -   pni_parse_url(char* url, char **scheme, char **user, char **pass, char
> **host, char **port, char **path)
> -   The following type maps convert this into a python function that taks
> a URL string argument
> -   and returns a list of strings [scheme, user, pass, host, port, path]
> -   This probably could be done more neatly.
> -*/
> -
> -// Typemap to copy the url string as it will be modified by parse_url
> -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char *url (int
> res, char *t = 0, size_t n = 0, int alloc = 0) {
> -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> -  if (!SWIG_IsOK(res)) {
> -    %argument_fail(res, "char *url", $symname, $argnum);
> -  }
> -  $1 = %new_array(n, $*1_ltype);
> -  memcpy($1,t,sizeof(char)*n);
> -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> -  $1[n-1] = 0;
> -}
> -%typemap(freearg,match="in") char *url "free($1);";
> -%typemap(argout) char *url "";
> -
> -// Typemap for char** return strings. Don't free them.
> -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0) "$1 = &temp;";
> -%typemap(freearg,match="in") char **OUTSTR "";
> -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char **OUTSTR {
> -    %append_output(SWIG_FromCharPtr(*$1));
> -}
> -
> -// Typemap to initialize result as empty list
> -%typemap(out) void "$result = PyList_New(0);";
> -
> -
> -%apply char** OUTSTR {char **scheme, char **user, char **pass, char
> **host, char **port, char **path};
> -void pni_parse_url(char* url, char **scheme, char **user, char **pass,
> char **host, char **port, char **path);
> -%ignore pni_parse_url;
> -
>  %include "proton/cproton.i"
>
> Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
> +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri Sep 19
> 21:00:50 2014
> @@ -3657,114 +3657,98 @@ __all__ = [
>
>
>  class Url(object):
> -    """
> -    Simple URL parser/constructor, handles URLs of the form:
> +  """
> +  Simple URL parser/constructor, handles URLs of the form:
>
> -      <scheme>://<user>:<password>@<host>:<port>/<path>
> +    <scheme>://<user>:<password>@<host>:<port>/<path>
>
> -    All components can be None if not specifeid in the URL string.
> +  All components can be None if not specifeid in the URL string.
>
> -    The port can be specified as a service name, e.g. 'amqp' in the
> -    URL string but Url.port always gives the integer value.
> +  The port can be specified as a service name, e.g. 'amqp' in the
> +  URL string but Url.port always gives the integer value.
> +
> +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> +  @ivar user: Username
> +  @ivar password: Password
> +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> +  @ivar port: Integer port.
> +  @ivar host_port: Returns host:port
> +  """
> +
> +  AMQPS = "amqps"
> +  AMQP = "amqp"
> +
> +  class Port(int):
> +    """An integer port number that can be constructed from a service name
> string"""
> +
> +    def __new__(cls, value):
> +      port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
> +      setattr(port, 'name', str(value))
> +      return port
> +
> +    def __eq__(self, x): return str(self) == x or int(self) == x
> +    def __ne__(self, x): return not self == x
> +    def __str__(self): return str(self.name)
> +
> +    @staticmethod
> +    def port_int(value):
> +      """Convert service, an integer or a service name, into an integer
> port number."""
> +      try:
> +        return int(value)
> +      except ValueError:
> +        try:
> +          return socket.getservbyname(value)
> +        except socket.error:
> +          raise ValueError("Not a valid port number or service name:
> '%s'" % value)
>
> -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> -    @ivar user: Username
> -    @ivar password: Password
> -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> -    @ivar port: Integer port.
> -    @ivar host_port: Returns host:port
> +  def __init__(self, url=None, **kwargs):
> +    """
> +    @param url: URL string to parse.
> +    @param kwargs: scheme, user, password, host, port, path.
> +      If specified, replaces corresponding part in url string.
>      """
> +    if url:
> +      self._url = pn_url_parse(str(url))
> +      if not self._url: raise ValueError("Invalid URL '%s'" % url)
> +    else:
> +      self._url = pn_url()
> +    for k in kwargs:            # Let kwargs override values parsed from
> url
> +      getattr(self, k)          # Check for invalid kwargs
> +      setattr(self, k, kwargs[k])
> +
> +  class PartDescriptor(object):
> +    def __init__(self, part):
> +      self.getter = globals()["pn_url_%s" % part]
> +      self.setter = globals()["pn_url_set_%s" % part]
> +    def __get__(self, obj, type=None): return self.getter(obj._url)
> +    def __set__(self, obj, value): return self.setter(obj._url,
> str(value))
> +
> +  scheme = PartDescriptor('scheme')
> +  username = PartDescriptor('username')
> +  password = PartDescriptor('password')
> +  host = PartDescriptor('host')
> +  path = PartDescriptor('path')
> +
> +  @property
> +  def port(self):
> +    portstr = pn_url_port(self._url)
> +    return portstr and Url.Port(portstr)
> +
> +  @port.setter
> +  def port(self, value):
> +    if value is None: pn_url_set_port(self._url, None)
> +    else: pn_url_set_port(self._url, str(Url.Port(value)))
>
> -    AMQPS = "amqps"
> -    AMQP = "amqp"
> +  def __str__(self): return pn_url_str(self._url)
>
> -    class Port(int):
> -      """An integer port number that can also have an associated service
> name string"""
> +  def __repr__(self): return "Url(%r)" % str(self)
>
> -      def __new__(cls, value):
> -        port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
> -        setattr(port, 'name', str(value))
> -        return port
> -
> -      def __eq__(self, x): return str(self) == x or int(self) == x
> -      def __ne__(self, x): return not self == x
> -      def __str__(self): return str(self.name)
> -
> -      @staticmethod
> -      def port_int(value):
> -        """Convert service, an integer or a service name, into an integer
> port number."""
> -        try:
> -          return int(value)
> -        except ValueError:
> -          try:
> -            return socket.getservbyname(value)
> -          except socket.error:
> -            raise ValueError("Not a valid port number or service name:
> '%s'" % value)
> -
> -    def __init__(self, url=None, **kwargs):
> -        """
> -        @param url: String or Url instance to parse or copy.
> -        @param kwargs: URL fields: scheme, user, password, host, port,
> path.
> -            If specified, replaces corresponding component in url.
> -        """
> -
> -        fields = ['scheme', 'user', 'password', 'host', 'port', 'path']
> -
> -        for f in fields: setattr(self, f, None)
> -        for k in kwargs: getattr(self, k) # Check for invalid kwargs
> -
> -        if isinstance(url, Url): # Copy from another Url instance.
> -            self.__dict__.update(url.__dict__)
> -        elif url is not None:   # Parse from url
> -            parts = pni_parse_url(str(url))
> -            if not filter(None, parts): raise ValueError("Invalid AMQP
> URL: '%s'" % url)
> -            self.scheme, self.user, self.password, self.host, port,
> self.path = parts
> -            if not self.host: self.host = None
> -            self.port = port and self.Port(port)
> -
> -        # Let kwargs override values previously set from url
> -        for field in fields:
> -            setattr(self, field, kwargs.get(field, getattr(self, field)))
> -
> -    def __repr__(self):
> -        return "Url(%r)" % str(self)
> -
> -    def __str__(self):
> -        s = ""
> -        if self.scheme:
> -            s += "%s://" % self.scheme
> -        if self.user:
> -            s += self.user
> -        if self.password:
> -            s += ":%s" % self.password
> -        if self.user or self.password:
> -            s += '@'
> -        if self.host and ':' in self.host:
> -            s += "[%s]" % self.host
> -        elif self.host:
> -            s += self.host
> -        if self.port:
> -            s += ":%s" % self.port
> -        if self.path:
> -            s += "/%s" % self.path
> -        return s
> -
> -    def __eq__(self, url):
> -        return \
> -            self.scheme == url.scheme and \
> -            self.user == url.user and self.password == url.password and \
> -            self.host == url.host and self.port == url.port and \
> -            self.path == url.path
> -
> -    def __ne__(self, url):
> -        return not self.__eq__(url)
> -
> -    def defaults(self):
> -        """
> -        Fill in missing values with defaults
> -        @return: self
> -        """
> -        self.scheme = self.scheme or self.AMQP
> -        self.host = self.host or '0.0.0.0'
> -        self.port = self.port or self.Port(self.scheme)
> -        return self
> +  def defaults(self):
> +    """
> +    Fill in missing values (scheme, host or port) with defaults
> +    @return: self
> +    """
> +    self.scheme = self.scheme or self.AMQP
> +    self.host = self.host or '0.0.0.0'
> +    self.port = self.port or self.Port(self.scheme)
> +    return self
>
> Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19 21:00:50
> 2014
> @@ -26,8 +26,8 @@
>  #include <proton/messenger.h>
>  #include <proton/ssl.h>
>  #include <proton/driver_extras.h>
> -
>  #include <proton/types.h>
> +#include <proton/url.h>
>
>  #include <uuid/uuid.h>
>  %}
>
> Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/include/proton/cproton.i (original)
> +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri Sep 19
> 21:00:50 2014
> @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
>    pn_delivery_t *pn_cast_pn_delivery(void *x) { return (pn_delivery_t *)
> x; }
>    pn_transport_t *pn_cast_pn_transport(void *x) { return (pn_transport_t
> *) x; }
>  %}
> +
> +%include "proton/url.h"
> +
>
> Added: qpid/proton/trunk/proton-c/include/proton/url.h
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19 21:00:50
> 2014
> @@ -0,0 +1,83 @@
> +#ifndef PROTON_URL_H
> +#define PROTON_URL_H
> +/*
> + * 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.
> + */
> +
> +#include <proton/import_export.h>
> +
> +/** @file
> + * URL API for parsing URLs.
> + *
> + * @defgroup url URL
> + * @{
> + */
> +
> +/** A parsed URL */
> +typedef struct pn_url_t pn_url_t;
> +
> +/** Create an empty URL */
> +PN_EXTERN pn_url_t *pn_url(void);
> +
> +/** Parse a string URL as a pn_url_t.
> + *@param[in] url A URL string.
> + *@return The parsed pn_url_t or NULL if url is not a valid URL string.
> + */
> +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> +
> +/** Free a URL */
> +PN_EXTERN void pn_url_free(pn_url_t *url);
> +
> +/** Clear the contents of the URL. */
> +PN_EXTERN void pn_url_clear(pn_url_t *url);
> +
> +/** Return the string form of a URL. Owned by the pn_url_t.*/
> +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> +
> +/**
> + *@name Getters for parts of the URL.
> + *
> + *Values belong to the URL. May return NULL if the value is not set.
> + *
> + *@{
> + */
> +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> +///@}
> +
> +/**
> + *@name Setters for parts of the URL.
> + *
> + *Values are copied. Value can be NULL to indicate the part is not set.
> + *
> + *@{
> + */
> +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme);
> +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char *username);
> +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char *password);
> +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host);
> +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port);
> +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path);
> +///@}
> +
> +///@}
> +#endif
>
> Added: qpid/proton/trunk/proton-c/src/url.c
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/src/url.c (added)
> +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50 2014
> @@ -0,0 +1,127 @@
> +/*
> + *
> + * 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.
> + *
> + */
> +
> +#include <proton/url.h>
> +#include <proton/util.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <stdio.h>
> +
> +static char* copy(const char* str) {
> +    if (str ==  NULL) return NULL;
> +    char *str2 = (char*)malloc(strlen(str));
> +    if (str2) strcpy(str2, str);
> +    return str2;
> +}
> +
> +struct pn_url_t {
> +    char *scheme;
> +    char *username;
> +    char *password;
> +    char *host;
> +    char *port;
> +    char *path;
> +    char *str;
> +};
> +
> +PN_EXTERN pn_url_t *pn_url() {
> +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> +    memset(url, 0, sizeof(*url));
> +    return url;
> +}
> +
> +/** Parse a string URL as a pn_url_t.
> + *@param[in] url A URL string.
> + *@return The parsed pn_url_t or NULL if url is not a valid URL string.
> + */
> +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> +    if (!str || !*str)          /* Empty string or NULL is illegal. */
> +        return NULL;
> +
> +    pn_url_t *url = pn_url();
> +    char *str2 = copy(str);         /* FIXME aconway 2014-09-19: clean up
> */
> +    pni_parse_url(str2, &url->scheme, &url->username, &url->password,
> &url->host, &url->port, &url->path);
> +    url->scheme = copy(url->scheme);
> +    url->username = copy(url->username);
> +    url->password = copy(url->password);
> +    url->host = (url->host && !*url->host) ? NULL : copy(url->host);
> +    url->port = copy(url->port);
> +    url->path = copy(url->path);
> +    return url;
> +}
> +
> +/** Free a URL */
> +PN_EXTERN void pn_url_free(pn_url_t *url) {
> +    pn_url_clear(url);
> +    free(url);
> +}
> +
> +/** Clear the contents of the URL. */
> +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> +    pn_url_set_username(url, NULL);
> +    pn_url_set_password(url, NULL);
> +    pn_url_set_host(url, NULL);
> +    pn_url_set_port(url, NULL);
> +    pn_url_set_path(url, NULL);
> +    free(url->str); url->str = NULL;
> +}
> +
> +static inline int len(const char *str) { return str ? strlen(str) : 0; }
> +
> +/** Return the string form of a URL. */
> +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> +    int size = len(url->scheme) + len(url->username) + len(url->password)
> +        + len(url->host) + len(url->port) + len(url->path)
> +        + len("s://u:p@[h]:p/p");
> +    free(url->str);
> +    url->str = (char*)malloc(size);
> +    if (!url->str) return NULL;
> +
> +    int i = 0;
> +    if (url->scheme) i += snprintf(url->str+i, size-i, "%s://",
> url->scheme);
> +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> url->username);
> +    if (url->password) i += snprintf(url->str+i, size-i, ":%s",
> url->password);
> +    if (url->username || url->password) i += snprintf(url->str+i, size-i,
> "@");
> +    if (url->host) {
> +        if (strchr(url->host, ':')) i += snprintf(url->str+i, size-i,
> "[%s]", url->host);
> +        else i += snprintf(url->str+i, size-i, "%s", url->host);
> +    }
> +    if (url->port) i += snprintf(url->str+i, size-i, ":%s", url->port);
> +    if (url->path) i += snprintf(url->str+i, size-i, "/%s", url->path);
> +    return url->str;
> +}
> +
> +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return url->scheme; }
> +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> url->username; }
> +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> url->password; }
> +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return url->host; }
> +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return url->port; }
> +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return url->path; }
> +
> +#define SET(part) free(url->part); url->part = copy(part)
> +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme) {
> SET(scheme); }
> +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char *username) {
> SET(username); }
> +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char *password) {
> SET(password); }
> +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host) {
> SET(host); }
> +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port) {
> SET(port); }
> +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path) {
> SET(path); }
> +
> +
>
> Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
>
> ==============================================================================
> --- qpid/proton/trunk/tests/python/proton_tests/url.py (original)
> +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep 19 21:00:50
> 2014
> @@ -28,9 +28,9 @@ class UrlTest(common.Test):
>      def assertNotEqual(self, a, b):
>          assert a != b, "%s == %s" % (a, b)
>
> -    def assertUrl(self, u, scheme, user, password, host, port, path):
> -        self.assertEqual((u.scheme, u.user, u.password, u.host, u.port,
> u.path),
> -                         (scheme, user, password, host, port, path))
> +    def assertUrl(self, u, scheme, username, password, host, port, path):
> +        self.assertEqual((u.scheme, u.username, u.password, u.host,
> u.port, u.path),
> +                         (scheme, username, password, host, port, path))
>
>      def testUrl(self):
>          url = Url('amqp://me:secret@myhost:1234/foobar')
> @@ -40,7 +40,7 @@ class UrlTest(common.Test):
>
>      def testDefaults(self):
>          # Check that we allow None for scheme, port
> -        url = Url(user='me', password='secret', host='myhost',
> path='foobar')
> +        url = Url(username='me', password='secret', host='myhost',
> path='foobar')
>          self.assertEqual(str(url), "me:secret@myhost/foobar")
>          self.assertUrl(url, None, 'me', 'secret', 'myhost', None,
> 'foobar')
>
> @@ -97,21 +97,19 @@ class UrlTest(common.Test):
>      def testMissing(self):
>          self.assertUrl(Url(), None, None, None, None, None, None)
>          self.assertUrl(Url('amqp://'), 'amqp', None, None, None, None,
> None)
> -        self.assertUrl(Url('user@'), None, 'user', None, None, None,
> None)
> +        self.assertUrl(Url('username@'), None, 'username', None, None,
> None, None)
>          self.assertUrl(Url(':pass@'), None, '', 'pass', None, None, None)
>          self.assertUrl(Url('host'), None, None, None, 'host', None, None)
>          self.assertUrl(Url(':1234'), None, None, None, None, 1234, None)
>          self.assertUrl(Url('/path'), None, None, None, None, None, 'path')
>
> -        for s in ['amqp://', 'user@', ':pass@', ':1234', '/path']:
> +        for s in ['amqp://', 'username@', ':pass@', ':1234', '/path']:
>              self.assertEqual(s, str(Url(s)))
>
>          for s, full in [
>                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> +                ('username@', 'amqp://username@0.0.0.0:amqp'),
>                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
>                  (':1234', 'amqp://0.0.0.0:1234'),
>                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
>              self.assertEqual(str(Url(s).defaults()), full)
> -
> -        self.assertRaises(ValueError, Url, '')
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> For additional commands, e-mail: commits-help@qpid.apache.org
>
>

Re: svn commit: r1626329 - in /qpid/proton/trunk: proton-c/ proton-c/bindings/perl/ proton-c/bindings/php/ proton-c/bindings/python/ proton-c/bindings/ruby/ proton-c/include/proton/ proton-c/src/ tests/python/proton_tests/

Posted by Robbie Gemmell <ro...@gmail.com>.
This seems to have broken the Java test runs:

https://builds.apache.org/view/M-R/view/Qpid/job/Qpid-proton-j/664/



On 19 September 2014 22:00, <ac...@apache.org> wrote:

> Author: aconway
> Date: Fri Sep 19 21:00:50 2014
> New Revision: 1626329
>
> URL: http://svn.apache.org/r1626329
> Log:
> PROTON-693: Python Url class to wrap C function pni_parse_url
>
> It was pointed out that pni_parse_url is an internal function and the
> interface
> is not suitable for public API.
>
> Rewrote the URL parser as a proper swigable C API pn_url_*. This gets rid
> of the
> need for previous swig insanity and is cleaner all round.
>
> Internally still uses the pni_parse_url parser, we can clean that up later.
>
> Added:
>     qpid/proton/trunk/proton-c/include/proton/url.h
>     qpid/proton/trunk/proton-c/src/url.c
> Modified:
>     qpid/proton/trunk/proton-c/CMakeLists.txt
>     qpid/proton/trunk/proton-c/bindings/perl/perl.i
>     qpid/proton/trunk/proton-c/bindings/php/php.i
>     qpid/proton/trunk/proton-c/bindings/python/cproton.i
>     qpid/proton/trunk/proton-c/bindings/python/proton.py
>     qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
>     qpid/proton/trunk/proton-c/include/proton/cproton.i
>     qpid/proton/trunk/tests/python/proton_tests/url.py
>
> Modified: qpid/proton/trunk/proton-c/CMakeLists.txt
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/CMakeLists.txt?rev=1626329&r1=1626328&r2=1626329&view=diff
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/CMakeLists.txt (original)
> +++ qpid/proton/trunk/proton-c/CMakeLists.txt Fri Sep 19 21:00:50 2014
> @@ -270,6 +270,7 @@ set (qpid-proton-core
>    src/object/iterator.c
>
>    src/util.c
> +  src/url.c
>    src/error.c
>    src/buffer.c
>    src/parser.c
>
> Modified: qpid/proton/trunk/proton-c/bindings/perl/perl.i
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/perl/perl.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/bindings/perl/perl.i (original)
> +++ qpid/proton/trunk/proton-c/bindings/perl/perl.i Fri Sep 19 21:00:50
> 2014
> @@ -8,6 +8,7 @@
>  #include <proton/messenger.h>
>  #include <proton/ssl.h>
>  #include <proton/driver_extras.h>
> +#include <proton/url.h>
>  %}
>
>  %include <cstring.i>
>
> Modified: qpid/proton/trunk/proton-c/bindings/php/php.i
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/php/php.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/bindings/php/php.i (original)
> +++ qpid/proton/trunk/proton-c/bindings/php/php.i Fri Sep 19 21:00:50 2014
> @@ -29,6 +29,7 @@
>  %header %{
>  /* Include the headers needed by the code in this wrapper file */
>  #include <proton/types.h>
> +#include <proton/url.h>
>  #include <proton/message.h>
>  #include <proton/driver.h>
>  #include <proton/driver_extras.h>
>
> Modified: qpid/proton/trunk/proton-c/bindings/python/cproton.i
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/bindings/python/cproton.i (original)
> +++ qpid/proton/trunk/proton-c/bindings/python/cproton.i Fri Sep 19
> 21:00:50 2014
> @@ -23,6 +23,7 @@
>  #include <winsock2.h>
>  #endif
>  #include <proton/engine.h>
> +#include <proton/url.h>
>  #include <proton/message.h>
>  #include <proton/sasl.h>
>  #include <proton/driver.h>
> @@ -280,41 +281,4 @@ int pn_ssl_get_peer_hostname(pn_ssl_t *s
>    }
>  %}
>
> -
> -/**
> -   pni_parse_url(char* url, char **scheme, char **user, char **pass, char
> **host, char **port, char **path)
> -   The following type maps convert this into a python function that taks
> a URL string argument
> -   and returns a list of strings [scheme, user, pass, host, port, path]
> -   This probably could be done more neatly.
> -*/
> -
> -// Typemap to copy the url string as it will be modified by parse_url
> -%typemap(in,noblock=1,fragment="SWIG_AsCharPtrAndSize") char *url (int
> res, char *t = 0, size_t n = 0, int alloc = 0) {
> -  res = SWIG_AsCharPtrAndSize($input, &t, &n, &alloc);
> -  if (!SWIG_IsOK(res)) {
> -    %argument_fail(res, "char *url", $symname, $argnum);
> -  }
> -  $1 = %new_array(n, $*1_ltype);
> -  memcpy($1,t,sizeof(char)*n);
> -  if (alloc == SWIG_NEWOBJ) %delete_array(t);
> -  $1[n-1] = 0;
> -}
> -%typemap(freearg,match="in") char *url "free($1);";
> -%typemap(argout) char *url "";
> -
> -// Typemap for char** return strings. Don't free them.
> -%typemap(in,numinputs=0) char **OUTSTR($*1_ltype temp = 0) "$1 = &temp;";
> -%typemap(freearg,match="in") char **OUTSTR "";
> -%typemap(argout,noblock=1,fragment="SWIG_FromCharPtr") char **OUTSTR {
> -    %append_output(SWIG_FromCharPtr(*$1));
> -}
> -
> -// Typemap to initialize result as empty list
> -%typemap(out) void "$result = PyList_New(0);";
> -
> -
> -%apply char** OUTSTR {char **scheme, char **user, char **pass, char
> **host, char **port, char **path};
> -void pni_parse_url(char* url, char **scheme, char **user, char **pass,
> char **host, char **port, char **path);
> -%ignore pni_parse_url;
> -
>  %include "proton/cproton.i"
>
> Modified: qpid/proton/trunk/proton-c/bindings/python/proton.py
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/python/proton.py?rev=1626329&r1=1626328&r2=1626329&view=diff
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/bindings/python/proton.py (original)
> +++ qpid/proton/trunk/proton-c/bindings/python/proton.py Fri Sep 19
> 21:00:50 2014
> @@ -3657,114 +3657,98 @@ __all__ = [
>
>
>  class Url(object):
> -    """
> -    Simple URL parser/constructor, handles URLs of the form:
> +  """
> +  Simple URL parser/constructor, handles URLs of the form:
>
> -      <scheme>://<user>:<password>@<host>:<port>/<path>
> +    <scheme>://<user>:<password>@<host>:<port>/<path>
>
> -    All components can be None if not specifeid in the URL string.
> +  All components can be None if not specifeid in the URL string.
>
> -    The port can be specified as a service name, e.g. 'amqp' in the
> -    URL string but Url.port always gives the integer value.
> +  The port can be specified as a service name, e.g. 'amqp' in the
> +  URL string but Url.port always gives the integer value.
> +
> +  @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> +  @ivar user: Username
> +  @ivar password: Password
> +  @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> +  @ivar port: Integer port.
> +  @ivar host_port: Returns host:port
> +  """
> +
> +  AMQPS = "amqps"
> +  AMQP = "amqp"
> +
> +  class Port(int):
> +    """An integer port number that can be constructed from a service name
> string"""
> +
> +    def __new__(cls, value):
> +      port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
> +      setattr(port, 'name', str(value))
> +      return port
> +
> +    def __eq__(self, x): return str(self) == x or int(self) == x
> +    def __ne__(self, x): return not self == x
> +    def __str__(self): return str(self.name)
> +
> +    @staticmethod
> +    def port_int(value):
> +      """Convert service, an integer or a service name, into an integer
> port number."""
> +      try:
> +        return int(value)
> +      except ValueError:
> +        try:
> +          return socket.getservbyname(value)
> +        except socket.error:
> +          raise ValueError("Not a valid port number or service name:
> '%s'" % value)
>
> -    @ivar scheme: Url scheme e.g. 'amqp' or 'amqps'
> -    @ivar user: Username
> -    @ivar password: Password
> -    @ivar host: Host name, ipv6 literal or ipv4 dotted quad.
> -    @ivar port: Integer port.
> -    @ivar host_port: Returns host:port
> +  def __init__(self, url=None, **kwargs):
> +    """
> +    @param url: URL string to parse.
> +    @param kwargs: scheme, user, password, host, port, path.
> +      If specified, replaces corresponding part in url string.
>      """
> +    if url:
> +      self._url = pn_url_parse(str(url))
> +      if not self._url: raise ValueError("Invalid URL '%s'" % url)
> +    else:
> +      self._url = pn_url()
> +    for k in kwargs:            # Let kwargs override values parsed from
> url
> +      getattr(self, k)          # Check for invalid kwargs
> +      setattr(self, k, kwargs[k])
> +
> +  class PartDescriptor(object):
> +    def __init__(self, part):
> +      self.getter = globals()["pn_url_%s" % part]
> +      self.setter = globals()["pn_url_set_%s" % part]
> +    def __get__(self, obj, type=None): return self.getter(obj._url)
> +    def __set__(self, obj, value): return self.setter(obj._url,
> str(value))
> +
> +  scheme = PartDescriptor('scheme')
> +  username = PartDescriptor('username')
> +  password = PartDescriptor('password')
> +  host = PartDescriptor('host')
> +  path = PartDescriptor('path')
> +
> +  @property
> +  def port(self):
> +    portstr = pn_url_port(self._url)
> +    return portstr and Url.Port(portstr)
> +
> +  @port.setter
> +  def port(self, value):
> +    if value is None: pn_url_set_port(self._url, None)
> +    else: pn_url_set_port(self._url, str(Url.Port(value)))
>
> -    AMQPS = "amqps"
> -    AMQP = "amqp"
> +  def __str__(self): return pn_url_str(self._url)
>
> -    class Port(int):
> -      """An integer port number that can also have an associated service
> name string"""
> +  def __repr__(self): return "Url(%r)" % str(self)
>
> -      def __new__(cls, value):
> -        port = super(Url.Port, cls).__new__(cls, cls.port_int(value))
> -        setattr(port, 'name', str(value))
> -        return port
> -
> -      def __eq__(self, x): return str(self) == x or int(self) == x
> -      def __ne__(self, x): return not self == x
> -      def __str__(self): return str(self.name)
> -
> -      @staticmethod
> -      def port_int(value):
> -        """Convert service, an integer or a service name, into an integer
> port number."""
> -        try:
> -          return int(value)
> -        except ValueError:
> -          try:
> -            return socket.getservbyname(value)
> -          except socket.error:
> -            raise ValueError("Not a valid port number or service name:
> '%s'" % value)
> -
> -    def __init__(self, url=None, **kwargs):
> -        """
> -        @param url: String or Url instance to parse or copy.
> -        @param kwargs: URL fields: scheme, user, password, host, port,
> path.
> -            If specified, replaces corresponding component in url.
> -        """
> -
> -        fields = ['scheme', 'user', 'password', 'host', 'port', 'path']
> -
> -        for f in fields: setattr(self, f, None)
> -        for k in kwargs: getattr(self, k) # Check for invalid kwargs
> -
> -        if isinstance(url, Url): # Copy from another Url instance.
> -            self.__dict__.update(url.__dict__)
> -        elif url is not None:   # Parse from url
> -            parts = pni_parse_url(str(url))
> -            if not filter(None, parts): raise ValueError("Invalid AMQP
> URL: '%s'" % url)
> -            self.scheme, self.user, self.password, self.host, port,
> self.path = parts
> -            if not self.host: self.host = None
> -            self.port = port and self.Port(port)
> -
> -        # Let kwargs override values previously set from url
> -        for field in fields:
> -            setattr(self, field, kwargs.get(field, getattr(self, field)))
> -
> -    def __repr__(self):
> -        return "Url(%r)" % str(self)
> -
> -    def __str__(self):
> -        s = ""
> -        if self.scheme:
> -            s += "%s://" % self.scheme
> -        if self.user:
> -            s += self.user
> -        if self.password:
> -            s += ":%s" % self.password
> -        if self.user or self.password:
> -            s += '@'
> -        if self.host and ':' in self.host:
> -            s += "[%s]" % self.host
> -        elif self.host:
> -            s += self.host
> -        if self.port:
> -            s += ":%s" % self.port
> -        if self.path:
> -            s += "/%s" % self.path
> -        return s
> -
> -    def __eq__(self, url):
> -        return \
> -            self.scheme == url.scheme and \
> -            self.user == url.user and self.password == url.password and \
> -            self.host == url.host and self.port == url.port and \
> -            self.path == url.path
> -
> -    def __ne__(self, url):
> -        return not self.__eq__(url)
> -
> -    def defaults(self):
> -        """
> -        Fill in missing values with defaults
> -        @return: self
> -        """
> -        self.scheme = self.scheme or self.AMQP
> -        self.host = self.host or '0.0.0.0'
> -        self.port = self.port or self.Port(self.scheme)
> -        return self
> +  def defaults(self):
> +    """
> +    Fill in missing values (scheme, host or port) with defaults
> +    @return: self
> +    """
> +    self.scheme = self.scheme or self.AMQP
> +    self.host = self.host or '0.0.0.0'
> +    self.port = self.port or self.Port(self.scheme)
> +    return self
>
> Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
> +++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Fri Sep 19 21:00:50
> 2014
> @@ -26,8 +26,8 @@
>  #include <proton/messenger.h>
>  #include <proton/ssl.h>
>  #include <proton/driver_extras.h>
> -
>  #include <proton/types.h>
> +#include <proton/url.h>
>
>  #include <uuid/uuid.h>
>  %}
>
> Modified: qpid/proton/trunk/proton-c/include/proton/cproton.i
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/cproton.i?rev=1626329&r1=1626328&r2=1626329&view=diff
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/include/proton/cproton.i (original)
> +++ qpid/proton/trunk/proton-c/include/proton/cproton.i Fri Sep 19
> 21:00:50 2014
> @@ -1394,3 +1394,6 @@ typedef unsigned long int uintptr_t;
>    pn_delivery_t *pn_cast_pn_delivery(void *x) { return (pn_delivery_t *)
> x; }
>    pn_transport_t *pn_cast_pn_transport(void *x) { return (pn_transport_t
> *) x; }
>  %}
> +
> +%include "proton/url.h"
> +
>
> Added: qpid/proton/trunk/proton-c/include/proton/url.h
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/include/proton/url.h?rev=1626329&view=auto
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/include/proton/url.h (added)
> +++ qpid/proton/trunk/proton-c/include/proton/url.h Fri Sep 19 21:00:50
> 2014
> @@ -0,0 +1,83 @@
> +#ifndef PROTON_URL_H
> +#define PROTON_URL_H
> +/*
> + * 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.
> + */
> +
> +#include <proton/import_export.h>
> +
> +/** @file
> + * URL API for parsing URLs.
> + *
> + * @defgroup url URL
> + * @{
> + */
> +
> +/** A parsed URL */
> +typedef struct pn_url_t pn_url_t;
> +
> +/** Create an empty URL */
> +PN_EXTERN pn_url_t *pn_url(void);
> +
> +/** Parse a string URL as a pn_url_t.
> + *@param[in] url A URL string.
> + *@return The parsed pn_url_t or NULL if url is not a valid URL string.
> + */
> +PN_EXTERN pn_url_t *pn_url_parse(const char *url);
> +
> +/** Free a URL */
> +PN_EXTERN void pn_url_free(pn_url_t *url);
> +
> +/** Clear the contents of the URL. */
> +PN_EXTERN void pn_url_clear(pn_url_t *url);
> +
> +/** Return the string form of a URL. Owned by the pn_url_t.*/
> +PN_EXTERN const char *pn_url_str(pn_url_t *url);
> +
> +/**
> + *@name Getters for parts of the URL.
> + *
> + *Values belong to the URL. May return NULL if the value is not set.
> + *
> + *@{
> + */
> +PN_EXTERN const char *pn_url_scheme(pn_url_t *url);
> +PN_EXTERN const char *pn_url_username(pn_url_t *url);
> +PN_EXTERN const char *pn_url_password(pn_url_t *url);
> +PN_EXTERN const char *pn_url_host(pn_url_t *url);
> +PN_EXTERN const char *pn_url_port(pn_url_t *url);
> +PN_EXTERN const char *pn_url_path(pn_url_t *url);
> +///@}
> +
> +/**
> + *@name Setters for parts of the URL.
> + *
> + *Values are copied. Value can be NULL to indicate the part is not set.
> + *
> + *@{
> + */
> +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme);
> +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char *username);
> +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char *password);
> +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host);
> +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port);
> +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path);
> +///@}
> +
> +///@}
> +#endif
>
> Added: qpid/proton/trunk/proton-c/src/url.c
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/src/url.c?rev=1626329&view=auto
>
> ==============================================================================
> --- qpid/proton/trunk/proton-c/src/url.c (added)
> +++ qpid/proton/trunk/proton-c/src/url.c Fri Sep 19 21:00:50 2014
> @@ -0,0 +1,127 @@
> +/*
> + *
> + * 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.
> + *
> + */
> +
> +#include <proton/url.h>
> +#include <proton/util.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <stdio.h>
> +
> +static char* copy(const char* str) {
> +    if (str ==  NULL) return NULL;
> +    char *str2 = (char*)malloc(strlen(str));
> +    if (str2) strcpy(str2, str);
> +    return str2;
> +}
> +
> +struct pn_url_t {
> +    char *scheme;
> +    char *username;
> +    char *password;
> +    char *host;
> +    char *port;
> +    char *path;
> +    char *str;
> +};
> +
> +PN_EXTERN pn_url_t *pn_url() {
> +    pn_url_t *url = (pn_url_t*)malloc(sizeof(pn_url_t));
> +    memset(url, 0, sizeof(*url));
> +    return url;
> +}
> +
> +/** Parse a string URL as a pn_url_t.
> + *@param[in] url A URL string.
> + *@return The parsed pn_url_t or NULL if url is not a valid URL string.
> + */
> +PN_EXTERN pn_url_t *pn_url_parse(const char *str) {
> +    if (!str || !*str)          /* Empty string or NULL is illegal. */
> +        return NULL;
> +
> +    pn_url_t *url = pn_url();
> +    char *str2 = copy(str);         /* FIXME aconway 2014-09-19: clean up
> */
> +    pni_parse_url(str2, &url->scheme, &url->username, &url->password,
> &url->host, &url->port, &url->path);
> +    url->scheme = copy(url->scheme);
> +    url->username = copy(url->username);
> +    url->password = copy(url->password);
> +    url->host = (url->host && !*url->host) ? NULL : copy(url->host);
> +    url->port = copy(url->port);
> +    url->path = copy(url->path);
> +    return url;
> +}
> +
> +/** Free a URL */
> +PN_EXTERN void pn_url_free(pn_url_t *url) {
> +    pn_url_clear(url);
> +    free(url);
> +}
> +
> +/** Clear the contents of the URL. */
> +PN_EXTERN void pn_url_clear(pn_url_t *url) {
> +    pn_url_set_username(url, NULL);
> +    pn_url_set_password(url, NULL);
> +    pn_url_set_host(url, NULL);
> +    pn_url_set_port(url, NULL);
> +    pn_url_set_path(url, NULL);
> +    free(url->str); url->str = NULL;
> +}
> +
> +static inline int len(const char *str) { return str ? strlen(str) : 0; }
> +
> +/** Return the string form of a URL. */
> +PN_EXTERN const char *pn_url_str(pn_url_t *url) {
> +    int size = len(url->scheme) + len(url->username) + len(url->password)
> +        + len(url->host) + len(url->port) + len(url->path)
> +        + len("s://u:p@[h]:p/p");
> +    free(url->str);
> +    url->str = (char*)malloc(size);
> +    if (!url->str) return NULL;
> +
> +    int i = 0;
> +    if (url->scheme) i += snprintf(url->str+i, size-i, "%s://",
> url->scheme);
> +    if (url->username) i += snprintf(url->str+i, size-i, "%s",
> url->username);
> +    if (url->password) i += snprintf(url->str+i, size-i, ":%s",
> url->password);
> +    if (url->username || url->password) i += snprintf(url->str+i, size-i,
> "@");
> +    if (url->host) {
> +        if (strchr(url->host, ':')) i += snprintf(url->str+i, size-i,
> "[%s]", url->host);
> +        else i += snprintf(url->str+i, size-i, "%s", url->host);
> +    }
> +    if (url->port) i += snprintf(url->str+i, size-i, ":%s", url->port);
> +    if (url->path) i += snprintf(url->str+i, size-i, "/%s", url->path);
> +    return url->str;
> +}
> +
> +PN_EXTERN const char *pn_url_scheme(pn_url_t *url) { return url->scheme; }
> +PN_EXTERN const char *pn_url_username(pn_url_t *url) { return
> url->username; }
> +PN_EXTERN const char *pn_url_password(pn_url_t *url) { return
> url->password; }
> +PN_EXTERN const char *pn_url_host(pn_url_t *url) { return url->host; }
> +PN_EXTERN const char *pn_url_port(pn_url_t *url) { return url->port; }
> +PN_EXTERN const char *pn_url_path(pn_url_t *url) { return url->path; }
> +
> +#define SET(part) free(url->part); url->part = copy(part)
> +PN_EXTERN void pn_url_set_scheme(pn_url_t *url, const char *scheme) {
> SET(scheme); }
> +PN_EXTERN void pn_url_set_username(pn_url_t *url, const char *username) {
> SET(username); }
> +PN_EXTERN void pn_url_set_password(pn_url_t *url, const char *password) {
> SET(password); }
> +PN_EXTERN void pn_url_set_host(pn_url_t *url, const char *host) {
> SET(host); }
> +PN_EXTERN void pn_url_set_port(pn_url_t *url, const char *port) {
> SET(port); }
> +PN_EXTERN void pn_url_set_path(pn_url_t *url, const char *path) {
> SET(path); }
> +
> +
>
> Modified: qpid/proton/trunk/tests/python/proton_tests/url.py
> URL:
> http://svn.apache.org/viewvc/qpid/proton/trunk/tests/python/proton_tests/url.py?rev=1626329&r1=1626328&r2=1626329&view=diff
>
> ==============================================================================
> --- qpid/proton/trunk/tests/python/proton_tests/url.py (original)
> +++ qpid/proton/trunk/tests/python/proton_tests/url.py Fri Sep 19 21:00:50
> 2014
> @@ -28,9 +28,9 @@ class UrlTest(common.Test):
>      def assertNotEqual(self, a, b):
>          assert a != b, "%s == %s" % (a, b)
>
> -    def assertUrl(self, u, scheme, user, password, host, port, path):
> -        self.assertEqual((u.scheme, u.user, u.password, u.host, u.port,
> u.path),
> -                         (scheme, user, password, host, port, path))
> +    def assertUrl(self, u, scheme, username, password, host, port, path):
> +        self.assertEqual((u.scheme, u.username, u.password, u.host,
> u.port, u.path),
> +                         (scheme, username, password, host, port, path))
>
>      def testUrl(self):
>          url = Url('amqp://me:secret@myhost:1234/foobar')
> @@ -40,7 +40,7 @@ class UrlTest(common.Test):
>
>      def testDefaults(self):
>          # Check that we allow None for scheme, port
> -        url = Url(user='me', password='secret', host='myhost',
> path='foobar')
> +        url = Url(username='me', password='secret', host='myhost',
> path='foobar')
>          self.assertEqual(str(url), "me:secret@myhost/foobar")
>          self.assertUrl(url, None, 'me', 'secret', 'myhost', None,
> 'foobar')
>
> @@ -97,21 +97,19 @@ class UrlTest(common.Test):
>      def testMissing(self):
>          self.assertUrl(Url(), None, None, None, None, None, None)
>          self.assertUrl(Url('amqp://'), 'amqp', None, None, None, None,
> None)
> -        self.assertUrl(Url('user@'), None, 'user', None, None, None,
> None)
> +        self.assertUrl(Url('username@'), None, 'username', None, None,
> None, None)
>          self.assertUrl(Url(':pass@'), None, '', 'pass', None, None, None)
>          self.assertUrl(Url('host'), None, None, None, 'host', None, None)
>          self.assertUrl(Url(':1234'), None, None, None, None, 1234, None)
>          self.assertUrl(Url('/path'), None, None, None, None, None, 'path')
>
> -        for s in ['amqp://', 'user@', ':pass@', ':1234', '/path']:
> +        for s in ['amqp://', 'username@', ':pass@', ':1234', '/path']:
>              self.assertEqual(s, str(Url(s)))
>
>          for s, full in [
>                  ('amqp://', 'amqp://0.0.0.0:amqp'),
> -                ('user@', 'amqp://user@0.0.0.0:amqp'),
> +                ('username@', 'amqp://username@0.0.0.0:amqp'),
>                  (':pass@', 'amqp://:pass@0.0.0.0:amqp'),
>                  (':1234', 'amqp://0.0.0.0:1234'),
>                  ('/path', 'amqp://0.0.0.0:amqp/path')]:
>              self.assertEqual(str(Url(s).defaults()), full)
> -
> -        self.assertRaises(ValueError, Url, '')
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
> For additional commands, e-mail: commits-help@qpid.apache.org
>
>