subprocess fixes

parent d280ed12
......@@ -45,6 +45,8 @@
(define-inlinable (H x) `(@ (language python hash) ,x))
(define-inlinable (W x) `(@ (language python with) ,x))
(define in-dec (make-fluid #f))
(define (mk/ec x) x)
(define-syntax-rule (let/ecx c a ...)
......@@ -1040,7 +1042,8 @@ empty list."
(#:decorated
((_ (l ...))
(fluid-set! decorations (map (g vs exp) l))
(with-fluids ((in-dec #t))
(fluid-set! decorations (map (g vs exp) l)))
`(,cvalues)))
(#:string
......@@ -1218,7 +1221,7 @@ empty list."
(#:classdef
((_ class parents code)
(with-fluids ((is-class? #t))
(with-fluids ((is-class? (exp vs class)))
(let ()
(define (clean l)
(match l
......@@ -1248,7 +1251,7 @@ empty list."
`(set! ,class
(,(C 'class-decor) ,decor
(,(C 'with-class) ,class
(,(C 'mk-p-class2)
(,(C 'mk-py-class2)
,class
,(if parents
(arglist->pkw (clean parents))
......@@ -1720,7 +1723,7 @@ empty list."
(#:raise
((_ #f . #f)
`(,(T 'raise) (,(O 'Exception))))
`(,(T 'raise-stx)))
((_ code . #f)
`(,(T 'raise) ,(exp vs code)))
......
......@@ -36,11 +36,13 @@
(define __repr__
(lambda (self)
(aif it (rawref self 'value #f)
(format #f "~a:~a"
(rawref self '__name__) it)
(format #f "~a"
(rawref self '__name__))))))
(aif it (ref self '__str__)
(it)
(aif it (rawref self 'value #f)
(format #f "~a:~a"
(rawref self '__name__) it)
(format #f "~a"
(rawref self '__name__)))))))
(define-python-class SystemExit ()
(define __init__
......
......@@ -213,7 +213,12 @@
(lambda (self)
(check (self port)
port)))
(define fileno
(lambda (self)
(check (self port)
(port->fdes port))))
(define close
(lambda (self)
(catch #t
......
......@@ -22,7 +22,7 @@
(define ceil
(lambda (x)
((@ (guile) inexac->exact)
((@ (guile) inexact->exact)
((@ (guile) ceiling)
x))))
......
......@@ -1916,7 +1916,7 @@
(define CLD_CONTINUED 6)
(define (waitpid pid options)
(ca ((@ (guile) waitpid) pid options)))
(ca (let ((x ((@ (guile) waitpid) pid options))) (values (car x) (cdr x)))))
(define wait3 #f)
(defineu wait3 ()
......@@ -1959,7 +1959,7 @@
(define (WIFSIGNALED status) (> (ash (+ (logand status #x7f) 1) -1) 0))
(define (WIFEXITED status) (= (WTERMSIG status) 0))
(define (WEXITSTATUS status) (ash (logand status #xff00) 8))
(define (WEXITSTATUS status) (ash (logand status #xff00) -8))
(define (WSTOPSIG status) (WEXITSTATUS status))
(define (WTERMSIG status) (logand status #x7f))
......
......@@ -5,6 +5,7 @@
#:use-module (language python list)
#:use-module (language python try)
#:use-module (language python def)
#:use-module (language python bool)
#:use-module (oop pf-objects)
#:use-module (system foreign)
#:use-module (rnrs bytevectors)
......@@ -193,26 +194,27 @@
(dynamic-func "poll" (dynamic-link))
(list '* int int))))
(lambda (fds n timespec)
(rm (f fds n (inexact->exact (floor (* 1000 timespec))))))))
(rm (f fds n (inexact->exact (floor timespec)))))))
(define-python-class poll ()
(define __init__
(lambda (self)
(set self '__data '())))
(set self '_cache #f)
(set self '_data '())))
(define register
(lambda* (self fd #:optional (eventmask 0))
(set self '__cache #f)
(let ((data (ref self '__data)))
(set self '_cache #f)
(let ((data (ref self '_data)))
(if (assoc fd data)
(raise (error "poll registering of already registered fd"))
(set self '__data (cons (cons fd eventmask) data))))))
(set self '_data (cons (cons fd eventmask) data))))))
(define modify
(lambda (self fd eventmask)
(set self '__cache #f)
(let ((data (ref self '__data)))
(set self '_cache #f)
(let ((data (ref self '_data)))
(aif it (assoc fd data)
(set-cdr! it eventmask)
(begin
......@@ -221,9 +223,9 @@
(define unregister
(lambda (self fd)
(set self '__cache #f)
(set self '__data
(let lp ((l (ref self '__data)))
(set self '_cache #f)
(set self '_data
(let lp ((l (ref self '_data)))
(if (pair? l)
(let ((x (car l)))
(if (= (car x) fd)
......@@ -233,7 +235,8 @@
(define poll
(let ((k 8))
(lambda* (self #:optional (timeout -1))
(object-method
(lambda* (self #:optional (timeout -1))
(define (make-data-pt data n)
(let ((v (make-bytevector (* n k))))
(let lp ((i 0) (l data))
......@@ -247,19 +250,18 @@
(native-endianness))
(lp (+ i 1) (cdr l)))
(bytevector->pointer v)))))
(call-with-values
(lambda ()
(aif it (ref self '__cache)
(let ((n (ref self '__n)))
(aif it (ref self '_cache)
(let ((n (ref self '_n)))
(pollf it n timeout)
(values it n))
(let* ((data (ref self '__data))
(let* ((data (ref self '_data))
(n (length data))
(x (make-data-pt data n)))
(set self '__cache x)
(set self '__n n)
(pollf x n timeout)
(set self '_cache x)
(set self '_n n)
(pollf x n (if (bool timeout) timeout -1))
(values x n))))
(lambda (x n)
......@@ -273,7 +275,7 @@
(if (not (= y 0))
(cons (list fd y) (lp (+ i 1)))
(lp (+ i 1))))
'())))))))))
'()))))))))))
(define* (select rl wl xl #:optional (timeout 0))
......
......@@ -210,6 +210,7 @@ class _BaseSelectorImpl(BaseSelector):
"""
try:
return _fileobj_to_fd(fileobj)
except ValueError:
# Do an exhaustive search.
for key in self._fd_to_key.values():
......@@ -221,13 +222,10 @@ class _BaseSelectorImpl(BaseSelector):
def register(self, fileobj, events, data=None):
if (not events) or (events & ~(EVENT_READ | EVENT_WRITE)):
raise ValueError("Invalid events: {!r}".format(events))
key = SelectorKey(fileobj, self._fileobj_lookup(fileobj), events, data)
if key.fd in self._fd_to_key:
raise KeyError("{!r} (FD {}) is already registered"
.format(fileobj, key.fd))
self._fd_to_key[key.fd] = key
return key
......@@ -327,14 +325,13 @@ class SelectSelector(_BaseSelectorImpl):
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
......@@ -359,11 +356,13 @@ if hasattr(select, 'poll'):
# 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:
......@@ -374,6 +373,7 @@ if hasattr(select, 'poll'):
key = self._key_from_fd(fd)
if key:
ready.append((key, events & key.events))
return ready
......
(define-module (language python module signal)
#:use-module (language python module enum)
#:export ())
#:export (SIGTERM SIGKILL))
(define SIGTERM 15)
(define SIGKILL 9)
......@@ -362,7 +362,7 @@ def run(*popenargs, input=None, timeout=None, check=False, **kwargs):
process.wait()
raise
retcode = process.poll()
if check and retcode:
if check and retcode:
raise CalledProcessError(retcode, process.args,
output=stdout, stderr=stderr)
......@@ -762,13 +762,12 @@ class Popen(object):
endtime = _time() + timeout
else:
endtime = None
try:
stdout, stderr = self._communicate(input, endtime, timeout)
finally:
self._communication_started = True
sts = self.wait(timeout=self._remaining_time(endtime))
return (stdout, stderr)
......@@ -934,7 +933,6 @@ class Popen(object):
devnull_fd = getattr(self, '_devnull', None)
if p2cread != -1 and p2cwrite != -1 and p2cread != devnull_fd:
pk(1.5)
os.close(p2cread)
......@@ -1126,7 +1124,6 @@ class Popen(object):
# http://bugs.python.org/issue14396.
if pid == self.pid:
self._handle_exitstatus(sts)
return self.returncode
......@@ -1143,10 +1140,10 @@ class Popen(object):
self.stdin.close()
except BrokenPipeError:
pass # communicate() must ignore BrokenPipeError.
pk(20)
stdout = None
stderr = None
# Only create this mapping if we haven't already.
if not self._communication_started:
self._fileobj2output = {}
......@@ -1154,19 +1151,18 @@ class Popen(object):
self._fileobj2output[self.stdout] = []
if self.stderr:
self._fileobj2output[self.stderr] = []
pk(21)
if self.stdout:
stdout = self._fileobj2output[self.stdout]
if self.stderr:
stderr = self._fileobj2output[self.stderr]
pk(22)
self._save_input(input)
pk(23)
if self._input:
input_view = memoryview(self._input)
pk(24)
with _PopenSelector() as selector:
pk(25)
if self.stdin and input:
selector.register(self.stdin, selectors.EVENT_WRITE)
if self.stdout:
......@@ -1178,7 +1174,6 @@ class Popen(object):
timeout = self._remaining_time(endtime)
if timeout is not None and timeout < 0:
raise TimeoutExpired(self.args, orig_timeout)
ready = selector.select(timeout)
self._check_timeout(endtime, orig_timeout)
......@@ -1206,7 +1201,7 @@ class Popen(object):
self._fileobj2output[key.fileobj].append(data)
self.wait(timeout=self._remaining_time(endtime))
# All data exchanged. Translate lists into strings.
if stdout is not None:
stdout = b''.join(stdout)
......
......@@ -3,13 +3,16 @@
#:use-module (language python yield)
#:use-module (oop pf-objects)
#:use-module (oop goops)
#:use-module ((oop dict) #:select (slask-it))
#:use-module (ice-9 control)
#:use-module (ice-9 match)
#:replace (raise)
#:export (try))
#:export (try raise-stx))
(define-syntax-rule (aif it p x y) (let ((it p)) (if it x y)))
(define-syntax-parameter the-exception (lambda (x) #f))
(define-inlinable (standard-check class obj l)
(cond
((eq? class #t)
......@@ -48,18 +51,24 @@
((_ E tag l)
(check E tag l))))
(define-syntax-rule (mm f)
(lambda x
(syntax-parameterize ((the-exception (lambda (u) #'x)))
(apply f x))))
(define (m code)
(let ((c code))
(lambda (k . l)
(if (eq? k StopIteration)
(apply c 'python k l)
(apply c k l)))))
(apply c 'python k l)
(apply c k l)))))
(define-syntax handler
(lambda (x)
(syntax-case x ()
((_ . l) #'(handler_ . l)))))
(define-syntax handler_
(syntax-rules (=>)
((handler ecx)
......@@ -91,8 +100,9 @@
((a ...)
(compile-error "not a proper python macro try block"))))
(define inc (let ((i 0)) (lambda () (set! i (+ i 1)) i)))
(define-syntax try
(syntax-rules ()
((try code exc ... #:finally fin)
......@@ -109,7 +119,7 @@
((try code exc ...)
(catch #t
code
(handler (exc ...))))))
(mm (handler (exc ...)))))))
(define raise
......@@ -119,4 +129,14 @@
(throw 'python (apply x l))
(apply throw 'python x l)))
(() (raise Exception))))
(()
(raise Exception "annynoomous"))))
(define-syntax raise-stx
(syntax-rules ()
((_ x . l)
(raise x . l))
((_)
(if the-exception
(apply throw (slask-it the-exception))
(raise Exception "annonymous")))))
......@@ -43,27 +43,31 @@
(let ((vexit (lambda l (apply exit l)))
(venter (lambda () (enter exp)))
(id 'id))
(try
(lambda ()
(set! id (venter))
. code)
(#:except #t =>
(lambda (tag l)
(set! type (if (pyclass? tag)
tag
(aif it (ref tag '__class__)
it
tag)))
(set! value
(aif it (ref tag 'value)
it
(if (pair? l)
(car l)
None)))))
#:finally
(lambda ()
(vexit id type value trace))))))
((_ (exp) . code)
(with0 (id exp) . code))))
(catch #t
(lambda ()
(try
(lambda ()
(set! id (venter))
. code)
(#:except #t =>
(lambda (tag l)
(set! type (if (pyclass? tag)
tag
(aif it (ref tag '__class__)
it
tag)))
(set! value
(aif it (ref tag 'value)
it
(if (pair? l)
(car l)
None)))
(raise tag l)))
#:finally
(lambda ()
(vexit id type value trace))))
(lambda x (apply throw x))))))
((_ (exp) . code)
(with0 (id exp) . code))))
......@@ -5,11 +5,13 @@
hash-for-each* object-method class-method
static-method Module splitm splitmm
formatter m? bytes b? b-decode hset!
hashforeach mkw to-list int slask-it))
hashforeach mkw to-list int slask-it leveler))
(define-syntax-rule (aif it p x y) (let ((it p)) (if it x y)))
(define (leveler x) (x))
(define prophash (make-hash-table))
(define (procedure-property- o key . l)
......
......@@ -16,6 +16,7 @@
call with copy fset fcall put put! py-get
pcall pcall! get fset-x pyclass?
def-p-class mk-p-class make-p-class mk-p-class2
mk-py-class mk-py-class2
define-python-class define-python-class-noname
get-type py-class find-in-class
py-super-mac py-super py-equal?
......@@ -1175,6 +1176,115 @@ explicitly tell it to not update etc.
(name-object name)
name))))))
(define-syntax mk-py-class
(lambda (x)
(syntax-case x ()
((_ name parents (ddef dname dval) ...)
#'(mk-p-class name parents "" (ddef dname dval) ...))
((_ name parents doc (ddef dname dval) ...)
(with-syntax (((ddname ...)
(map (lambda (dn)
(datum->syntax
#'name
(string->symbol
(string-append
(symbol->string
(syntax->datum #'name))
"-"
(symbol->string
(syntax->datum dn))))))
#'(dname ...)))
(nname (datum->syntax
#'name
(string->symbol
(string-append
(symbol->string
(syntax->datum #'name))
"-goops-class")))))
(%add-to-warn-list (syntax->datum #'nname))
(map (lambda (x) (%add-to-warn-list (syntax->datum x)))
#'(ddname ...))
#'(let ()
(define name
(let ((dname (make-up dval)) ...)
(let ((ret
(make-p-class 'name doc
parents
(lambda (dict)
(pylist-set! dict 'dname dname)
...
(values)))))
(begin
(module-define! (current-module) 'ddname dname)
(name-object ddname))
...
ret)))
(module-define! (current-module) 'nname (rawref name '__goops__))
(name-object nname)
(name-object name)
name))))))
(define (replace-stx ass code)
(define m (make-hash-table))
(define (p x)
(pretty-print (syntax->datum x)) x)
(define (tr0 x)
(let lp ((x x))
(syntax-case x ()
(((@ a ref) x y)
#`((@ a ref)
#,(aif it (hash-ref m (syntax->datum #'x))
it
#'x)
y))
(x
(aif it (hash-ref m (syntax->datum #'x))
it
#'x)))))
(define (tr x)
(syntax-case x ()
((a . b)
(cons (tr0 #'a) (tr #'b)))
(x #'x)))
(define (sec x)
(syntax-case x ()
((let ((a ((@ b def) x y)) . l) . u)
(equal? (syntax->datum #'def) 'def-decor)
#`(let ((a ((@ b def) #,(tr #'x) y)) . l) . u))
(x #'x)))
(for-each
(lambda (x)
(hash-set! m (syntax->datum (car x)) (cdr x)))
ass)
(let lp ((code code))
(syntax-case code (set! @)
((set! x y)
(aif it (hash-ref m (syntax->datum #'x))
#`(set! #,it #,(sec #'y))
(error "wrong set! in classdef" (syntax->datum #'x))))
(((@ (guile) set!) x y)
(aif it (hash-ref m (syntax->datum #'x))
#`((@ (guile) set!) #,it #,(sec #'y))
(error "wrong set! in classdef" (syntax->datum #'x))))
(((@@ u qset) x . y)
(equal? (syntax->datum #'qset) 'qset!)
(aif it (hash-ref m (syntax->datum #'x))
#`((@@ u qset) #,it . y)
(error "wrong set! in classdef" (syntax->datum #'x))))
((x . y)
(cons (lp #'x) (lp #'y)))
(x #'x))))
(define-syntax mk-p-class2
(lambda (x)
(syntax-case x ()
......@@ -1227,6 +1337,64 @@ explicitly tell it to not update etc.
(name-object name)
name))))))
(define-syntax mk-py-class2
(lambda (x)
(syntax-case x ()
((_ name parents ((ddef dname dval) ...) body)
#'(mk-p-class2 name parents "" ((ddef dname dval) ...) body))
((_ name parents doc ((ddef dname dval) ...) body)
(with-syntax (((ddname ...)
(map (lambda (dn)
(datum->syntax
#'name
(string->symbol
(string-append
(symbol->string
(syntax->datum #'name))
"-"
(symbol->string
(syntax->datum dn))))))
#'(dname ...)))
(nname (datum->syntax
#'name
(string->symbol
(string-append
(symbol->string
(syntax->datum #'name))
"-goops-class")))))
(%add-to-warn-list (syntax->datum #'nname))
(map (lambda (x) (%add-to-warn-list (syntax->datum x)))
#'(ddname ...))
(let* ((dname2 (generate-temporaries #'(dname ...)))
(body2 (replace-stx (map cons #'(dname ...) dname2) #'body)))
(with-syntax (((dname2 ...) dname2)
(body2 body2))
#'(let ()
(define name
(let ((pa parents))
(let ((dname2 (make-up dval)) ...)
body2
(let ((ret
(make-p-class 'name doc
pa
(lambda (dict)
(pylist-set! dict 'dname dname2)
...
dict))))
(begin
(module-define! (current-module) 'ddname dname2)
(name-object ddname))
...
ret))))
(module-define!
(current-module) 'nname (rawref name '__goops__))
(name-object nname)
(name-object name)
name))))))))
(define-syntax mk-p-class-noname
(lambda (x)
(syntax-case x ()
......@@ -1461,9 +1629,7 @@ explicitly tell it to not update etc.
(list x #`(let* #,(map (lambda (v) (list x v))
(reverse r)) #,x))
u)))))
#`(let #,(reverse u) code ...)))))))