socket.py
authorStefan Israelsson Tampe <stefan.itampe@gmail.com>
Fri, 24 Aug 2018 20:23:23 +0000 (22:23 +0200)
committerStefan Israelsson Tampe <stefan.itampe@gmail.com>
Fri, 24 Aug 2018 20:23:23 +0000 (22:23 +0200)
13 files changed:
modules/language/python/compile.scm
modules/language/python/dir.scm
modules/language/python/eval.scm
modules/language/python/for.scm
modules/language/python/module.scm
modules/language/python/module/_socket.scm [new file with mode: 0644]
modules/language/python/module/os.scm
modules/language/python/module/python.scm
modules/language/python/module/selectors.py
modules/language/python/module/socket.py [new file with mode: 0644]
modules/language/python/module/stat.scm
modules/language/python/module/string.scm
modules/oop/pf-objects.scm

index aec886bc821ee53414ceb101883b7886d09d8e5f..983eb66d521f1977e2e86f700571984991d91617 100644 (file)
       r)))
 
 
-(define-syntax-rule (use a ...)
+(define-syntax-rule (use p l a ...)
   (catch #t
-    (lambda () (use-modules a ...))
+    (lambda ()
+      (if (not p) (reload-module (resolve-module l)))
+      (use-modules a ...))
     (lambda x
       (warn "failed to load " x)
       (raise (ImportError '(a ...))))))
 
 (define (pre) (warn "Patching guile will lead to way better experience use 'python.patch' on guile-2.2 e.g. (use-modules (language python guilemod))"))
 
+(define (gw-persson x l)
+  (if (or (member x (fluid-ref (@@ (system base message) %dont-warn-list)))
+          (member x l))
+      x
+      #f))
+
 (define-syntax clear-warning-data
   (lambda (x)
     (catch #t
                           (fluid-set! decorations '())
                           r))               
                (class   (exp vs class))
+               (vo  vs)
                (vs  (union (list class) vs))
                (ns  (scope code '()))
                (ls  ns #;(diff ns vs))
                 ,(if parents
                      (arglist->pkw (clean parents))
                      `(,(G 'cons) '() '()))
-                ,(map (lambda (x) `(define ,x #f)) ls)
+                ,(map (lambda (x) `(define ,x ,(gw-persson x vo))) ls)
                 ,(wth (exp vs code)))))))))))
  (#:verb
   ((_ x) x))
  
  (#:import
   ((_ (#:from (() . nm) . #f))
-   (let* ((xl  (map (lambda (nm) (exp vs nm)) nm))
-          (l `(language python module ,@xl)))
+   (let* ((xl (map (lambda (nm) (exp vs nm)) nm))
+          (l  `(language python module ,@xl)))
 
      ;; Make sure to load the module in
-     (catch #t
-       (lambda () (Module (reverse l) (reverse xl)))
-       (lambda x #f))
-     
-     (for-each dont-warn (get-exported-symbols l))
-     
-     `(,(C 'use) ,l)))
+     (let ((? (catch #t
+                (lambda () (Module (reverse l) (reverse xl)) #t)
+                (lambda x #f))))
+       (if (eq? ? #t) (for-each dont-warn (get-exported-symbols l)))       
+       `(,(C 'use) ,? ',l ,l))))
   
   ((_ (#:from (() . nm)  l))
-   `(,(C 'use)  ((language python module ,@(map (lambda (nm) (exp vs nm)) nm))
-                 #:select
-                 ,(map (lambda (x)
-                         (match x
-                           ((a . #f)
-                            (let ((s (exp vs a)))
-                              (fluid-set! ignore
-                                          (cons s (fluid-ref ignore)))
-                              (dont-warn s)
-                              s))
-                                     
-                           ((a . b)
-                            (let ((s1 (exp vs a))
-                                  (s2 (exp vs b)))
-                              (fluid-set! ignore
-                                          (cons s2
-                                                (fluid-ref ignore)))
-                              (dont-warn s2)
-                              (cons s1 s2)))))
-                       l))))
+   ;; Make sure to load the module in
+   (let* ((xl  (map (lambda (nm) (exp vs nm)) nm))
+          (ll `(language python module ,@xl))
+          (?  (catch #t
+                (lambda () (Module (reverse ll) (reverse xl)) #t)
+                (lambda x #f))))
+     
+     (if ? (for-each dont-warn (get-exported-symbols ll)))
+     
+     `(,(C 'use) ,? ',ll
+       (,ll
+        #:select
+        ,(map (lambda (x)
+                (match x
+                  ((a . #f)
+                   (let ((s (exp vs a)))
+                     (fluid-set! ignore
+                                 (cons s (fluid-ref ignore)))
+                     (dont-warn s)
+                     s))
+                  
+                  ((a . b)
+                   (let ((s1 (exp vs a))
+                         (s2 (exp vs b)))
+                     (fluid-set! ignore
+                                 (cons s2
+                                       (fluid-ref ignore)))
+                     (dont-warn s2)
+                     (cons s1 s2)))))
+              l)))))
                                              
   
   ((_ (#:name ((ids ...) . as) ...) ...)
    `(begin
       ,@(map
-        (lambda (ids as)
+         (lambda (ids as)
            `(begin
               ,@(map (lambda (ids as)
                        (let ((path (map (g vs exp) ids)))
                                  ((#:verb
                                    ((@ (language python module) import)
                                     ((@ (language python module) Module)
-                                     ',(append '(language python module) path))
+                                     ',(append '(language python module)
+                                               path))
                                     ,(exp vs (car ids)))))))))))
                      ids as)))
          ids as))))
              #`(let/ec ret l)
              code))))))
 
+(define void (list 'void))
+
 (define-syntax var
   (lambda (x)
     (syntax-case x (cons quote)
          (dont-warn (syntax->datum #'v))
          #'(if (and #f (module-defined? (current-module) 'v))
                (values)
-               (define! 'v #f)))))))
+               (define! 'v void)))))))
 
 (define-inlinable (non? x) (eq? x #:nil))
 
     ((_ '() v) (values))
     ((_  x  v)
      (define! 'x v))))
-
index 75c42d7139e6066ff2bbacf01899e9e4152c9315..0791666062fb9a95b126991243cbef19fbb008e3 100644 (file)
@@ -77,7 +77,7 @@
 (define-method (dir (o <py-list>))
   (cont
    (next-method)
-   (let ((l1 (pk (pylist-listing))))
+   (let ((l1 (pylist-listing)))
      (if (is-a? o <p>)
          (let* ((l2 (next-method))
                 (l  (+ l1 l2)))
index 53b4bcede7e4d8e1813b1e5cdc71a95a0eb9db09..a54ea648ead3494555ea23dde7b2ac5dcc98ebc5 100644 (file)
 
 (define-syntax-rule (L x) (@@ (ice-9 local-eval) x))
 
+(define MM (list 'error))
+(define (M mod)
+  (let ((l '()))
+    (module-for-each
+     (lambda (k v)
+       (if (not (eq? (variable-ref v) MM))
+           (set! l (cons (symbol->string k) l))))
+     mod)
+    l))
+
 (define-syntax globals
   (lambda (x)
     (syntax-case x ()
       ((g)
-       #'((L env-module) (locals g))))))
+       #'(M ((L env-module) (locals g)))))))
+
 
 (define* (local-eval x locals globals)
   "Evaluate the expression @var{x} within the local environment @var{local} and
index 76c9fa86e385a7d334224123395d49466bf49b4a..5b7b4a67082788376c9ae837a3b928cf0bf0c62c 100644 (file)
   o)
 
 (define-method (wrap-in (o <p>))
-  (aif it (pk 2 (ref (pk 1 o) '__iter__))
+  (aif it (ref o '__iter__)
        (let ((x (it)))
-         (pk 3  x)
          (cond
-          ((pair? x)
-           (wrap-in x))
-          (else
-           x)))
+          ((pair? x) (wrap-in x))
+          (else      x)))
        (next-method)))
 
 (define-method (next (l <p>))
 (set! (@@ (oop pf-objects) hashforeach)
   (lambda (f d)
     (for ((k v : d)) () (f k v))))
-
-#;
-(pk
- (for c ((x : (gen '(1 2 3)))) ((s 0))
-      (pk x)
-      (if (> x 2) (c s))
-      (+ s x)
-
-      #:final
-      s))
index 51270c20a3bcdcec8e571c494020bb02fc62a26e..8e705a8633462c0d46b740e413d65c3e4f042515 100644 (file)
@@ -8,6 +8,7 @@
   #:use-module (language python try)
   #:use-module (language python dir)
   #:use-module (language python list)
+  #:use-module (language python dict)
   #:export (Module private public import __import__ modules))
 
 (define-syntax-rule (aif it p x y) (let ((it p)) (if it x y)))
          (apply f l))
       (apply f l)))
 
-(define modules (make-hash-table))
+(define-python-class ms (dict)
+  (define __getitem__
+    (lambda (self k)
+      (if (string? k)
+          (aif it (py-get (slot-ref self 't) k #f)
+               it
+               (let* ((l   (map string->symbol (string-split k #\.)))
+                      (pth (cons* 'language 'python 'module l)))
+                 (Module (reverse pth) (reverse l))))
+          (pylist-ref (slot-ref self 't) k))))
+
+  (define get
+    (lambda* (self k #:optional (e #f))
+      (if (string? k)
+          (aif it (py-get (slot-ref self 't) k #f)
+               it
+               (let* ((l   (map string->symbol (string-split k #\.)))
+                      (pth (cons* 'language 'python 'module l)))
+                 (Module (reverse pth) (reverse l))))
+          (py-get (slot-ref self 't) k e)))))
+      
+          
+
+(define modules (ms))
 (define (__import__ x)
   (let ((x (py-get modules x #f)))
     (if x
         (values)
         (let ((e (Module x)))
-          (pylist-set! modules x e)))))
+          (pylist-set! modules x e)
+          e))))
diff --git a/modules/language/python/module/_socket.scm b/modules/language/python/module/_socket.scm
new file mode 100644 (file)
index 0000000..5d7730b
--- /dev/null
@@ -0,0 +1,710 @@
+(define-module (language python module _socket)
+  #:use-module (language python string)
+  #:use-module (language python yield)
+  #:use-module (language python bytes)
+  #:use-module (language python exceptions)
+  #:use-module (language python def)
+  #:use-module (language python list)
+  #:use-module (rnrs bytevectors)
+  #:use-module (rnrs io ports)
+
+  #:use-module (oop pf-objects)
+  #:export
+  (SOCK_CLOEXEC SOCK_NONBLOCK SOCK_RDM SOCK_STREAM
+                SOCK_DGRAM SOCK_RAW SOCK_SEQPACKET
+
+                MSG_CMSG_CLOEXEC MSG_CONFIRM MSG_CTRUNC MSG_DONTROUTE
+                MSG_DONTWAIT MSG_EOR MSG_ERRQUEUE MSG_FASTOPEN MSG_MORE
+                MSG_NOSIGNAL MSG_OOB MSG_PEEK MSG_TRUNC MSG_WAITALL
+                MSG_DONTROUTE MSG_DONTWAIT MSG_OOB MSG_PEEK
+
+                AI_ADDRCONFIG AI_CANONNAME AI_NUMERICSERV AI_V4MAPPED
+                AI_ALL AI_NUMERICHOST AI_PASSIVE
+
+                IP_ADD_MEMBERSHIP IP_DEFAULT_MULTICAST_LOOP
+                IP_DEFAULT_MULTICAST_TTL IP_DROP_MEMBERSHIP IP_HDRINCL
+                IP_MAX_MEMBERSHIPS IP_MULTICAST_IF IP_MULTICAST_LOOP
+                IP_MULTICAST_TTL IP_OPTIONS IP_RECVOPTS IP_RECVRETOPTS
+                IP_RETOPTS IP_TOS IP_TRANSPARENT IP_TTL
+
+                IPV6_CHECKSUM IPV6_DONTFRAG IPV6_DSTOPTS IPV6_HOPLIMIT
+                IPV6_HOPOPTS IPV6_JOIN_GROUP IPV6_LEAVE_GROUP
+                IPV6_MULTICAST_HOPS IPV6_MULTICAST_IF IPV6_MULTICAST_LOOP
+                IPV6_NEXTHOP IPV6_PATHMTU IPV6_PKTINFO IPV6_RECVDSTOPTS
+                IPV6_RECVHOPLIMIT IPV6_RECVHOPOPTS IPV6_RECVPATHMTU
+                IPV6_RECVPKTINFO IPV6_RECVRTHDR IPV6_RECVTCLASS
+                IPV6_RTHDR IPV6_RTHDRDSTOPTS IPV6_RTHDR_TYPE_0 IPV6_TCLASS
+                IPV6_UNICAST_HOPS IPV6_V6ONLY
+
+                IPPROTO_AH IPPROTO_DSTOPTS IPPROTO_EGP IPPROTO_ESP
+                IPPROTO_FRAGMENT IPPROTO_GRE IPPROTO_HOPOPTS IPPROTO_ICMP
+                IPPROTO_ICMPV6 IPPROTO_IDP IPPROTO_IGMP IPPROTO_IP
+                IPPROTO_IPIP IPPROTO_IPV6 IPPROTO_NONE IPPROTO_PIM
+                IPPROTO_PUP IPPROTO_RAW IPPROTO_ROUTING IPPROTO_RSVP
+                IPPROTO_SCTP IPPROTO_TCP IPPROTO_TP IPPROTO_UDP
+
+                INADDR_ALLHOSTS_GROUP INADDR_ANY INADDR_BROADCAST
+                INADDR_LOOPBACK INADDR_MAX_LOCAL_GROUP INADDR_NONE
+                INADDR_UNSPEC_GROUP
+
+                TCP_CONGESTION TCP_CORK TCP_DEFER_ACCEPT TCP_FASTOPEN
+                TCP_INFO TCP_KEEPCNT TCP_KEEPIDLE TCP_KEEPINTVL
+                TCP_LINGER2 TCP_MAXSEG TCP_NODELAY TCP_QUICKACK TCP_SYNCNT
+                TCP_USER_TIMEOUT TCP_WINDOW_CLAMP
+                
+                TIPC_ADDR_ID TIPC_ADDR_NAME TIPC_ADDR_NAMESEQ TIPC_CFG_SRV
+                TIPC_CLUSTER_SCOPE TIPC_CONN_TIMEOUT
+                TIPC_CRITICAL_IMPORTANCE TIPC_DEST_DROPPABLE
+                TIPC_HIGH_IMPORTANCE TIPC_IMPORTANCE TIPC_LOW_IMPORTANCE
+                TIPC_MEDIUM_IMPORTANCE TIPC_NODE_SCOPE TIPC_PUBLISHED
+                TIPC_SRC_DROPPABLE TIPC_SUBSCR_TIMEOUT TIPC_SUB_CANCEL
+                TIPC_SUB_PORTS TIPC_SUB_SERVICE TIPC_TOP_SRV
+                TIPC_WAIT_FOREVER TIPC_WITHDRAWN TIPC_ZONE_SCOPE
+                
+                SO_ACCEPTCONN SO_BINDTODEVICE SO_BROADCAST SO_DEBUG
+                SO_DOMAIN SO_DONTROUTE SO_ERROR SO_KEEPALIVE SO_LINGER
+                SO_MARK SO_OOBINLINE SO_PASSCRED SO_PASSSEC SO_PEERCRED
+                SO_PEERSEC SO_PRIORITY SO_PROTOCOL SO_RCVBUF SO_RCVLOWAT
+                SO_RCVTIMEO SO_REUSEADDR SO_REUSEPORT SO_SNDBUF
+                SO_SNDLOWAT SO_SNDTIMEO SO_TYPE
+                
+                SOL_ALG SOL_CAN_BASE SOL_CAN_RAW SOL_HCI SOL_IP SOL_RDS
+                SOL_SOCKET SOL_TCP SOL_TIPC SOL_UDP
+                
+                SOMAXCONN
+                
+                CMSG_LEN CMSG_SPACE
+                    
+                HCI_DATA_DIR HCI_FILTER HCI_TIME_STAMP
+
+                EAI_ADDRFAMILY EAI_AGAIN EAI_BADFLAGS EAI_FAIL EAI_FAMILY
+                EAI_MEMORY EAI_NODATA EAI_NONAME EAI_OVERFLOW EAI_SERVICE
+                EAI_SOCKTYPE EAI_SYSTEM
+
+                CAN_BCM CAN_BCM_RX_CHANGED CAN_BCM_RX_DELETE
+                CAN_BCM_RX_READ CAN_BCM_RX_SETUP CAN_BCM_RX_STATUS
+                CAN_BCM_RX_TIMEOUT CAN_BCM_TX_DELETE CAN_BCM_TX_EXPIRED
+                CAN_BCM_TX_READ CAN_BCM_TX_SEND CAN_BCM_TX_SETUP
+                CAN_BCM_TX_STATUS CAN_EFF_FLAG CAN_EFF_MASK CAN_ERR_FLAG
+                CAN_ERR_MASK CAN_RAW CAN_RAW_ERR_FILTER CAN_RAW_FD_FRAMES
+                CAN_RAW_FILTER CAN_RAW_LOOPBACK CAN_RAW_RECV_OWN_MSGS
+                CAN_RTR_FLAG CAN_SFF_MASK
+                    
+                BTPROTO_HCI BTPROTO_L2CAP BTPROTO_RFCOMM BTPROTO_SCO
+                    
+                BDADDR_ANY BDADDR_LOCAL
+
+                ALG_OP_DECRYPT ALG_OP_ENCRYPT ALG_OP_SIGN ALG_OP_VERIFY
+                ALG_SET_AEAD_ASSOCLEN ALG_SET_AEAD_AUTHSIZE ALG_SET_IV
+                ALG_SET_KEY ALG_SET_OP ALG_SET_PUBKEY
+                
+                AF_ALG AF_APPLETALK AF_ASH AF_ATMPVC AF_ATMSVC AF_AX25
+                AF_BLUETOOTH AF_BRIDGE AF_CAN AF_DECnet AF_ECONET AF_INET
+                AF_INET6 AF_IPX AF_IRDA AF_KEY AF_LLC AF_NETBEUI
+                AF_NETLINK AF_NETROM AF_PACKET AF_PPPOX AF_RDS AF_ROSE
+                AF_ROUTE AF_SECURITY AF_SNA AF_TIPC AF_UNIX AF_UNSPEC
+                AF_WANPIPE AF_X25
+                
+                SHUT_RD SHUT_RDWR SHUT_WR
+                
+                SCM_CREDENTIALS SCM_RIGHTS
+                    
+                PF_CAN PF_PACKET PF_RDS
+                    
+                PACKET_BROADCAST PACKET_FASTROUTE PACKET_HOST
+                PACKET_LOOPBACK PACKET_MULTICAST PACKET_OTHERHOST
+                PACKET_OUTGOING
+
+                NI_DGRAM NI_MAXHOST NI_MAXSERV NI_NAMEREQD NI_NOFQDN
+                NI_NUMERICHOST NI_NUMERICSERV
+                
+                NETLINK_CRYPTO NETLINK_DNRTMSG NETLINK_FIREWALL
+                NETLINK_IP6_FW NETLINK_NFLOG NETLINK_ROUTE
+                NETLINK_USERSOCK NETLINK_XFRM
+                
+                socket
+
+                dup getaddrinfo getdefaulttimeout gethostbyname
+                gethostbyname_ex gethostname getnameinfo getprotobyn
+                getservbyname htonl htons if_indextoname if_nameindex
+                if_nametoindex inet_aton inet_ntop ntohl setdefaulttimeout
+                getservbyport
+                ))
+
+(define-syntax-rule (aif it p . l) (let ((it p)) (if it . l)))
+
+(define-syntax-rule (wrap self it code ...)
+  (aif it (ref self '__fileno)
+       (begin code ...)
+       (raise (ValueError "no socket created"))))
+
+(define NETLINK_CRYPTO 21)
+(define NETLINK_DNRTMSG 14)
+(define NETLINK_FIREWALL 3)
+(define NETLINK_IP6_FW 13)
+(define NETLINK_NFLOG 5)
+(define NETLINK_ROUTE 0)
+(define NETLINK_USERSOCK 2)
+(define NETLINK_XFRM 6)
+
+(define NI_DGRAM 16)
+(define NI_MAXHOST 1025)
+(define NI_MAXSERV 32)
+(define NI_NAMEREQD 8)
+(define NI_NOFQDN 4)
+(define NI_NUMERICHOST 1)
+(define NI_NUMERICSERV 2)
+
+(define PACKET_BROADCAST 1)
+(define PACKET_FASTROUTE 6)
+(define PACKET_HOST 0)
+(define PACKET_LOOPBACK 5)
+(define PACKET_MULTICAST 2)
+(define PACKET_OTHERHOST 3)
+(define PACKET_OUTGOING 4)
+
+(define PF_CAN 29)
+(define PF_PACKET 17)
+(define PF_RDS 21)
+
+(define SCM_CREDENTIALS 2)
+(define SCM_RIGHTS 1)
+
+
+(define SHUT_RD 0)
+(define SHUT_RDWR 2)
+(define SHUT_WR 1)
+
+(define AF_ALG 38)
+(define AF_APPLETALK 5)
+(define AF_ASH 18)
+(define AF_ATMPVC 8)
+(define AF_ATMSVC 20)
+(define AF_AX25 3)
+(define AF_BLUETOOTH 31)
+(define AF_BRIDGE 7)
+(define AF_CAN 29)
+(define AF_DECnet 12)
+(define AF_ECONET 19)
+(define AF_INET 2)
+(define AF_INET6 10)
+(define AF_IPX 4)
+(define AF_IRDA 23)
+(define AF_KEY 15)
+(define AF_LLC 26)
+(define AF_NETBEUI 13)
+(define AF_NETLINK 16)
+(define AF_NETROM 6)
+(define AF_PACKET 17)
+(define AF_PPPOX 24)
+(define AF_RDS 21)
+(define AF_ROSE 11)
+(define AF_ROUTE 16)
+(define AF_SECURITY 14)
+(define AF_SNA 22)
+(define AF_TIPC 30)
+(define AF_UNIX 1)
+(define AF_UNSPEC 0)
+(define AF_WANPIPE 25)
+(define AF_X25 9)
+
+(define ALG_OP_DECRYPT 0)
+(define ALG_OP_ENCRYPT 1)
+(define ALG_OP_SIGN 2)
+(define ALG_OP_VERIFY 3)
+(define ALG_SET_AEAD_ASSOCLEN 4)
+(define ALG_SET_AEAD_AUTHSIZE 5)
+(define ALG_SET_IV 2)
+(define ALG_SET_KEY 1)
+(define ALG_SET_OP 3)
+(define ALG_SET_PUBKEY 6)
+
+(define BDADDR_ANY   "00:00:00:00:00:00")
+(define BDADDR_LOCAL "00:00:00:FF:FF:FF")
+
+(define BTPROTO_HCI 1)
+(define BTPROTO_L2CAP 0)
+(define BTPROTO_RFCOMM 3)
+(define BTPROTO_SCO 2)
+
+(define CAN_BCM 2)
+(define CAN_BCM_RX_CHANGED 12)
+(define CAN_BCM_RX_DELETE 6)
+(define CAN_BCM_RX_READ 7)
+(define CAN_BCM_RX_SETUP 5)
+(define CAN_BCM_RX_STATUS 10)
+(define CAN_BCM_RX_TIMEOUT 11)
+(define CAN_BCM_TX_DELETE 2)
+(define CAN_BCM_TX_EXPIRED 9)
+(define CAN_BCM_TX_READ 3)
+(define CAN_BCM_TX_SEND 4)
+(define CAN_BCM_TX_SETUP 1)
+(define CAN_BCM_TX_STATUS 8)
+(define CAN_EFF_FLAG 2147483648)
+(define CAN_EFF_MASK 536870911)
+(define CAN_ERR_FLAG 536870912)
+(define CAN_ERR_MASK 536870911)
+(define CAN_RAW 1)
+(define CAN_RAW_ERR_FILTER 2)
+(define CAN_RAW_FD_FRAMES 5)
+(define CAN_RAW_FILTER 1)
+(define CAN_RAW_LOOPBACK 3)
+(define CAN_RAW_RECV_OWN_MSGS 4)
+(define CAN_RTR_FLAG 1073741824)
+(define CAN_SFF_MASK 2047)
+
+(define (CMSG_LEN . l)
+  (error "CMSG_LEN not implemented"))
+(define (CMSG_SPACE . l)
+  (error "CMSG_SPACE not implemented"))
+
+(define EAI_ADDRFAMILY -9)
+(define EAI_AGAIN -3)
+(define EAI_BADFLAGS -1)
+(define EAI_FAIL -4)
+(define EAI_FAMILY -6)
+(define EAI_MEMORY -10)
+(define EAI_NODATA -5)
+(define EAI_NONAME -2)
+(define EAI_OVERFLOW -12)
+(define EAI_SERVICE -8)
+(define EAI_SOCKTYPE -7)
+(define EAI_SYSTEM -11)
+
+(define HCI_DATA_DIR 1)
+(define HCI_FILTER 2)
+(define HCI_TIME_STAMP 3)
+
+(define SOMAXCONN 128)
+
+(define SOL_ALG 279)
+(define SOL_CAN_BASE 100)
+(define SOL_CAN_RAW 101)
+(define SOL_HCI 0)
+(define SOL_IP 0)
+(define SOL_RDS 276)
+(define SOL_SOCKET 1)
+(define SOL_TCP 6)
+(define SOL_TIPC 271)
+(define SOL_UDP 17)
+
+(define SO_ACCEPTCONN 30)
+(define SO_BINDTODEVICE 25)
+(define SO_BROADCAST 6)
+(define SO_DEBUG 1)
+(define SO_DOMAIN 39)
+(define SO_DONTROUTE 5)
+(define SO_ERROR 4)
+(define SO_KEEPALIVE 9)
+(define SO_LINGER 13)
+(define SO_MARK 36)
+(define SO_OOBINLINE 10)
+(define SO_PASSCRED 16)
+(define SO_PASSSEC 34)
+(define SO_PEERCRED 17)
+(define SO_PEERSEC 31)
+(define SO_PRIORITY 12)
+(define SO_PROTOCOL 38)
+(define SO_RCVBUF 8)
+(define SO_RCVLOWAT 18)
+(define SO_RCVTIMEO 20)
+(define SO_REUSEADDR 2)
+(define SO_REUSEPORT 15)
+(define SO_SNDBUF 7)
+(define SO_SNDLOWAT 19)
+(define SO_SNDTIMEO 21)
+(define SO_TYPE 3)
+
+(define TIPC_ADDR_ID 3)
+(define TIPC_ADDR_NAME 2)
+(define TIPC_ADDR_NAMESEQ 1)
+(define TIPC_CFG_SRV 0)
+(define TIPC_CLUSTER_SCOPE 2)
+(define TIPC_CONN_TIMEOUT 130)
+(define TIPC_CRITICAL_IMPORTANCE 3)
+(define TIPC_DEST_DROPPABLE 129)
+(define TIPC_HIGH_IMPORTANCE 2)
+(define TIPC_IMPORTANCE 127)
+(define TIPC_LOW_IMPORTANCE 0)
+(define TIPC_MEDIUM_IMPORTANCE 1)
+(define TIPC_NODE_SCOPE 3)
+(define TIPC_PUBLISHED 1)
+(define TIPC_SRC_DROPPABLE 128)
+(define TIPC_SUBSCR_TIMEOUT 3)
+(define TIPC_SUB_CANCEL 4)
+(define TIPC_SUB_PORTS 1)
+(define TIPC_SUB_SERVICE 2)
+(define TIPC_TOP_SRV 1)
+(define TIPC_WAIT_FOREVER -1)
+(define TIPC_WITHDRAWN 2)
+(define TIPC_ZONE_SCOPE 1)
+
+(define TCP_CONGESTION 13)
+(define TCP_CORK 3)
+(define TCP_DEFER_ACCEPT 9)
+(define TCP_FASTOPEN 23)
+(define TCP_INFO 11)
+(define TCP_KEEPCNT 6)
+(define TCP_KEEPIDLE 4)
+(define TCP_KEEPINTVL 5)
+(define TCP_LINGER2 8)
+(define TCP_MAXSEG 2)
+(define TCP_NODELAY 1)
+(define TCP_QUICKACK 12)
+(define TCP_SYNCNT 7)
+(define TCP_USER_TIMEOUT 18)
+(define TCP_WINDOW_CLAMP 10)
+
+(define INADDR_ALLHOSTS_GROUP 3758096385)
+(define INADDR_ANY 0)
+(define INADDR_BROADCAST 4294967295)
+(define INADDR_LOOPBACK 2130706433)
+(define INADDR_MAX_LOCAL_GROUP 3758096639)
+(define INADDR_NONE 4294967295)
+(define INADDR_UNSPEC_GROUP 3758096384)
+
+(define IPPROTO_AH 51)
+(define IPPROTO_DSTOPTS 60)
+(define IPPROTO_EGP 8)
+(define IPPROTO_ESP 50)
+(define IPPROTO_FRAGMENT 44)
+(define IPPROTO_GRE 47)
+(define IPPROTO_HOPOPTS 0)
+(define IPPROTO_ICMP 1)
+(define IPPROTO_ICMPV6 58)
+(define IPPROTO_IDP 22)
+(define IPPROTO_IGMP 2)
+(define IPPROTO_IP 0)
+(define IPPROTO_IPIP 4)
+(define IPPROTO_IPV6 41)
+(define IPPROTO_NONE 59)
+(define IPPROTO_PIM 103)
+(define IPPROTO_PUP 12)
+(define IPPROTO_RAW 255)
+(define IPPROTO_ROUTING 43)
+(define IPPROTO_RSVP 46)
+(define IPPROTO_SCTP 132)
+(define IPPROTO_TCP 6)
+(define IPPROTO_TP 29)
+(define IPPROTO_UDP 17)
+
+(define IP_ADD_MEMBERSHIP 35)
+(define IP_DEFAULT_MULTICAST_LOOP 1)
+(define IP_DEFAULT_MULTICAST_TTL 1)
+(define IP_DROP_MEMBERSHIP 36)
+(define IP_HDRINCL 3)
+(define IP_MAX_MEMBERSHIPS 20)
+(define IP_MULTICAST_IF 32)
+(define IP_MULTICAST_LOOP 34)
+(define IP_MULTICAST_TTL 33)
+(define IP_OPTIONS 4)
+(define IP_RECVOPTS 6)
+(define IP_RECVRETOPTS 7)
+(define IP_RETOPTS 7)
+(define IP_TOS 1)
+(define IP_TRANSPARENT 19)
+(define IP_TTL 2)
+
+(define IPV6_CHECKSUM 7)
+(define IPV6_DONTFRAG 62)
+(define IPV6_DSTOPTS 59)
+(define IPV6_HOPLIMIT 52)
+(define IPV6_HOPOPTS 54)
+(define IPV6_JOIN_GROUP 20)
+(define IPV6_LEAVE_GROUP 21)
+(define IPV6_MULTICAST_HOPS 18)
+(define IPV6_MULTICAST_IF 17)
+(define IPV6_MULTICAST_LOOP 19)
+(define IPV6_NEXTHOP 9)
+(define IPV6_PATHMTU 61)
+(define IPV6_PKTINFO 50)
+(define IPV6_RECVDSTOPTS 58)
+(define IPV6_RECVHOPLIMIT 51)
+(define IPV6_RECVHOPOPTS 53)
+(define IPV6_RECVPATHMTU 60)
+(define IPV6_RECVPKTINFO 49)
+(define IPV6_RECVRTHDR 56)
+(define IPV6_RECVTCLASS 66)
+(define IPV6_RTHDR 57)
+(define IPV6_RTHDRDSTOPTS 55)
+(define IPV6_RTHDR_TYPE_0 0)
+(define IPV6_TCLASS 67)
+(define IPV6_UNICAST_HOPS 16)
+(define IPV6_V6ONLY 26)
+
+
+(define AF_INET   (@ (guile) AF_INET))
+(define AF_INET6  (@ (guile) AF_INET6))
+(define AF_UNIX   (@ (guile) AF_UNIX))
+(define AF_UNSPEC (@ (guile) AF_UNSPEC))
+
+(define SOCK_CLOEXEC   (@ (guile) SOCK_CLOEXEC))
+(define SOCK_NONBLOCK  (@ (guile) SOCK_NONBLOCK))
+(define SOCK_RDM       (@ (guile) SOCK_RDM))
+(define SOCK_STREAM    (@ (guile) SOCK_STREAM))
+(define SOCK_DGRAM     (@ (guile) SOCK_DGRAM))
+(define SOCK_RAW       (@ (guile) SOCK_RAW))
+(define SOCK_SEQPACKET (@ (guile) SOCK_SEQPACKET))
+
+(define MSG_DONTROUTE (@ (guile) MSG_DONTROUTE))
+(define MSG_DONTWAIT  (@ (guile) MSG_DONTWAIT))
+(define MSG_OOB       (@ (guile) MSG_OOB))
+(define MSG_PEEK      (@ (guile) MSG_PEEK))
+(define MSG_CMSG_CLOEXEC 1073741824)
+(define MSG_CONFIRM 2048)
+(define MSG_CTRUNC 8)
+(define MSG_EOR 128)
+(define MSG_ERRQUEUE 8192)
+(define MSG_FASTOPEN 536870912)
+(define MSG_MORE 32768)
+(define MSG_NOSIGNAL 16384)
+(define MSG_TRUNC 32)
+(define MSG_WAITALL 256)
+
+(define AI_ADDRCONFIG  (@ (guile) AI_ADDRCONFIG))
+(define AI_CANONNAME   (@ (guile) AI_CANONNAME))
+(define AI_NUMERICSERV (@ (guile) AI_NUMERICSERV))
+(define AI_V4MAPPED    (@ (guile) AI_V4MAPPED))
+(define AI_ALL         (@ (guile) AI_ALL))
+(define AI_NUMERICHOST (@ (guile) AI_NUMERICHOST))
+(define AI_PASSIVE     (@ (guile) AI_PASSIVE))
+
+(define scm-socket     (@ (guile) socket))
+
+(define-python-class socket ()
+  (define __init__
+    (lam (self (= family AF_INET) (= type SOCK_STREAM) (= proto 0)
+               (= fileno None))
+      (set self '__family  family)
+      (set self '__type    type)
+      (set self '__proto   proto)
+      (set self '__fileno
+           (if (port? fileno)
+               fileno
+               (if (integer? fileno)
+                   (fdes->ports fileno)
+                   ((@ (guile) socket) family type proto))))))
+                 
+  
+  (define _accept
+    (lambda (self)
+      (wrap self it
+            (let ((r ((@ (guile) accept) it)))
+              (values (car it) (cdr it))))))
+             
+  
+  (define close
+    (lambda (self)
+      (wrap self it (close it))))
+
+  (define connect
+    (lambda (self addr)
+      (catch #t
+        (lambda ()
+          (wrap self it
+                (aif it ((@ (guile) connect) it (scm-str addr))
+                     0
+                     EAGAIN)
+                EBADF))
+        (lambda x EBADF))))
+  
+  (define dup
+    (lambda (self)
+      (wrap self it
+            (dup (port->fdes it)))))
+  
+  (define getpeername
+    (lambda (self)
+      (wrap self it
+            ((@ (guile) getpeername) it))))
+
+  (define getsockname
+    (lambda (self)
+      (wrap self it
+            ((@ (guile) getsockname) it))))
+
+  (define getsockopt
+    (lam (self level optname (= buflen 0))
+      (wrap self it
+            ((@ (guile) getsockopt) it level optname))))
+
+  (define gettimeout
+    (lambda (self) #f))
+
+  (define listen
+    (lambda* (self #:optional (backlog 5))
+      (wrap self it
+            ((@ (guile) listen) it backlog))))
+
+  (define recv
+    (lambda* (self buffersize #:optional (flags 0))
+      (wrap self it
+            (let ((buf (make-bytevector buffersize)))
+              (let ((n (recv it buf flags)))
+                (let ((r (make-bytevector n)))
+                  (let lp ((i 0))
+                    (if (< i n)
+                        (bytevector-u8-set! r i (bytevector-u8-ref buf i))
+                        (bytes r)))))))))
+
+
+  (define recv_into
+    (lambda* (self buffer #:optional (nbytes (len buffer)) (flags 0))
+      (let ((r (recv self nbytes flags)))
+        (let ((n (len r)))
+          (let lp ((i 0))
+            (if (< i n)
+                (pylist-set! buffer i (pylist-ref r i))
+                (values)))))))
+
+  (define recvmsg
+    (lambda* (self buffsize #:optional (ancbufsize 0) (flags 0))
+      (error "recvmsg not implemented")))
+
+  (define recvmsg_into
+    (lambda* (self buffers #:optional (ancbufsize 0) (flags 0))
+      (error "recvmsg not implemented")))
+
+  (define send
+    (lambda* (self data #:optional (flags 0))
+      (wrap self it
+            ((@ (guile) send) it (bv-scm data) flags))))
+
+  (define sendall
+    (lambda* (self data #:optional (flags 0))
+      (let ((n (len data)))
+        (let lp ((i 0) (b data))
+          (if (= i n)
+              (values)
+              (let ((j (send self data flags)))
+                (lp (+ i j) (pylist-slice i (+ i j) None))))))))
+    
+
+  (define sendmsg
+    (lambda* (self buffers #:optional (ancdata 0) (flags 0) address None)
+      (error "not sendmsg is not implemented")))
+
+  (define sendmsg_afalg
+    (lambda x
+      (error "not sendmsg_afalg is not implemented")))
+
+  (define sendto
+    (case-lambda
+      ((s data address)
+       (sendto s data 0 address))
+      ((s data flags address)
+       (values))))
+
+  (define setblocking
+    (lambda (self flag)
+      (if flag
+          (settimeout self None)
+          (settimeout self 0.0))))
+
+  (define setsockopt
+    (case-lambda
+      ((self level option value) #f)
+      ((self level option value optlen) #f)))
+        
+  (define settimeout
+    (lambda (self time)
+      #f))
+
+  (define shutdown
+    (lambda (self flag)
+      (wrap self it
+            ((@ (guile) shutdown) it flag)))))
+
+
+(define (dup x)
+  (if (port? x)
+      (fdes->ports ((@ (guile) dup) (port->fdes x)))
+      (fdes->ports ((@ (guile) dup) x))))
+
+(define (getaddrinfo . l)
+  (apply (@ (guile) getaddrinfo) l))
+
+(define (getdefaulttimeout . l)
+  (fluid-ref *default-time-out*))
+
+(define (gethostbyname host)
+  ((@ (guile) gethostbyname) host))
+
+(define (gethostbyname_ex host)
+  (error "not implemented"))
+
+(define (gethostname . l)
+  (apply (@ (guile) gethostname) l))
+
+(define (getnameinfo sockaddr flags)
+  (error "not implemented"))
+
+(define (getprotobyname name)
+  ((@ (guile) getprotobyname) name))
+
+(define* (getservbyname . l)
+  (apply (@ (guile) getservbyname) l))
+
+(define* (getservbyport . l)
+  (apply (@ (guile) getservbyport) l))
+
+(define (if_indextoname if_index)
+  (error "not implemented"))
+
+(define (if_nameindex)
+  (error "not implemented"))
+
+(define (if_nametoindex if_name)
+  (error "not implemented"))
+
+(define (inet_aton x)
+  (inet-pton AF_INET x))
+
+(define (inet_ntoa x)
+  (inet-ntop AF_INET x))
+
+(define (inet_ntop x)
+  ((@ (guile) inet-ntop) x))
+
+(define (inet_pton x y)
+  ((@ (guile) inet-pton) x y))
+
+(define (f32 i)
+  (let ((bv (make-bytevector 4)))
+    (bytevector-u32-set! bv 0 i 'big)
+    (bytevector-u32-ref  bv 0 (native-endianness))))
+
+(define (f16 i)
+  (let ((bv (make-bytevector 4)))
+    (bytevector-u16-set! bv 0 i 'big)
+    (bytevector-u16-ref  bv 0 (native-endianness))))
+
+(define (ntohl i) (f32 i))
+(define (ntohs i) (f16 i))
+(define (htonl i) (f32 i))
+(define (htons i) (f16 i))
+
+(define *default-time-out* (make-fluid None))
+(define (setdefaulttimeout x)
+  (fluid-set! *default-time-out* x))
+
+(define (sethostname x)
+  ((@ (guile) sethostname) (scm-str x)))
+
+
+
+
+      
+
+
+
+
+    
+
+
+      
+
+
+
+
+    
index 16ee6e67bf767dda3f0eacce54dd5ba798864a61..d593b5851feb7c8e19f51c870940deecd4d86327 100644 (file)
@@ -14,6 +14,7 @@
   #:use-module (language python module)
   #:use-module (language python exceptions)
   #:use-module (language python yield)
+  #:use-module (language python dir)
   #:use-module (language python range)
   #:use-module (language python string)
   #:use-module (language python bytes)
   (py-list (apply getrandom_ l)))
 
 (define path "posixpath")
+
+(define (_get_exports_list mod)
+  (let ((p (rawref mod '_private)))
+    (rawset mod '_private #f)
+    (let ((l (dir mod)))
+      (rawset mod '_private p)
+      l)))
index 1c15d40c85a4ffae8cc670fc61cc72f34d6700f5..f105f2202d92e01eba9530f198386f3a618df9b1 100644 (file)
@@ -25,3 +25,5 @@
   (Module '(path os module python language) '(path os)))
 
 (re-export-all (language python module _python))
+
+(set! (@@ (language python eval) MM) (@@ (language python compile) void))
index 41d70ba1b16188dad073fb95395c6ecfe760573f..6afb52ee48581b51e7c391e9491777ee95be0ad4 100644 (file)
@@ -1,5 +1,4 @@
 module(selectors)
-
 """Selectors module.
 
 This module allows high-level and efficient I/O multiplexing, built upon the
@@ -10,13 +9,14 @@ This module allows high-level and efficient I/O multiplexing, built upon the
 from abc import ABCMeta, abstractmethod
 from collections import namedtuple, Mapping
 import math
-import select as selectraw
+import select
 import sys
 
 # generic events, that must be mapped to implementation-specific ones
 EVENT_READ = (1 << 0)
 EVENT_WRITE = (1 << 1)
 
+
 def _fileobj_to_fd(fileobj):
     """Return a file descriptor from a file object.
 
@@ -44,6 +44,11 @@ def _fileobj_to_fd(fileobj):
 
 SelectorKey = namedtuple('SelectorKey', ['fileobj', 'fd', 'events', 'data'])
 
+SelectorKey.__doc__ = """SelectorKey(fileobj, fd, events, data)
+
+    Object used to associate a file object to its backing
+    file descriptor, selected event mask, and attached data.
+"""
 
 class _SelectorMapping(Mapping):
     """Mapping of file objects to selector keys."""
@@ -64,6 +69,7 @@ class _SelectorMapping(Mapping):
     def __iter__(self):
         return iter(self._selector._fd_to_key)
 
+
 class BaseSelector(metaclass=ABCMeta):
     """Selector abstract base class.
 
@@ -189,6 +195,7 @@ class BaseSelector(metaclass=ABCMeta):
     def __exit__(self, *args):
         self.close()
 
+
 class _BaseSelectorImpl(BaseSelector):
     """Base selector implementation."""
 
@@ -298,10 +305,10 @@ class SelectSelector(_BaseSelectorImpl):
 
     if sys.platform == 'win32':
         def _select(self, r, w, _, timeout=None):
-            r, w, x = selectraw.select(r, w, w, timeout)
+            r, w, x = select.select(r, w, w, timeout)
             return r, w + x, []
     else:
-        _select = selectraw.select
+        _select = select.select
 
     def select(self, timeout=None):
         timeout = None if timeout is None else max(timeout, 0)
@@ -324,132 +331,275 @@ class SelectSelector(_BaseSelectorImpl):
                 ready.append((key, events & key.events))
         return ready
 
-class PollSelector(_BaseSelectorImpl):
-    """Poll-based selector."""
-
-    def __init__(self):
-        super().__init__()
-        self._poll = selectraw.poll()
 
-    def register(self, fileobj, events, data=None):
-        key = super().register(fileobj, events, data)
-        poll_events = 0
-        if events & EVENT_READ:
-            poll_events |= selectraw.POLLIN
-        if events & EVENT_WRITE:
-            poll_events |= selectraw.POLLOUT
-        self._poll.register(key.fd, poll_events)
-        return key
-
-    def unregister(self, fileobj):
-        key = super().unregister(fileobj)
-        self._poll.unregister(key.fd)
-        return key
-
-    def select(self, timeout=None):
-        if timeout is None:
-            timeout = None
-        elif timeout <= 0:
-            timeout = 0
-        else:
-            # poll() has a resolution of 1 millisecond, round away from
-            # zero to wait *at least* timeout seconds.
-            timeout = math.ceil(timeout * 1e3)
-        ready = []
-        try:
-            fd_event_list = self._poll.poll(timeout)
-        except InterruptedError:
+if hasattr(select, 'poll'):
+
+    class PollSelector(_BaseSelectorImpl):
+        """Poll-based selector."""
+
+        def __init__(self):
+            super().__init__()
+            self._poll = select.poll()
+
+        def register(self, fileobj, events, data=None):
+            key = super().register(fileobj, events, data)
+            poll_events = 0
+            if events & EVENT_READ:
+                poll_events |= select.POLLIN
+            if events & EVENT_WRITE:
+                poll_events |= select.POLLOUT
+            self._poll.register(key.fd, poll_events)
+            return key
+
+        def unregister(self, fileobj):
+            key = super().unregister(fileobj)
+            self._poll.unregister(key.fd)
+            return key
+
+        def select(self, timeout=None):
+            if timeout is None:
+                timeout = None
+            elif timeout <= 0:
+                timeout = 0
+            else:
+                # poll() has a resolution of 1 millisecond, round away from
+                # zero to wait *at least* timeout seconds.
+                timeout = math.ceil(timeout * 1e3)
+            ready = []
+            try:
+                fd_event_list = self._poll.poll(timeout)
+            except InterruptedError:
+                return ready
+            for fd, event in fd_event_list:
+                events = 0
+                if event & ~select.POLLIN:
+                    events |= EVENT_WRITE
+                if event & ~select.POLLOUT:
+                    events |= EVENT_READ
+
+                key = self._key_from_fd(fd)
+                if key:
+                    ready.append((key, events & key.events))
             return ready
-        for fd, event in fd_event_list:
-            events = 0
-            if event & ~selectraw.POLLIN:
-                events |= EVENT_WRITE
-            if event & ~selectraw.POLLOUT:
-                events |= EVENT_READ
-
-            key = self._key_from_fd(fd)
-            if key:
-                ready.append((key, events & key.events))
-        return ready
-
-
-class EpollSelector(_BaseSelectorImpl):
-    """Epoll-based selector."""
 
-    def __init__(self):
-        super().__init__()
-        self._epoll = selectraw.epoll()
-
-    def fileno(self):
-        return self._epoll.fileno()
 
-    def register(self, fileobj, events, data=None):
-        key = super().register(fileobj, events, data)
-        epoll_events = 0
-        if events & EVENT_READ:
-            epoll_events |= selectraw.EPOLLIN
-        if events & EVENT_WRITE:
-            epoll_events |= selectraw.EPOLLOUT
-        try:
-            self._epoll.register(key.fd, epoll_events)
-        except BaseException:
-            super().unregister(fileobj)
-            raise
-        return key
-
-    def unregister(self, fileobj):
-        key = super().unregister(fileobj)
-        try:
-            self._epoll.unregister(key.fd)
-        except OSError:
-            # This can happen if the FD was closed since it
-            # was registered.
-            pass
-        return key
-
-    def select(self, timeout=None):
-        if timeout is None:
-            timeout = -1
-        elif timeout <= 0:
-            timeout = 0
-        else:
-            # epoll_wait() has a resolution of 1 millisecond, round away
-            # from zero to wait *at least* timeout seconds.
-            timeout = math.ceil(timeout * 1e3) * 1e-3
-
-        # epoll_wait() expects `maxevents` to be greater than zero;
-        # we want to make sure that `select()` can be called when no
-        # FD is registered.
-        max_ev = max(len(self._fd_to_key), 1)
-
-        ready = []
-        try:
-            fd_event_list = self._epoll.poll(timeout, max_ev)
-        except InterruptedError:
+if hasattr(select, 'epoll'):
+
+    class EpollSelector(_BaseSelectorImpl):
+        """Epoll-based selector."""
+
+        def __init__(self):
+            super().__init__()
+            self._epoll = select.epoll()
+
+        def fileno(self):
+            return self._epoll.fileno()
+
+        def register(self, fileobj, events, data=None):
+            key = super().register(fileobj, events, data)
+            epoll_events = 0
+            if events & EVENT_READ:
+                epoll_events |= select.EPOLLIN
+            if events & EVENT_WRITE:
+                epoll_events |= select.EPOLLOUT
+            try:
+                self._epoll.register(key.fd, epoll_events)
+            except BaseException:
+                super().unregister(fileobj)
+                raise
+            return key
+
+        def unregister(self, fileobj):
+            key = super().unregister(fileobj)
+            try:
+                self._epoll.unregister(key.fd)
+            except OSError:
+                # This can happen if the FD was closed since it
+                # was registered.
+                pass
+            return key
+
+        def select(self, timeout=None):
+            if timeout is None:
+                timeout = -1
+            elif timeout <= 0:
+                timeout = 0
+            else:
+                # epoll_wait() has a resolution of 1 millisecond, round away
+                # from zero to wait *at least* timeout seconds.
+                timeout = math.ceil(timeout * 1e3) * 1e-3
+
+            # epoll_wait() expects `maxevents` to be greater than zero;
+            # we want to make sure that `select()` can be called when no
+            # FD is registered.
+            max_ev = max(len(self._fd_to_key), 1)
+
+            ready = []
+            try:
+                fd_event_list = self._epoll.poll(timeout, max_ev)
+            except InterruptedError:
+                return ready
+            for fd, event in fd_event_list:
+                events = 0
+                if event & ~select.EPOLLIN:
+                    events |= EVENT_WRITE
+                if event & ~select.EPOLLOUT:
+                    events |= EVENT_READ
+
+                key = self._key_from_fd(fd)
+                if key:
+                    ready.append((key, events & key.events))
             return ready
-        for fd, event in fd_event_list:
-            events = 0
-            if event & ~selectraw.EPOLLIN:
-                events |= EVENT_WRITE
-            if event & ~selectraw.EPOLLOUT:
-                events |= EVENT_READ
-
-            key = self._key_from_fd(fd)
-            if key:
-                ready.append((key, events & key.events))
-        return ready
 
-    def close(self):
-        self._epoll.close()
-        super().close()
-
-DefaultSelector = EpollSelector
+        def close(self):
+            self._epoll.close()
+            super().close()
+
+
+if hasattr(select, 'devpoll'):
+
+    class DevpollSelector(_BaseSelectorImpl):
+        """Solaris /dev/poll selector."""
+
+        def __init__(self):
+            super().__init__()
+            self._devpoll = select.devpoll()
+
+        def fileno(self):
+            return self._devpoll.fileno()
+
+        def register(self, fileobj, events, data=None):
+            key = super().register(fileobj, events, data)
+            poll_events = 0
+            if events & EVENT_READ:
+                poll_events |= select.POLLIN
+            if events & EVENT_WRITE:
+                poll_events |= select.POLLOUT
+            self._devpoll.register(key.fd, poll_events)
+            return key
+
+        def unregister(self, fileobj):
+            key = super().unregister(fileobj)
+            self._devpoll.unregister(key.fd)
+            return key
+
+        def select(self, timeout=None):
+            if timeout is None:
+                timeout = None
+            elif timeout <= 0:
+                timeout = 0
+            else:
+                # devpoll() has a resolution of 1 millisecond, round away from
+                # zero to wait *at least* timeout seconds.
+                timeout = math.ceil(timeout * 1e3)
+            ready = []
+            try:
+                fd_event_list = self._devpoll.poll(timeout)
+            except InterruptedError:
+                return ready
+            for fd, event in fd_event_list:
+                events = 0
+                if event & ~select.POLLIN:
+                    events |= EVENT_WRITE
+                if event & ~select.POLLOUT:
+                    events |= EVENT_READ
+
+                key = self._key_from_fd(fd)
+                if key:
+                    ready.append((key, events & key.events))
+            return ready
 
-__all__ = [ 'BaseSelector'    ,
-            'DefaultSelector' ,
-            'EpollSelector'   ,
-            'PollSelector'    ,
-            'SelectSelector'  ,
-            'EventRead'       ,
-            'EventWrite'      ]
+        def close(self):
+            self._devpoll.close()
+            super().close()
+
+
+if hasattr(select, 'kqueue'):
+
+    class KqueueSelector(_BaseSelectorImpl):
+        """Kqueue-based selector."""
+
+        def __init__(self):
+            super().__init__()
+            self._kqueue = select.kqueue()
+
+        def fileno(self):
+            return self._kqueue.fileno()
+
+        def register(self, fileobj, events, data=None):
+            key = super().register(fileobj, events, data)
+            try:
+                if events & EVENT_READ:
+                    kev = select.kevent(key.fd, select.KQ_FILTER_READ,
+                                        select.KQ_EV_ADD)
+                    self._kqueue.control([kev], 0, 0)
+                if events & EVENT_WRITE:
+                    kev = select.kevent(key.fd, select.KQ_FILTER_WRITE,
+                                        select.KQ_EV_ADD)
+                    self._kqueue.control([kev], 0, 0)
+            except BaseException:
+                super().unregister(fileobj)
+                raise
+            return key
+
+        def unregister(self, fileobj):
+            key = super().unregister(fileobj)
+            if key.events & EVENT_READ:
+                kev = select.kevent(key.fd, select.KQ_FILTER_READ,
+                                    select.KQ_EV_DELETE)
+                try:
+                    self._kqueue.control([kev], 0, 0)
+                except OSError:
+                    # This can happen if the FD was closed since it
+                    # was registered.
+                    pass
+            if key.events & EVENT_WRITE:
+                kev = select.kevent(key.fd, select.KQ_FILTER_WRITE,
+                                    select.KQ_EV_DELETE)
+                try:
+                    self._kqueue.control([kev], 0, 0)
+                except OSError:
+                    # See comment above.
+                    pass
+            return key
+
+        def select(self, timeout=None):
+            timeout = None if timeout is None else max(timeout, 0)
+            max_ev = len(self._fd_to_key)
+            ready = []
+            try:
+                kev_list = self._kqueue.control(None, max_ev, timeout)
+            except InterruptedError:
+                return ready
+            for kev in kev_list:
+                fd = kev.ident
+                flag = kev.filter
+                events = 0
+                if flag == select.KQ_FILTER_READ:
+                    events |= EVENT_READ
+                if flag == select.KQ_FILTER_WRITE:
+                    events |= EVENT_WRITE
+
+                key = self._key_from_fd(fd)
+                if key:
+                    ready.append((key, events & key.events))
+            return ready
 
+        def close(self):
+            self._kqueue.close()
+            super().close()
+
+
+# Choose the best implementation, roughly:
+#    epoll|kqueue|devpoll > poll > select.
+# select() also can't accept a FD > FD_SETSIZE (usually around 1024)
+#if 'KqueueSelector' in globals():
+#    DefaultSelector = KqueueSelector
+if 'EpollSelector' in globals():
+    DefaultSelector = EpollSelector
+elif 'DevpollSelector' in globals():
+    DefaultSelector = DevpollSelector
+elif 'PollSelector' in globals():
+    DefaultSelector = PollSelector
+else:
+    DefaultSelector = SelectSelector
diff --git a/modules/language/python/module/socket.py b/modules/language/python/module/socket.py
new file mode 100644 (file)
index 0000000..31b814a
--- /dev/null
@@ -0,0 +1,754 @@
+module(socket)
+
+# Wrapper module for _socket, providing some additional facilities
+# implemented in Python.
+
+"""\
+This module provides socket operations and some related functions.
+On Unix, it supports IP (Internet Protocol) and Unix domain sockets.
+On other systems, it only supports IP. Functions specific for a
+socket are available as methods of the socket object.
+
+Functions:
+
+socket() -- create a new socket object
+socketpair() -- create a pair of new socket objects [*]
+fromfd() -- create a socket object from an open file descriptor [*]
+fromshare() -- create a socket object from data received from socket.share() [*]
+gethostname() -- return the current hostname
+gethostbyname() -- map a hostname to its IP number
+gethostbyaddr() -- map an IP number or hostname to DNS info
+getservbyname() -- map a service name and a protocol name to a port number
+getprotobyname() -- map a protocol name (e.g. 'tcp') to a number
+ntohs(), ntohl() -- convert 16, 32 bit int from network to host byte order
+htons(), htonl() -- convert 16, 32 bit int from host to network byte order
+inet_aton() -- convert IP addr string (123.45.67.89) to 32-bit packed format
+inet_ntoa() -- convert 32-bit packed format IP to string (123.45.67.89)
+socket.getdefaulttimeout() -- get the default timeout value
+socket.setdefaulttimeout() -- set the default timeout value
+create_connection() -- connects to an address, with an optional timeout and
+                       optional source address.
+
+ [*] not available on all platforms!
+
+Special objects:
+
+SocketType -- type object for socket objects
+error -- exception raised for I/O errors
+has_ipv6 -- boolean value indicating if IPv6 is supported
+
+IntEnum constants:
+
+AF_INET, AF_UNIX -- socket domains (first argument to socket() call)
+SOCK_STREAM, SOCK_DGRAM, SOCK_RAW -- socket types (second argument)
+
+Integer constants:
+
+Many other constants may be defined; these may be used in calls to
+the setsockopt() and getsockopt() methods.
+"""
+pk(0,1)
+import _socket
+from _socket import *
+pk(0,2)
+import os, sys, io, selectors
+from enum import IntEnum, IntFlag
+pk(0,3)
+try:
+    import errno
+except ImportError:
+    errno = None
+pk(0,4)
+EBADF = getattr(errno, 'EBADF', 9)
+EAGAIN = getattr(errno, 'EAGAIN', 11)
+EWOULDBLOCK = getattr(errno, 'EWOULDBLOCK', 11)
+pk(0,5)
+__all__ = ["fromfd", "getfqdn", "create_connection",
+        "AddressFamily", "SocketKind"]
+__all__.extend(os._get_exports_list(_socket))
+pk(0,6)
+# Set up the socket.AF_* socket.SOCK_* constants as members of IntEnums for
+# nicer string representations.
+# Note that _socket only knows about the integer values. The public interface
+# in this module understands the enums and translates them back from integers
+# where needed (e.g. .family property of a socket object).
+name__ = '_socket'
+pk(1)
+IntEnum._convert(
+        'AddressFamily',
+        name__,
+        lambda C: C.isupper() and C.startswith('AF_'))
+IntEnum._convert(
+        'SocketKind',
+        name__,
+        lambda C: C.isupper() and C.startswith('SOCK_'))
+
+IntFlag._convert(
+        'MsgFlag',
+        name__,
+        lambda C: C.isupper() and C.startswith('MSG_'))
+
+IntFlag._convert(
+        'AddressInfo',
+        name__,
+        lambda C: C.isupper() and C.startswith('AI_'))
+pk(2)
+_LOCALHOST    = '127.0.0.1'
+_LOCALHOST_V6 = '::1'
+
+
+def _intenum_converter(value, enum_klass):
+    """Convert a numeric family value to an IntEnum member.
+
+    If it's not a known member, return the numeric value itself.
+    """
+    try:
+        return enum_klass(value)
+    except ValueError:
+        return value
+
+_realsocket = socket
+
+# WSA error codes
+if sys.platform.lower().startswith("win"):
+    errorTab = {}
+    errorTab[10004] = "The operation was interrupted."
+    errorTab[10009] = "A bad file handle was passed."
+    errorTab[10013] = "Permission denied."
+    errorTab[10014] = "A fault occurred on the network??" # WSAEFAULT
+    errorTab[10022] = "An invalid operation was attempted."
+    errorTab[10035] = "The socket operation would block"
+    errorTab[10036] = "A blocking operation is already in progress."
+    errorTab[10048] = "The network address is in use."
+    errorTab[10054] = "The connection has been reset."
+    errorTab[10058] = "The network has been shut down."
+    errorTab[10060] = "The operation timed out."
+    errorTab[10061] = "Connection refused."
+    errorTab[10063] = "The name is too long."
+    errorTab[10064] = "The host is down."
+    errorTab[10065] = "The host is unreachable."
+    __all__.append("errorTab")
+
+
+class _GiveupOnSendfile(Exception): pass
+
+
+class socket(_socket.socket):
+
+    """A subclass of _socket.socket adding the makefile() method."""
+
+    __slots__ = ["__weakref__", "_io_refs", "_closed"]
+
+    def __init__(self, family=AF_INET, type=SOCK_STREAM, proto=0, fileno=None):
+        # For user code address family and type values are IntEnum members, but
+        # for the underlying _socket.socket they're just integers. The
+        # constructor of _socket.socket converts the given argument to an
+        # integer automatically.
+        _socket.socket.__init__(self, family, type, proto, fileno)
+        self._io_refs = 0
+        self._closed = False
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, *args):
+        if not self._closed:
+            self.close()
+
+    def __repr__(self):
+        """Wrap __repr__() to reveal the real class name and socket
+        address(es).
+        """
+        closed = getattr(self, '_closed', False)
+        s = "<%s.%s%s fd=%i, family=%s, type=%s, proto=%i" \
+            % (self.__class__.__module__,
+               self.__class__.__qualname__,
+               " [closed]" if closed else "",
+               self.fileno(),
+               self.family,
+               self.type,
+               self.proto)
+        if not closed:
+            try:
+                laddr = self.getsockname()
+                if laddr:
+                    s += ", laddr=%s" % str(laddr)
+            except error:
+                pass
+            try:
+                raddr = self.getpeername()
+                if raddr:
+                    s += ", raddr=%s" % str(raddr)
+            except error:
+                pass
+        s += '>'
+        return s
+
+    def __getstate__(self):
+        raise TypeError("Cannot serialize socket object")
+
+    def dup(self):
+        """dup() -> socket object
+
+        Duplicate the socket. Return a new socket object connected to the same
+        system resource. The new socket is non-inheritable.
+        """
+        fd = dup(self.fileno())
+        sock = self.__class__(self.family, self.type, self.proto, fileno=fd)
+        sock.settimeout(self.gettimeout())
+        return sock
+
+    def accept(self):
+        """accept() -> (socket object, address info)
+
+        Wait for an incoming connection.  Return a new socket
+        representing the connection, and the address of the client.
+        For IP sockets, the address info is a pair (hostaddr, port).
+        """
+        fd, addr = self._accept()
+        # If our type has the SOCK_NONBLOCK flag, we shouldn't pass it onto the
+        # new socket. We do not currently allow passing SOCK_NONBLOCK to
+        # accept4, so the returned socket is always blocking.
+        type = self.type & ~globals().get("SOCK_NONBLOCK", 0)
+        sock = socket(self.family, type, self.proto, fileno=fd)
+        # Issue #7995: if no default timeout is set and the listening
+        # socket had a (non-zero) timeout, force the new socket in blocking
+        # mode to override platform-specific socket flags inheritance.
+        if getdefaulttimeout() is None and self.gettimeout():
+            sock.setblocking(True)
+        return sock, addr
+
+    def makefile(self, mode="r", buffering=None, *,
+                 encoding=None, errors=None, newline=None):
+        """makefile(...) -> an I/O stream connected to the socket
+
+        The arguments are as for io.open() after the filename, except the only
+        supported mode values are 'r' (default), 'w' and 'b'.
+        """
+        # XXX refactor to share code?
+        if not set(mode) <= {"r", "w", "b"}:
+            raise ValueError("invalid mode %r (only r, w, b allowed)" % (mode,))
+        writing = "w" in mode
+        reading = "r" in mode or not writing
+        assert reading or writing
+        binary = "b" in mode
+        rawmode = ""
+        if reading:
+            rawmode += "r"
+        if writing:
+            rawmode += "w"
+        raw = SocketIO(self, rawmode)
+        self._io_refs += 1
+        if buffering is None:
+            buffering = -1
+        if buffering < 0:
+            buffering = io.DEFAULT_BUFFER_SIZE
+        if buffering == 0:
+            if not binary:
+                raise ValueError("unbuffered streams must be binary")
+            return raw
+        if reading and writing:
+            buffer = io.BufferedRWPair(raw, raw, buffering)
+        elif reading:
+            buffer = io.BufferedReader(raw, buffering)
+        else:
+            assert writing
+            buffer = io.BufferedWriter(raw, buffering)
+        if binary:
+            return buffer
+        text = io.TextIOWrapper(buffer, encoding, errors, newline)
+        text.mode = mode
+        return text
+
+    if hasattr(os, 'sendfile'):
+
+        def _sendfile_use_sendfile(self, file, offset=0, count=None):
+            self._check_sendfile_params(file, offset, count)
+            sockno = self.fileno()
+            try:
+                fileno = file.fileno()
+            except (AttributeError, io.UnsupportedOperation) as err:
+                raise _GiveupOnSendfile(err)  # not a regular file
+            try:
+                fsize = os.fstat(fileno).st_size
+            except OSError as err:
+                raise _GiveupOnSendfile(err)  # not a regular file
+            if not fsize:
+                return 0  # empty file
+            blocksize = fsize if not count else count
+
+            timeout = self.gettimeout()
+            if timeout == 0:
+                raise ValueError("non-blocking sockets are not supported")
+            # poll/select have the advantage of not requiring any
+            # extra file descriptor, contrarily to epoll/kqueue
+            # (also, they require a single syscall).
+            if hasattr(selectors, 'PollSelector'):
+                selector = selectors.PollSelector()
+            else:
+                selector = selectors.SelectSelector()
+            selector.register(sockno, selectors.EVENT_WRITE)
+
+            total_sent = 0
+            # localize variable access to minimize overhead
+            selector_select = selector.select
+            os_sendfile = os.sendfile
+            try:
+                while True:
+                    if timeout and not selector_select(timeout):
+                        raise _socket.timeout('timed out')
+                    if count:
+                        blocksize = count - total_sent
+                        if blocksize <= 0:
+                            break
+                    try:
+                        sent = os_sendfile(sockno, fileno, offset, blocksize)
+                    except BlockingIOError:
+                        if not timeout:
+                            # Block until the socket is ready to send some
+                            # data; avoids hogging CPU resources.
+                            selector_select()
+                        continue
+                    except OSError as err:
+                        if total_sent == 0:
+                            # We can get here for different reasons, the main
+                            # one being 'file' is not a regular mmap(2)-like
+                            # file, in which case we'll fall back on using
+                            # plain send().
+                            raise _GiveupOnSendfile(err)
+                        raise err from None
+                    else:
+                        if sent == 0:
+                            break  # EOF
+                        offset += sent
+                        total_sent += sent
+                return total_sent
+            finally:
+                if total_sent > 0 and hasattr(file, 'seek'):
+                    file.seek(offset)
+    else:
+        def _sendfile_use_sendfile(self, file, offset=0, count=None):
+            raise _GiveupOnSendfile(
+                "os.sendfile() not available on this platform")
+
+    def _sendfile_use_send(self, file, offset=0, count=None):
+        self._check_sendfile_params(file, offset, count)
+        if self.gettimeout() == 0:
+            raise ValueError("non-blocking sockets are not supported")
+        if offset:
+            file.seek(offset)
+        blocksize = min(count, 8192) if count else 8192
+        total_sent = 0
+        # localize variable access to minimize overhead
+        file_read = file.read
+        sock_send = self.send
+        try:
+            while True:
+                if count:
+                    blocksize = min(count - total_sent, blocksize)
+                    if blocksize <= 0:
+                        break
+                data = memoryview(file_read(blocksize))
+                if not data:
+                    break  # EOF
+                while True:
+                    try:
+                        sent = sock_send(data)
+                    except BlockingIOError:
+                        continue
+                    else:
+                        total_sent += sent
+                        if sent < len(data):
+                            data = data[sent:]
+                        else:
+                            break
+            return total_sent
+        finally:
+            if total_sent > 0 and hasattr(file, 'seek'):
+                file.seek(offset + total_sent)
+
+    def _check_sendfile_params(self, file, offset, count):
+        if 'b' not in getattr(file, 'mode', 'b'):
+            raise ValueError("file should be opened in binary mode")
+        if not self.type & SOCK_STREAM:
+            raise ValueError("only SOCK_STREAM type sockets are supported")
+        if count is not None:
+            if not isinstance(count, int):
+                raise TypeError(
+                    "count must be a positive integer (got {!r})".format(count))
+            if count <= 0:
+                raise ValueError(
+                    "count must be a positive integer (got {!r})".format(count))
+
+    def sendfile(self, file, offset=0, count=None):
+        """sendfile(file[, offset[, count]]) -> sent
+
+        Send a file until EOF is reached by using high-performance
+        os.sendfile() and return the total number of bytes which
+        were sent.
+        *file* must be a regular file object opened in binary mode.
+        If os.sendfile() is not available (e.g. Windows) or file is
+        not a regular file socket.send() will be used instead.
+        *offset* tells from where to start reading the file.
+        If specified, *count* is the total number of bytes to transmit
+        as opposed to sending the file until EOF is reached.
+        File position is updated on return or also in case of error in
+        which case file.tell() can be used to figure out the number of
+        bytes which were sent.
+        The socket must be of SOCK_STREAM type.
+        Non-blocking sockets are not supported.
+        """
+        try:
+            return self._sendfile_use_sendfile(file, offset, count)
+        except _GiveupOnSendfile:
+            return self._sendfile_use_send(file, offset, count)
+
+    def _decref_socketios(self):
+        if self._io_refs > 0:
+            self._io_refs -= 1
+        if self._closed:
+            self.close()
+
+    def _real_close(self, _ss=_socket.socket):
+        # This function should not reference any globals. See issue #808164.
+        _ss.close(self)
+
+    def close(self):
+        # This function should not reference any globals. See issue #808164.
+        self._closed = True
+        if self._io_refs <= 0:
+            self._real_close()
+
+    def detach(self):
+        """detach() -> file descriptor
+
+        Close the socket object without closing the underlying file descriptor.
+        The object cannot be used after this call, but the file descriptor
+        can be reused for other purposes.  The file descriptor is returned.
+        """
+        self._closed = True
+        return super().detach()
+
+    @property
+    def family(self):
+        """Read-only access to the address family for this socket.
+        """
+        return _intenum_converter(super().family, AddressFamily)
+
+    @property
+    def type(self):
+        """Read-only access to the socket type.
+        """
+        return _intenum_converter(super().type, SocketKind)
+
+    if os.name == 'nt':
+        def get_inheritable(self):
+            return os.get_handle_inheritable(self.fileno())
+        def set_inheritable(self, inheritable):
+            os.set_handle_inheritable(self.fileno(), inheritable)
+    else:
+        def get_inheritable(self):
+            return os.get_inheritable(self.fileno())
+        def set_inheritable(self, inheritable):
+            os.set_inheritable(self.fileno(), inheritable)
+    get_inheritable.__doc__ = "Get the inheritable flag of the socket"
+    set_inheritable.__doc__ = "Set the inheritable flag of the socket"
+
+def fromfd(fd, family, type, proto=0):
+    """ fromfd(fd, family, type[, proto]) -> socket object
+
+    Create a socket object from a duplicate of the given file
+    descriptor.  The remaining arguments are the same as for socket().
+    """
+    nfd = dup(fd)
+    return socket(family, type, proto, nfd)
+pk(3)
+if hasattr(_socket.socket, "share"):
+    def fromshare(info):
+        """ fromshare(info) -> socket object
+
+        Create a socket object from the bytes object returned by
+        socket.share(pid).
+        """
+        return socket(0, 0, 0, info)
+    __all__.append("fromshare")
+pk(4)
+if hasattr(_socket, "socketpair"):
+
+    def socketpair(family=None, type=SOCK_STREAM, proto=0):
+        """socketpair([family[, type[, proto]]]) -> (socket object, socket object)
+
+        Create a pair of socket objects from the sockets returned by the platform
+        socketpair() function.
+        The arguments are the same as for socket() except the default family is
+        AF_UNIX if defined on the platform; otherwise, the default is AF_INET.
+        """
+        if family is None:
+            try:
+                family = AF_UNIX
+            except NameError:
+                family = AF_INET
+        a, b = _socket.socketpair(family, type, proto)
+        a = socket(family, type, proto, a.detach())
+        b = socket(family, type, proto, b.detach())
+        return a, b
+
+else:
+
+    # Origin: https://gist.github.com/4325783, by Geert Jansen.  Public domain.
+    def socketpair(family=AF_INET, type=SOCK_STREAM, proto=0):
+        if family == AF_INET:
+            host = _LOCALHOST
+        elif family == AF_INET6:
+            host = _LOCALHOST_V6
+        else:
+            raise ValueError("Only AF_INET and AF_INET6 socket address families "
+                             "are supported")
+        if type != SOCK_STREAM:
+            raise ValueError("Only SOCK_STREAM socket type is supported")
+        if proto != 0:
+            raise ValueError("Only protocol zero is supported")
+
+        # We create a connected TCP socket. Note the trick with
+        # setblocking(False) that prevents us from having to create a thread.
+        lsock = socket(family, type, proto)
+        try:
+            lsock.bind((host, 0))
+            lsock.listen()
+            # On IPv6, ignore flow_info and scope_id
+            addr, port = lsock.getsockname()[:2]
+            csock = socket(family, type, proto)
+            try:
+                csock.setblocking(False)
+                try:
+                    csock.connect((addr, port))
+                except (BlockingIOError, InterruptedError):
+                    pass
+                csock.setblocking(True)
+                ssock, _ = lsock.accept()
+            except:
+                csock.close()
+                raise
+        finally:
+            lsock.close()
+        return (ssock, csock)
+    __all__.append("socketpair")
+pk(5)
+socketpair.__doc__ = """socketpair([family[, type[, proto]]]) -> (socket object, socket object)
+Create a pair of socket objects from the sockets returned by the platform
+socketpair() function.
+The arguments are the same as for socket() except the default family is AF_UNIX
+if defined on the platform; otherwise, the default is AF_INET.
+"""
+
+_blocking_errnos = { EAGAIN, EWOULDBLOCK }
+
+class SocketIO(io.RawIOBase):
+
+    """Raw I/O implementation for stream sockets.
+
+    This class supports the makefile() method on sockets.  It provides
+    the raw I/O interface on top of a socket object.
+    """
+
+    # One might wonder why not let FileIO do the job instead.  There are two
+    # main reasons why FileIO is not adapted:
+    # - it wouldn't work under Windows (where you can't used read() and
+    #   write() on a socket handle)
+    # - it wouldn't work with socket timeouts (FileIO would ignore the
+    #   timeout and consider the socket non-blocking)
+
+    # XXX More docs
+
+    def __init__(self, sock, mode):
+        if mode not in ("r", "w", "rw", "rb", "wb", "rwb"):
+            raise ValueError("invalid mode: %r" % mode)
+        io.RawIOBase.__init__(self)
+        self._sock = sock
+        if "b" not in mode:
+            mode += "b"
+        self._mode = mode
+        self._reading = "r" in mode
+        self._writing = "w" in mode
+        self._timeout_occurred = False
+
+    def readinto(self, b):
+        """Read up to len(b) bytes into the writable buffer *b* and return
+        the number of bytes read.  If the socket is non-blocking and no bytes
+        are available, None is returned.
+
+        If *b* is non-empty, a 0 return value indicates that the connection
+        was shutdown at the other end.
+        """
+        self._checkClosed()
+        self._checkReadable()
+        if self._timeout_occurred:
+            raise OSError("cannot read from timed out object")
+        while True:
+            try:
+                return self._sock.recv_into(b)
+            except timeout:
+                self._timeout_occurred = True
+                raise
+            except error as e:
+                if e.args[0] in _blocking_errnos:
+                    return None
+                raise
+
+    def write(self, b):
+        """Write the given bytes or bytearray object *b* to the socket
+        and return the number of bytes written.  This can be less than
+        len(b) if not all data could be written.  If the socket is
+        non-blocking and no bytes could be written None is returned.
+        """
+        self._checkClosed()
+        self._checkWritable()
+        try:
+            return self._sock.send(b)
+        except error as e:
+            # XXX what about EINTR?
+            if e.args[0] in _blocking_errnos:
+                return None
+            raise
+
+    def readable(self):
+        """True if the SocketIO is open for reading.
+        """
+        if self.closed:
+            raise ValueError("I/O operation on closed socket.")
+        return self._reading
+
+    def writable(self):
+        """True if the SocketIO is open for writing.
+        """
+        if self.closed:
+            raise ValueError("I/O operation on closed socket.")
+        return self._writing
+
+    def seekable(self):
+        """True if the SocketIO is open for seeking.
+        """
+        if self.closed:
+            raise ValueError("I/O operation on closed socket.")
+        return super().seekable()
+
+    def fileno(self):
+        """Return the file descriptor of the underlying socket.
+        """
+        self._checkClosed()
+        return self._sock.fileno()
+
+    @property
+    def name(self):
+        if not self.closed:
+            return self.fileno()
+        else:
+            return -1
+
+    @property
+    def mode(self):
+        return self._mode
+
+    def close(self):
+        """Close the SocketIO object.  This doesn't close the underlying
+        socket, except if all references to it have disappeared.
+        """
+        if self.closed:
+            return
+        io.RawIOBase.close(self)
+        self._sock._decref_socketios()
+        self._sock = None
+
+
+def getfqdn(name=''):
+    """Get fully qualified domain name from name.
+
+    An empty argument is interpreted as meaning the local host.
+
+    First the hostname returned by gethostbyaddr() is checked, then
+    possibly existing aliases. In case no FQDN is available, hostname
+    from gethostname() is returned.
+    """
+    name = name.strip()
+    if not name or name == '0.0.0.0':
+        name = gethostname()
+    try:
+        hostname, aliases, ipaddrs = gethostbyaddr(name)
+    except error:
+        pass
+    else:
+        aliases.insert(0, hostname)
+        for name in aliases:
+            if '.' in name:
+                break
+        else:
+            name = hostname
+    return name
+
+
+_GLOBAL_DEFAULT_TIMEOUT = object()
+
+def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT,
+                      source_address=None):
+    """Connect to *address* and return the socket object.
+
+    Convenience function.  Connect to *address* (a 2-tuple ``(host,
+    port)``) and return the socket object.  Passing the optional
+    *timeout* parameter will set the timeout on the socket instance
+    before attempting to connect.  If no *timeout* is supplied, the
+    global default timeout setting returned by :func:`getdefaulttimeout`
+    is used.  If *source_address* is set it must be a tuple of (host, port)
+    for the socket to bind as a source address before making the connection.
+    A host of '' or port 0 tells the OS to use the default.
+    """
+
+    host, port = address
+    err = None
+    for res in getaddrinfo(host, port, 0, SOCK_STREAM):
+        af, socktype, proto, canonname, sa = res
+        sock = None
+        try:
+            sock = socket(af, socktype, proto)
+            if timeout is not _GLOBAL_DEFAULT_TIMEOUT:
+                sock.settimeout(timeout)
+            if source_address:
+                sock.bind(source_address)
+            sock.connect(sa)
+            # Break explicitly a reference cycle
+            err = None
+            return sock
+
+        except error as _:
+            err = _
+            if sock is not None:
+                sock.close()
+
+    if err is not None:
+        raise err
+    else:
+        raise error("getaddrinfo returns an empty list")
+
+def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0):
+    """Resolve host and port into list of address info entries.
+
+    Translate the host/port argument into a sequence of 5-tuples that contain
+    all the necessary arguments for creating a socket connected to that service.
+    host is a domain name, a string representation of an IPv4/v6 address or
+    None. port is a string service name such as 'http', a numeric port number or
+    None. By passing None as the value of host and port, you can pass NULL to
+    the underlying C API.
+
+    The family, type and proto arguments can be optionally specified in order to
+    narrow the list of addresses returned. Passing zero as a value for each of
+    these arguments selects the full range of results.
+    """
+    # We override this function since we want to translate the numeric family
+    # and socket type values to enum constants.
+    addrlist = []
+    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
+        af, socktype, proto, canonname, sa = res
+        addrlist.append((_intenum_converter(af, AddressFamily),
+                         _intenum_converter(socktype, SocketKind),
+                         proto, canonname, sa))
+    return addrlist
+pk(6)
index 9723f437c55fcd908504a8d96e70e38fb96b7747..16ff0a6dfde2a92149dcd64ed809390c6b816151 100644 (file)
                   (break)))
             #:final
             (pylist-append! perm "-")))
-  (pk perm)
   (py-join "" perm))
 
index fe0ccc8dc85d963ff3885f4350cc2d6638c3b7f0..c431052557a604e4d02d82a46173047956fc7f0f 100644 (file)
 (define (get-align s align width sign)
   (define widthq (- width (len sign)))
   (define (f s a l)
-    (pk 'res (match (pk 'm a)
+    (match a
       ("<" (apply py-ljust  (+ sign s) width l))
       (">" (apply py-rjust  (+ sign s) width l))
       ("^" (apply py-center (+ sign s) width l))
-      ("=" (+ sign (apply py-rjust s widthq l))))))
+      ("=" (+ sign (apply py-rjust s widthq l)))))
      
   (match align
     (#f
                (values s     " "))))))
 
 (define (convert-float s format-str)
-  (match (pk 'conv-float
-             (with-fluids ((*whitespace* f-true))
-               (stis-parse format-str (f-seq formatSpec f-eof))))
+  (match (with-fluids ((*whitespace* f-true))
+           (stis-parse format-str (f-seq formatSpec f-eof)))
     ((align sign sharp zero width comma prec type)
      (call-with-values (lambda () (gen-sign s sign))                         
        (lambda (s s-sign)
          (let* ((prec (if prec prec 6))
                 (s    (let lp ((type type))
-                        (pk (match type
+                        (match type
                           (#f (lp "g"))
                           
                           ("f"
 
                           ("%"
                            (set s (* s 100))
-                           (+ (lp "f") "%")))))))
+                           (+ (lp "f") "%"))))))
                 
            (if width
                (if zero
                (+ s-sign s))))))))
 
 (define (convert-complex s format-str)
-  (match (pk 'conv-complex
-             (with-fluids ((*whitespace* f-true))
-               (stis-parse format-str (f-seq formatSpec f-eof))))
+  (match (with-fluids ((*whitespace* f-true))
+           (stis-parse format-str (f-seq formatSpec f-eof)))
     ((align sign sharp zero width comma prec type)
      (let* ((prec (if prec prec 6))
             (s    (let lp ((type type))
                         
          
 (define (convert-integer s format-str)
-  (match (pk 'conv-int
-             (with-fluids ((*whitespace* f-true))
-               (stis-parse format-str (f-seq formatSpec f-eof))))
+  (match (with-fluids ((*whitespace* f-true))
+           (stis-parse format-str (f-seq formatSpec f-eof)))
     ((align sign sharp zero width comma prec type)
      (call-with-values (lambda () (gen-sign s sign))                         
        (lambda (s s-sign)
   (make-generator (l)
     (lambda (yield l)
       (let lp ((u l) (i 0))
-        (match (pk 'lp u)
+        (match u
           (()
            (yield "" None None None))
           (((#:str str))
            (if (eq? a None)
                (begin
                  (yield s (number->string i) c b)
-                 (pk 'next)
                  (lp u (+ i 1)))
                (begin
                  (yield s a c b)
 
   (define vformat
     (lambda (self format_string args kwargs)
-      (pk 'vformat format_string args kwargs)
       (set self '_args '())
       (for ((s fn fo co : ((ref self 'parse) format_string))) ((ss '("")))
-           (pk 'parse s ss fn fo co)
            (if (eq? fn None)
                (cons s ss)
                (let* ((fn2 ((ref self 'get_field    ) fn args kwargs))
   
   (define get_field
     (lambda (self field_name args kwargs)
-      (pk 'get_field field_name args kwargs)
-      (match (pk 'field (with-fluids ((*whitespace* f-true))
-                          (stis-parse field_name fieldName)))
+      (match (with-fluids ((*whitespace* f-true))
+               (stis-parse field_name fieldName))
         ((key a ...)
          (set self '_args (cons key (ref self '_args)))
          (let ((f ((ref self 'get_value) key args kwargs)))
 
   (define get_value
     (lambda (self key args kwargs)
-      (pk 'get_value key args kwargs)
       (set self '__args (cons key args))
       (if (integer? key)
           (pylist-ref args   key)
   
   (define check_unused_args
     (lambda (self used_args args kwargs)
-      (pk 'check_unused_args used_args args kwargs)
       (let ((n (len args)))
         (let lp ((i 0))
           (if (< i n)
   
   (define convert_field
     (lambda (self value conversion)
-      (pk 'convert_field value conversion)
       (cond
        ((equal? conversion "s")
         (str value))
index 4b11202313b5ec8236d934b213b98d681b2d020f..5eea7994a229094a64810600bc4e6ac3e3314bd6 100644 (file)
@@ -1081,7 +1081,7 @@ explicitly tell it to not update etc.
          
          #'(let ()
              (define name 
-               (letruc ((dname (make-up dval)) ...)
+               (letruc2 ((dname (make-up dval)) ...)
                       body
                       (let ((ret
                             (make-p-class 'name doc
@@ -1302,7 +1302,31 @@ explicitly tell it to not update etc.
                                                  (reverse r)) #,x))
                           u)))))
              #`(letrec #,(reverse u) code ...)))))))
-                        
+
+(define-syntax letruc2
+  (lambda (x)
+    (syntax-case x ()
+      ((_ ((x v) ...) code ...)
+       (let lp ((a #'(x ...)) (b #'(v ...)) (u '()))
+         (if (pair? a)
+             (let* ((x (car a))
+                    (s (syntax->datum x)))
+               (let lp2 ((a2 (cdr a)) (b2 (cdr b)) (a3 '()) (b3 '())
+                         (r (list (car b))))
+                 (if (pair? a2)
+                     (if (eq? (syntax->datum a2) s)
+                         (lp2 (cdr a2) (cdr b2) a3 b3 (cons (car b2) r))
+                         (lp2 (cdr a2) (cdr b2)
+                              (cons (car a2) a3)
+                              (cons (car b2) b3)
+                              r))
+                     (lp (reverse a3) (reverse b3)
+                         (cons
+                          (list x #`(let* #,(map (lambda (v) (list x v))
+                                                 (reverse r)) #,x))
+                          u)))))
+             #`(let #,(reverse u) code ...)))))))
+
 
              
 (define-method (py-init . l)