| # |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you under the Apache License, Version 2.0 (the |
| # "License"); you may not use this file except in compliance |
| # with the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, |
| # software distributed under the License is distributed on an |
| # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| # KIND, either express or implied. See the License for the |
| # specific language governing permissions and limitations |
| # under the License. |
| # |
| |
| import os, socket, time, textwrap, re, sys |
| |
| try: |
| from ssl import wrap_socket as ssl |
| except ImportError: |
| from socket import ssl as wrap_socket |
| class ssl: |
| def __init__(self, sock, keyfile=None, certfile=None, trustfile=None): |
| # Bug (QPID-4337): this is the "old" version of python SSL. |
| # The private key is required. If a certificate is given, but no |
| # keyfile, assume the key is contained in the certificate |
| if certfile and not keyfile: |
| keyfile = certfile |
| self.sock = sock |
| self.ssl = wrap_socket(sock, keyfile=keyfile, certfile=certfile) |
| |
| def recv(self, n): |
| return self.ssl.read(n) |
| |
| def send(self, s): |
| return self.ssl.write(s) |
| |
| def close(self): |
| self.sock.close() |
| |
| def get_client_properties_with_defaults(provided_client_properties={}, version_property_key="qpid.client_version"): |
| ppid = 0 |
| version = "unidentified" |
| try: |
| ppid = os.getppid() |
| except: |
| pass |
| |
| try: |
| import pkg_resources |
| pkg = pkg_resources.require("qpid-python") |
| if pkg and pkg[0] and pkg[0].version: |
| version = pkg[0].version |
| except: |
| pass |
| |
| client_properties = {"product": "qpid python client", |
| version_property_key : version, |
| "platform": os.name, |
| "qpid.client_process": os.path.basename(sys.argv and sys.argv[0] or ''), |
| "qpid.client_pid": os.getpid(), |
| "qpid.client_ppid": ppid} |
| |
| if provided_client_properties: |
| client_properties.update(provided_client_properties) |
| return client_properties |
| |
| def connect(host, port): |
| for res in socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM): |
| af, socktype, proto, canonname, sa = res |
| sock = socket.socket(af, socktype, proto) |
| try: |
| sock.connect(sa) |
| break |
| except socket.error, msg: |
| sock.close() |
| else: |
| # If we got here then we couldn't connect (yet) |
| raise |
| return sock |
| |
| def listen(host, port, predicate = lambda: True, bound = lambda: None): |
| sock = socket.socket() |
| sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
| sock.bind((host, port)) |
| sock.listen(5) |
| bound() |
| while predicate(): |
| s, a = sock.accept() |
| yield s |
| |
| def mtime(filename): |
| return os.stat(filename).st_mtime |
| |
| def wait(condition, predicate, timeout=None): |
| condition.acquire() |
| try: |
| passed = 0 |
| start = time.time() |
| while not predicate(): |
| if timeout is None: |
| # using the timed wait prevents keyboard interrupts from being |
| # blocked while waiting |
| condition.wait(3) |
| elif passed < timeout: |
| condition.wait(timeout - passed) |
| else: |
| return False |
| passed = time.time() - start |
| return True |
| finally: |
| condition.release() |
| |
| def notify(condition, action=lambda: None): |
| condition.acquire() |
| try: |
| action() |
| condition.notifyAll() |
| finally: |
| condition.release() |
| |
| def fill(text, indent, heading = None): |
| sub = indent * " " |
| if heading: |
| if not text: |
| return (indent - 2) * " " + heading |
| init = (indent - 2) * " " + heading + " -- " |
| else: |
| init = sub |
| w = textwrap.TextWrapper(initial_indent = init, subsequent_indent = sub) |
| return w.fill(" ".join(text.split())) |
| |
| class URL: |
| |
| RE = re.compile(r""" |
| # [ <scheme>:// ] [ <user> [ / <password> ] @] ( <host4> | \[ <host6> \] ) [ :<port> ] |
| ^ (?: ([^:/@]+)://)? (?: ([^:/@]+) (?: / ([^:/@]+) )? @)? (?: ([^@:/\[]+) | \[ ([a-f0-9:.]+) \] ) (?: :([0-9]+))?$ |
| """, re.X | re.I) |
| |
| AMQPS = "amqps" |
| AMQP = "amqp" |
| |
| def __init__(self, s=None, **kwargs): |
| if s is None: |
| self.scheme = kwargs.get('scheme', None) |
| self.user = kwargs.get('user', None) |
| self.password = kwargs.get('password', None) |
| self.host = kwargs.get('host', None) |
| self.port = kwargs.get('port', None) |
| if self.host is None: |
| raise ValueError('Host required for url') |
| elif isinstance(s, URL): |
| self.scheme = s.scheme |
| self.user = s.user |
| self.password = s.password |
| self.host = s.host |
| self.port = s.port |
| else: |
| match = URL.RE.match(s) |
| if match is None: |
| raise ValueError(s) |
| self.scheme, self.user, self.password, host4, host6, port = match.groups() |
| self.host = host4 or host6 |
| if port is None: |
| self.port = None |
| else: |
| self.port = int(port) |
| |
| 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 |
| s += "@" |
| if ':' not in self.host: |
| s += self.host |
| else: |
| s += "[%s]" % self.host |
| if self.port: |
| s += ":%s" % self.port |
| return s |
| |
| def __eq__(self, url): |
| if isinstance(url, basestring): |
| url = URL(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 |
| |
| def __ne__(self, url): |
| return not self.__eq__(url) |
| |
| def default(value, default): |
| if value is None: |
| return default |
| else: |
| return value |