fix up circular cimports related to the sockaddr type, and touch up endpoint/getaddrinfo a bit
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qmsk/net/socket/_address.pxd Fri Sep 25 21:34:04 2009 +0300
@@ -0,0 +1,42 @@
+"""
+ Internal module to keep the abstract sockaddr types out of the address module, which must contain backreferences to
+ the concrete implementations.
+"""
+
+cimport qmsk.net.socket.platform as platform
+
+cdef class sockaddr :
+ """
+ A network-level socket address
+
+ XXX: not abstract enough. Functions/properties like getnameinfo/addr/port do not work for e.g. sockaddr_un
+
+ >>> sockaddr().family
+ 0
+ >>> sockaddr().port
+ Traceback (most recent call last):
+ ...
+ NotImplementedError
+ >>> sockaddr().getnameinfo()
+ Traceback (most recent call last):
+ ...
+ NotImplementedError
+ """
+
+ # address family
+ # XXX: this should be a class constant! It's part of our type safety!
+ cdef readonly platform.sa_family_t family
+
+ cdef void _init_family (self, platform.sa_family_t family = ?)
+
+ # get the sockaddr/socklen
+ # each of these can be NULL to ignore it
+ cdef int _get_sockaddr (self, platform.sockaddr **sa_ptr, platform.socklen_t *sa_len) except -1
+
+ cdef platform.sockaddr* _get_sockaddr_ptr (self) except NULL
+ cdef platform.socklen_t _get_sockaddr_len (self) except -1
+
+ # set the sockaddr, socklen must match
+ cdef int _set_sockaddr (self, platform.sockaddr *sa, size_t sa_len) except -1
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qmsk/net/socket/_address.pyx Fri Sep 25 21:34:04 2009 +0300
@@ -0,0 +1,97 @@
+
+
+cdef class sockaddr :
+ cdef void _init_family (self, platform.sa_family_t family=platform.AF_UNSPEC) :
+ self.family = family
+
+ # XXX:use size_t
+ cdef int _get_sockaddr (self, platform.sockaddr **sa_ptr, platform.socklen_t *sa_len) except -1 :
+ """
+ Get the sockaddr pointer and sockaddr length for this address
+ """
+
+ raise NotImplementedError()
+
+ cdef platform.sockaddr* _get_sockaddr_ptr (self) except NULL :
+ """
+ Get the sockaddr pointer
+ """
+
+ cdef platform.sockaddr *sa
+ cdef platform.socklen_t sa_len
+
+ self._get_sockaddr(&sa, &sa_len)
+
+ return sa
+
+ cdef platform.socklen_t _get_sockaddr_len (self) except -1 :
+ """
+ Get the sockaddr len
+ """
+
+ cdef platform.sockaddr *sa
+ cdef platform.socklen_t sa_len
+
+ self._get_sockaddr(&sa, &sa_len)
+
+ return sa_len
+
+ cdef int _set_sockaddr (self, platform.sockaddr *sa, size_t sa_len) except -1 :
+ """
+ Set the sockaddr value for this address; sa_len must match!
+ """
+
+ raise NotImplementedError()
+
+ def getnameinfo (self) :
+ """
+ Returns a (host, serv) tuple for this address à la getnameinfo
+
+ >>> addr = sockaddr_in()
+ >>> assert addr.getnameinfo() == (addr.addr, str(addr.port))
+ """
+
+ cdef platform.sockaddr *sa
+ cdef platform.socklen_t sa_len
+
+ # XXX: take as args?
+ cdef int flags = platform.NI_NUMERICHOST | platform.NI_NUMERICSERV
+
+ # get our abstract sockaddr
+ self._get_sockaddr(&sa, &sa_len)
+
+ # get nice text format
+ return platform.getnameinfo(sa, sa_len, flags)
+
+ property addr :
+ """
+ The ASCII literal network address
+ """
+
+ def __get__ (self) :
+ """
+ Default implmentation using getnameinfo()
+ """
+
+ addr, port = self.getnameinfo()
+
+ return addr
+
+ property port :
+ """
+ The integer port number
+ """
+
+ def __get__ (self) :
+ """
+ Default implementation using getnameinfo() and int()
+ """
+
+ addr, port = self.getnameinfo()
+
+ return int(port)
+
+ def __repr__ (self) :
+ return "sockaddr(%d, %s, %d)" % (self.family, self.addr, self.port)
+
+
--- a/qmsk/net/socket/address.pxd Tue Sep 01 00:08:02 2009 +0300
+++ b/qmsk/net/socket/address.pxd Fri Sep 25 21:34:04 2009 +0300
@@ -6,43 +6,9 @@
endpoint - human-readable network address, corresponding to multiple sockaddr's
"""
-cimport qmsk.net.libc as libc
-
cimport qmsk.net.socket.platform as platform
-cdef class sockaddr :
- """
- A network-level socket address
-
- XXX: not abstract enough. Functions/properties like getnameinfo/addr/port do not work for e.g. sockaddr_un
-
- >>> sockaddr().family
- 0
- >>> sockaddr().port
- Traceback (most recent call last):
- ...
- NotImplementedError
- >>> sockaddr().getnameinfo()
- Traceback (most recent call last):
- ...
- NotImplementedError
- """
-
- # address family
- # XXX: this should be a class constant! It's part of our type safety!
- cdef readonly platform.sa_family_t family
-
- cdef void _init_family (self, platform.sa_family_t family = ?)
-
- # get the sockaddr/socklen
- # each of these can be NULL to ignore it
- cdef int _get_sockaddr (self, platform.sockaddr **sa_ptr, platform.socklen_t *sa_len) except -1
-
- cdef platform.sockaddr* _get_sockaddr_ptr (self) except NULL
- cdef platform.socklen_t _get_sockaddr_len (self) except -1
-
- # set the sockaddr, socklen must match
- cdef int _set_sockaddr (self, platform.sockaddr *sa, size_t sa_len) except -1
+from qmsk.net.socket._address cimport sockaddr
# build a sockaddr from the given sockaddr struct, based on sa_family
cdef sockaddr build_sockaddr (platform.sockaddr *sa, size_t sa_len)
@@ -82,17 +48,13 @@
cdef class endpoint :
"""
- A network-level socket endpoint. This is the level that humans mostly work with, but the tricky bit is that
- an endpoint can map to more than one sockaddr...
+ XXX: silly abstraction, just use the getaddrinfo function
- Hence, endpoints are stored as human-readable hostname/service strings, which are then translated to sockaddrs
- using getaddrinfo.
-
- >>> from __future__ import absolute_import; import socket as _socket
+ >>> from qmsk.net.socket.constants import *
>>> e = endpoint('127.0.0.1', 80)
>>> str(e)
'hostname=127.0.0.1, service=80'
- >>> res = e.getaddrinfo(_socket.AF_UNSPEC, _socket.SOCK_STREAM)
+ >>> res = e.getaddrinfo(AF_UNSPEC, SOCK_STREAM)
>>> len(res)
1
>>> str(res[0])
@@ -100,7 +62,7 @@
>>> e = endpoint('2001::5', 80)
>>> str(e)
'hostname=2001::5, service=80'
- >>> res = e.getaddrinfo(_socket.AF_UNSPEC, _socket.SOCK_STREAM)
+ >>> res = e.getaddrinfo(AF_UNSPEC, SOCK_STREAM)
>>> len(res)
1
>>> str(res[0])
--- a/qmsk/net/socket/address.pyx Tue Sep 01 00:08:02 2009 +0300
+++ b/qmsk/net/socket/address.pyx Fri Sep 25 21:34:04 2009 +0300
@@ -1,104 +1,13 @@
cimport qmsk.net.libc as libc
cimport qmsk.net.py as py
-from qmsk.net.socket.address cimport *
+#from qmsk.net.socket.address cimport *
+
+cimport qmsk.net.libc as libc
cimport qmsk.net.socket.platform as platform
-cdef class sockaddr :
- cdef void _init_family (self, platform.sa_family_t family=platform.AF_UNSPEC) :
- self.family = family
-
- # XXX:use size_t
- cdef int _get_sockaddr (self, platform.sockaddr **sa_ptr, platform.socklen_t *sa_len) except -1 :
- """
- Get the sockaddr pointer and sockaddr length for this address
- """
-
- raise NotImplementedError()
-
- cdef platform.sockaddr* _get_sockaddr_ptr (self) except NULL :
- """
- Get the sockaddr pointer
- """
-
- cdef platform.sockaddr *sa
- cdef platform.socklen_t sa_len
-
- self._get_sockaddr(&sa, &sa_len)
-
- return sa
-
- cdef platform.socklen_t _get_sockaddr_len (self) except -1 :
- """
- Get the sockaddr len
- """
-
- cdef platform.sockaddr *sa
- cdef platform.socklen_t sa_len
-
- self._get_sockaddr(&sa, &sa_len)
-
- return sa_len
-
- cdef int _set_sockaddr (self, platform.sockaddr *sa, size_t sa_len) except -1 :
- """
- Set the sockaddr value for this address; sa_len must match!
- """
-
- raise NotImplementedError()
-
- def getnameinfo (self) :
- """
- Returns a (host, serv) tuple for this address à la getnameinfo
-
- >>> addr = sockaddr_in()
- >>> assert addr.getnameinfo() == (addr.addr, str(addr.port))
- """
-
- cdef platform.sockaddr *sa
- cdef platform.socklen_t sa_len
-
- # XXX: take as args?
- cdef int flags = platform.NI_NUMERICHOST | platform.NI_NUMERICSERV
-
- # get our abstract sockaddr
- self._get_sockaddr(&sa, &sa_len)
-
- # get nice text format
- return platform.getnameinfo(sa, sa_len, flags)
-
- property addr :
- """
- The ASCII literal network address
- """
-
- def __get__ (self) :
- """
- Default implmentation using getnameinfo()
- """
-
- addr, port = self.getnameinfo()
-
- return addr
-
- property port :
- """
- The integer port number
- """
-
- def __get__ (self) :
- """
- Default implementation using getnameinfo() and int()
- """
-
- addr, port = self.getnameinfo()
-
- return int(port)
-
- def __repr__ (self) :
- return "sockaddr(%d, %s, %d)" % (self.family, self.addr, self.port)
-
+# concrete sockaddr implementation types
# mapping of AF -> sockaddr, user-modifyable
cimport qmsk.net.socket.af_inet, qmsk.net.socket.af_inet6
@@ -226,7 +135,7 @@
Look up given hostname/service using the given socket parameters, and return a sequence of addrinfo objects.
hostname - internet address/hostname to look up, or None (for INADDR_ANY/localhost, see AI_PASSIVE)
- service - port/service to use, or None (for ephemeral)
+ service - port/service to use, or None (for ephemeral). Should be given as a string
family - address family to use, one of AF_*. May be AF_UNSPEC.
socktype - socket type to use, one of SOCK_*.
protocol - protocol to use, one of IPPROTO_* or zero to pick the default protocol for the given
@@ -267,6 +176,10 @@
_hostname = hostname
if service is not None :
+ # XXX: also accept integer port number?
+ if isinstance(service, int) :
+ service = str(service)
+
_service = service
# operate!
--- a/qmsk/net/socket/af_inet.pxd Tue Sep 01 00:08:02 2009 +0300
+++ b/qmsk/net/socket/af_inet.pxd Fri Sep 25 21:34:04 2009 +0300
@@ -2,8 +2,8 @@
AF_INET-specific stuff
"""
-from qmsk.net.socket.address cimport *
-
+from qmsk.net.socket._address cimport sockaddr
+cimport qmsk.net.socket.platform as platform
cdef class sockaddr_in (sockaddr) :
"""
--- a/qmsk/net/socket/af_inet.pyx Tue Sep 01 00:08:02 2009 +0300
+++ b/qmsk/net/socket/af_inet.pyx Fri Sep 25 21:34:04 2009 +0300
@@ -1,3 +1,4 @@
+cimport qmsk.net.libc as libc
cimport qmsk.net.py as py
cdef class sockaddr_in (sockaddr) :
--- a/qmsk/net/socket/af_inet6.pxd Tue Sep 01 00:08:02 2009 +0300
+++ b/qmsk/net/socket/af_inet6.pxd Fri Sep 25 21:34:04 2009 +0300
@@ -2,8 +2,8 @@
AF_INET6-specific stuff
"""
-from qmsk.net.socket.address cimport *
-
+from qmsk.net.socket._address cimport sockaddr
+cimport qmsk.net.socket.platform as platform
cdef class sockaddr_in6 (sockaddr) :
"""
--- a/qmsk/net/socket/af_inet6.pyx Tue Sep 01 00:08:02 2009 +0300
+++ b/qmsk/net/socket/af_inet6.pyx Fri Sep 25 21:34:04 2009 +0300
@@ -1,3 +1,4 @@
+cimport qmsk.net.libc as libc
cimport qmsk.net.py as py
cdef class sockaddr_in6 (sockaddr) :
--- a/qmsk/net/socket/af_unix.pxd Tue Sep 01 00:08:02 2009 +0300
+++ b/qmsk/net/socket/af_unix.pxd Fri Sep 25 21:34:04 2009 +0300
@@ -2,7 +2,8 @@
AF_UNIX-specific stuff
"""
-from qmsk.net.socket.address cimport *
+from qmsk.net.socket._address cimport sockaddr
+cimport qmsk.net.socket.platform as platform
cdef class sockaddr_un (sockaddr) :
--- a/qmsk/net/socket/af_unix.pyx Tue Sep 01 00:08:02 2009 +0300
+++ b/qmsk/net/socket/af_unix.pyx Fri Sep 25 21:34:04 2009 +0300
@@ -1,5 +1,5 @@
+cimport qmsk.net.libc as libc
cimport qmsk.net.py as py
-cimport qmsk.net.libc as libc
cdef class sockaddr_un (sockaddr) :
--- a/qmsk/net/socket/sctp.pyx Tue Sep 01 00:08:02 2009 +0300
+++ b/qmsk/net/socket/sctp.pyx Fri Sep 25 21:34:04 2009 +0300
@@ -10,7 +10,6 @@
"""
-from qmsk.net.socket.sctp cimport *
from qmsk.net.socket.address cimport sockaddr
cimport qmsk.net.socket.platform as platform
--- a/qmsk/net/socket/socket.pyx Tue Sep 01 00:08:02 2009 +0300
+++ b/qmsk/net/socket/socket.pyx Fri Sep 25 21:34:04 2009 +0300
@@ -1,5 +1,6 @@
from qmsk.net.socket.socket cimport *
-from qmsk.net.socket.address cimport sockaddr, build_sockaddr
+from qmsk.net.socket._address cimport sockaddr
+from qmsk.net.socket.address cimport build_sockaddr
cimport qmsk.net.socket.platform as platform
cimport qmsk.net.libc as libc, qmsk.net.py as py
--- a/setup.py Tue Sep 01 00:08:02 2009 +0300
+++ b/setup.py Fri Sep 25 21:34:04 2009 +0300
@@ -30,6 +30,7 @@
cython_ext("qmsk.net.py", ["qmsk/net/py.pyx"]),
cython_ext("qmsk.net.socket.platform", ["qmsk/net/socket/platform.pyx"]),
cython_ext("qmsk.net.socket.constants", ["qmsk/net/socket/constants.pyx"]),
+ cython_ext("qmsk.net.socket._address", ["qmsk/net/socket/_address.pyx"]),
cython_ext("qmsk.net.socket.address", ["qmsk/net/socket/address.pyx"]),
cython_ext("qmsk.net.socket.socket", ["qmsk/net/socket/socket.pyx"]),
cython_ext("qmsk.net.socket.af_inet", ["qmsk/net/socket/af_inet.pyx"]),