diff options
author | Stefan Israelsson Tampe <stefan.itampe@gmail.com> | 2018-08-24 22:23:23 +0200 |
---|---|---|
committer | Stefan Israelsson Tampe <stefan.itampe@gmail.com> | 2018-08-24 22:23:23 +0200 |
commit | 582d1c6f0be332ad4cb9f421bea5c2be56a12408 (patch) | |
tree | 3c0f8e487d1c57b509ae19ee4d858a90728ea7b3 | |
parent | 333a82328a53024f341a74a0f738ce0d6f0f6d4f (diff) |
socket.py
-rw-r--r-- | modules/language/python/compile.scm | 91 | ||||
-rw-r--r-- | modules/language/python/dir.scm | 2 | ||||
-rw-r--r-- | modules/language/python/eval.scm | 13 | ||||
-rw-r--r-- | modules/language/python/for.scm | 19 | ||||
-rw-r--r-- | modules/language/python/module.scm | 29 | ||||
-rw-r--r-- | modules/language/python/module/_socket.scm | 710 | ||||
-rw-r--r-- | modules/language/python/module/os.scm | 8 | ||||
-rw-r--r-- | modules/language/python/module/python.scm | 2 | ||||
-rw-r--r-- | modules/language/python/module/selectors.py | 400 | ||||
-rw-r--r-- | modules/language/python/module/socket.py | 754 | ||||
-rw-r--r-- | modules/language/python/module/stat.scm | 1 | ||||
-rw-r--r-- | modules/language/python/module/string.scm | 36 | ||||
-rw-r--r-- | modules/oop/pf-objects.scm | 28 |
13 files changed, 1886 insertions, 207 deletions
diff --git a/modules/language/python/compile.scm b/modules/language/python/compile.scm index aec886b..983eb66 100644 --- a/modules/language/python/compile.scm +++ b/modules/language/python/compile.scm @@ -76,9 +76,11 @@ 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 ...)))))) @@ -105,6 +107,12 @@ (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 @@ -1012,6 +1020,7 @@ (fluid-set! decorations '()) r)) (class (exp vs class)) + (vo vs) (vs (union (list class) vs)) (ns (scope code '())) (ls ns #;(diff ns vs)) @@ -1029,7 +1038,7 @@ ,(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)) @@ -1039,45 +1048,53 @@ (#: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))) @@ -1103,7 +1120,8 @@ ((#: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)))) @@ -2027,6 +2045,8 @@ #`(let/ec ret l) code)))))) +(define void (list 'void)) + (define-syntax var (lambda (x) (syntax-case x (cons quote) @@ -2039,7 +2059,7 @@ (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)) @@ -2570,4 +2590,3 @@ ((_ '() v) (values)) ((_ x v) (define! 'x v)))) - diff --git a/modules/language/python/dir.scm b/modules/language/python/dir.scm index 75c42d7..0791666 100644 --- a/modules/language/python/dir.scm +++ b/modules/language/python/dir.scm @@ -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))) diff --git a/modules/language/python/eval.scm b/modules/language/python/eval.scm index 53b4bce..a54ea64 100644 --- a/modules/language/python/eval.scm +++ b/modules/language/python/eval.scm @@ -12,11 +12,22 @@ (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 diff --git a/modules/language/python/for.scm b/modules/language/python/for.scm index 76c9fa8..5b7b4a6 100644 --- a/modules/language/python/for.scm +++ b/modules/language/python/for.scm @@ -145,14 +145,11 @@ 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>)) @@ -177,13 +174,3 @@ (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)) diff --git a/modules/language/python/module.scm b/modules/language/python/module.scm index 51270c2..8e705a8 100644 --- a/modules/language/python/module.scm +++ b/modules/language/python/module.scm @@ -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))) @@ -238,10 +239,34 @@ (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 index 0000000..5d7730b --- /dev/null +++ b/modules/language/python/module/_socket.scm @@ -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))) + + + + + + + + + + + + + + + + + + diff --git a/modules/language/python/module/os.scm b/modules/language/python/module/os.scm index 16ee6e6..d593b58 100644 --- a/modules/language/python/module/os.scm +++ b/modules/language/python/module/os.scm @@ -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) @@ -2352,3 +2353,10 @@ (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))) diff --git a/modules/language/python/module/python.scm b/modules/language/python/module/python.scm index 1c15d40..f105f22 100644 --- a/modules/language/python/module/python.scm +++ b/modules/language/python/module/python.scm @@ -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)) diff --git a/modules/language/python/module/selectors.py b/modules/language/python/module/selectors.py index 41d70ba..6afb52e 100644 --- a/modules/language/python/module/selectors.py +++ b/modules/language/python/module/selectors.py @@ -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 index 0000000..31b814a --- /dev/null +++ b/modules/language/python/module/socket.py @@ -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) diff --git a/modules/language/python/module/stat.scm b/modules/language/python/module/stat.scm index 9723f43..16ff0a6 100644 --- a/modules/language/python/module/stat.scm +++ b/modules/language/python/module/stat.scm @@ -117,6 +117,5 @@ (break))) #:final (pylist-append! perm "-"))) - (pk perm) (py-join "" perm)) diff --git a/modules/language/python/module/string.scm b/modules/language/python/module/string.scm index fe0ccc8..c431052 100644 --- a/modules/language/python/module/string.scm +++ b/modules/language/python/module/string.scm @@ -40,11 +40,11 @@ (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 @@ -82,15 +82,14 @@ (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" @@ -134,7 +133,7 @@ ("%" (set s (* s 100)) - (+ (lp "f") "%"))))))) + (+ (lp "f") "%")))))) (if width (if zero @@ -146,9 +145,8 @@ (+ 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)) @@ -176,9 +174,8 @@ (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) @@ -254,7 +251,7 @@ (make-generator (l) (lambda (yield l) (let lp ((u l) (i 0)) - (match (pk 'lp u) + (match u (() (yield "" None None None)) (((#:str str)) @@ -275,7 +272,6 @@ (if (eq? a None) (begin (yield s (number->string i) c b) - (pk 'next) (lp u (+ i 1))) (begin (yield s a c b) @@ -295,10 +291,8 @@ (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)) @@ -324,9 +318,8 @@ (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))) @@ -343,7 +336,6 @@ (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) @@ -351,7 +343,6 @@ (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) @@ -369,7 +360,6 @@ (define convert_field (lambda (self value conversion) - (pk 'convert_field value conversion) (cond ((equal? conversion "s") (str value)) diff --git a/modules/oop/pf-objects.scm b/modules/oop/pf-objects.scm index 4b11202..5eea799 100644 --- a/modules/oop/pf-objects.scm +++ b/modules/oop/pf-objects.scm @@ -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) |