Author: Maciej Fijalkowski <[email protected]>
Branch:
Changeset: r67222:8fd575d74e94
Date: 2013-10-08 17:12 +0200
http://bitbucket.org/pypy/pypy/changeset/8fd575d74e94/
Log: (fijal, arigo) merge fileops2, which brings some sanity (and more
featureS) to file implementation in RPython
diff --git a/rpython/flowspace/model.py b/rpython/flowspace/model.py
--- a/rpython/flowspace/model.py
+++ b/rpython/flowspace/model.py
@@ -252,6 +252,23 @@
from rpython.translator.tool.graphpage import try_show
try_show(self)
+ def get_graph(self):
+ import gc
+ pending = [self] # pending blocks
+ seen = {self: True, None: True}
+ for x in pending:
+ for y in gc.get_referrers(x):
+ if isinstance(y, FunctionGraph):
+ return y
+ elif isinstance(y, Link):
+ block = y.prevblock
+ if block not in seen:
+ pending.append(block)
+ seen[block] = True
+ elif isinstance(y, dict):
+ pending.append(y) # go back from the dict to the real obj
+ return pending
+
view = show
diff --git a/rpython/flowspace/specialcase.py b/rpython/flowspace/specialcase.py
--- a/rpython/flowspace/specialcase.py
+++ b/rpython/flowspace/specialcase.py
@@ -1,3 +1,4 @@
+import os
from rpython.flowspace.model import Constant, const
SPECIAL_CASES = {}
@@ -37,6 +38,18 @@
return space.frame.do_operation('simple_call', const(isinstance),
w_instance, w_type)
+@register_flow_sc(open)
+def sc_open(space, *args_w):
+ from rpython.rlib.rfile import create_file
+
+ return space.frame.do_operation("simple_call", const(create_file), *args_w)
+
+@register_flow_sc(os.tmpfile)
+def sc_os_tmpfile(space):
+ from rpython.rlib.rfile import create_temp_rfile
+
+ return space.frame.do_operation("simple_call", const(create_temp_rfile))
+
# _________________________________________________________________________
# a simplified version of the basic printing routines, for RPython programs
class StdOutBuffer:
diff --git a/rpython/rlib/rfile.py b/rpython/rlib/rfile.py
--- a/rpython/rlib/rfile.py
+++ b/rpython/rlib/rfile.py
@@ -1,55 +1,241 @@
-""" This file makes open() and friends RPython
+""" This file makes open() and friends RPython. Note that RFile should not
+be used directly and instead it's magically appearing each time you call
+python builtin open()
"""
import os
-from rpython.annotator.model import SomeObject, SomeString, SomeInteger
-from rpython.rtyper.extregistry import ExtRegistryEntry
-from rpython.rtyper.extfunc import register_external
+from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rtyper.tool import rffi_platform as platform
+from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from rpython.rlib.rarithmetic import r_uint, intmask
+from rpython.rlib import rposix
+from rpython.rlib.rstring import StringBuilder
-class SomeFile(SomeObject):
- def method_write(self, s_arg):
- assert isinstance(s_arg, SomeString)
+eci = ExternalCompilationInfo(includes=['stdio.h', 'unistd.h', 'sys/types.h'])
- def method_read(self, s_arg=None):
- if s_arg is not None:
- assert isinstance(s_arg, SomeInteger)
- return SomeString(can_be_None=False)
+def llexternal(*args):
+ return rffi.llexternal(*args, compilation_info=eci)
- def method_close(self):
- pass
+FILE = lltype.Struct('FILE') # opaque type maybe
- def method_seek(self, s_arg, s_whence=None):
- assert isinstance(s_arg, SomeInteger)
- if s_whence is not None:
- assert isinstance(s_whence, SomeInteger)
+class CConfig(object):
+ _compilation_info_ = eci
- def rtyper_makekey(self):
- return self.__class__,
+ off_t = platform.SimpleType('off_t')
- def rtyper_makerepr(self, rtyper):
- from rpython.rtyper.lltypesystem.rfile import FileRepr
+CC = platform.configure(CConfig)
+OFF_T = CC['off_t']
- return FileRepr(rtyper)
+c_open = llexternal('fopen', [rffi.CCHARP, rffi.CCHARP], lltype.Ptr(FILE))
+c_close = llexternal('fclose', [lltype.Ptr(FILE)], rffi.INT)
+c_write = llexternal('fwrite', [rffi.CCHARP, rffi.SIZE_T, rffi.SIZE_T,
+ lltype.Ptr(FILE)], rffi.SIZE_T)
+c_read = llexternal('fread', [rffi.CCHARP, rffi.SIZE_T, rffi.SIZE_T,
+ lltype.Ptr(FILE)], rffi.SIZE_T)
+c_feof = llexternal('feof', [lltype.Ptr(FILE)], rffi.INT)
+c_ferror = llexternal('ferror', [lltype.Ptr(FILE)], rffi.INT)
+c_clearerror = llexternal('clearerr', [lltype.Ptr(FILE)], lltype.Void)
+c_fseek = llexternal('fseek', [lltype.Ptr(FILE), rffi.LONG, rffi.INT],
+ rffi.INT)
+c_tmpfile = llexternal('tmpfile', [], lltype.Ptr(FILE))
+c_fileno = llexternal('fileno', [lltype.Ptr(FILE)], rffi.INT)
+c_ftell = llexternal('ftell', [lltype.Ptr(FILE)], lltype.Signed)
+c_fflush = llexternal('fflush', [lltype.Ptr(FILE)], rffi.INT)
+c_ftruncate = llexternal('ftruncate', [rffi.INT, OFF_T], rffi.INT)
+c_fgets = llexternal('fgets', [rffi.CCHARP, rffi.INT, lltype.Ptr(FILE)],
+ rffi.CCHARP)
-class FileEntry(ExtRegistryEntry):
- _about_ = open
+BASE_BUF_SIZE = 4096
+BASE_LINE_SIZE = 100
- def compute_result_annotation(self, s_name, s_mode=None):
- assert isinstance(s_name, SomeString)
- if s_mode is not None:
- assert isinstance(s_mode, SomeString)
- return SomeFile()
+def create_file(filename, mode="r", buffering=-1):
+ assert buffering == -1
+ assert filename is not None
+ assert mode is not None
+ ll_name = rffi.str2charp(filename)
+ try:
+ ll_mode = rffi.str2charp(mode)
+ try:
+ ll_f = c_open(ll_name, ll_mode)
+ if not ll_f:
+ errno = rposix.get_errno()
+ raise OSError(errno, os.strerror(errno))
+ finally:
+ lltype.free(ll_mode, flavor='raw')
+ finally:
+ lltype.free(ll_name, flavor='raw')
+ return RFile(ll_f)
- def specialize_call(self, hop):
- return hop.r_result.rtype_constructor(hop)
+def create_temp_rfile():
+ res = c_tmpfile()
+ if not res:
+ errno = rposix.get_errno()
+ raise OSError(errno, os.strerror(errno))
+ return RFile(res)
-class OSTempfileEntry(ExtRegistryEntry):
- _about_ = os.tmpfile
+class RFile(object):
+ def __init__(self, ll_file):
+ self.ll_file = ll_file
- def compute_result_annotation(self):
- return SomeFile()
+ def write(self, value):
+ assert value is not None
+ ll_file = self.ll_file
+ if not ll_file:
+ raise ValueError("I/O operation on closed file")
+ assert value is not None
+ ll_value = rffi.get_nonmovingbuffer(value)
+ try:
+ # note that since we got a nonmoving buffer, it is either raw
+ # or already cannot move, so the arithmetics below are fine
+ total_bytes = 0
+ ll_current = ll_value
+ while total_bytes < len(value):
+ bytes = c_write(ll_current, 1, len(value) -
r_uint(total_bytes),
+ ll_file)
+ if bytes == 0:
+ errno = rposix.get_errno()
+ raise OSError(errno, os.strerror(errno))
+ total_bytes += bytes
+ ll_current = rffi.cast(rffi.CCHARP,
+ rffi.cast(lltype.Unsigned, ll_value) +
+ total_bytes)
+ finally:
+ rffi.free_nonmovingbuffer(value, ll_value)
- def specialize_call(self, hop):
- return hop.r_result.rtype_tempfile(hop)
+ def close(self):
+ if self.ll_file:
+ # double close is allowed
+ res = c_close(self.ll_file)
+ self.ll_file = lltype.nullptr(FILE)
+ if res == -1:
+ errno = rposix.get_errno()
+ raise OSError(errno, os.strerror(errno))
+ def read(self, size=-1):
+ # XXX CPython uses a more delicate logic here
+ ll_file = self.ll_file
+ if not ll_file:
+ raise ValueError("I/O operation on closed file")
+ if size < 0:
+ # read the entire contents
+ buf = lltype.malloc(rffi.CCHARP.TO, BASE_BUF_SIZE, flavor='raw')
+ try:
+ s = StringBuilder()
+ while True:
+ returned_size = c_read(buf, 1, BASE_BUF_SIZE, ll_file)
+ if returned_size == 0:
+ if c_feof(ll_file):
+ # ok, finished
+ return s.build()
+ errno = c_ferror(ll_file)
+ c_clearerror(ll_file)
+ raise OSError(errno, os.strerror(errno))
+ s.append_charpsize(buf, returned_size)
+ finally:
+ lltype.free(buf, flavor='raw')
+ else:
+ raw_buf, gc_buf = rffi.alloc_buffer(size)
+ try:
+ returned_size = c_read(raw_buf, 1, size, ll_file)
+ if returned_size == 0:
+ if not c_feof(ll_file):
+ errno = c_ferror(ll_file)
+ raise OSError(errno, os.strerror(errno))
+ s = rffi.str_from_buffer(raw_buf, gc_buf, size,
+ rffi.cast(lltype.Signed,
returned_size))
+ finally:
+ rffi.keep_buffer_alive_until_here(raw_buf, gc_buf)
+ return s
+
+ def seek(self, pos, whence=0):
+ ll_file = self.ll_file
+ if not ll_file:
+ raise ValueError("I/O operation on closed file")
+ res = c_fseek(ll_file, pos, whence)
+ if res == -1:
+ errno = rposix.get_errno()
+ raise OSError(errno, os.strerror(errno))
+
+ def fileno(self):
+ if self.ll_file:
+ return intmask(c_fileno(self.ll_file))
+ raise ValueError("I/O operation on closed file")
+
+ def tell(self):
+ if self.ll_file:
+ res = intmask(c_ftell(self.ll_file))
+ if res == -1:
+ errno = rposix.get_errno()
+ raise OSError(errno, os.strerror(errno))
+ return res
+ raise ValueError("I/O operation on closed file")
+
+ def flush(self):
+ if self.ll_file:
+ res = c_fflush(self.ll_file)
+ if res != 0:
+ errno = rposix.get_errno()
+ raise OSError(errno, os.strerror(errno))
+ return
+ raise ValueError("I/O operation on closed file")
+
+ def truncate(self, arg=-1):
+ if self.ll_file:
+ if arg == -1:
+ arg = self.tell()
+ res = c_ftruncate(self.fileno(), arg)
+ if res == -1:
+ errno = rposix.get_errno()
+ raise OSError(errno, os.strerror(errno))
+ return
+ raise ValueError("I/O operation on closed file")
+
+ def __del__(self):
+ self.close()
+
+ def _readline1(self, raw_buf):
+ result = c_fgets(raw_buf, BASE_LINE_SIZE, self.ll_file)
+ if not result:
+ if c_feof(self.ll_file): # ok
+ return 0
+ errno = c_ferror(self.ll_file)
+ raise OSError(errno, os.strerror(errno))
+ #
+ # Assume that fgets() works as documented, and additionally
+ # never writes beyond the final \0, which the CPython
+ # fileobject.c says appears to be the case everywhere.
+ # The only case where the buffer was not big enough is the
+ # case where the buffer is full, ends with \0, and doesn't
+ # end with \n\0.
+ strlen = 0
+ while raw_buf[strlen] != '\0':
+ strlen += 1
+ if (strlen == BASE_LINE_SIZE - 1 and
+ raw_buf[BASE_LINE_SIZE - 2] != '\n'):
+ return -1 # overflow!
+ # common case
+ return strlen
+
+ def readline(self):
+ if self.ll_file:
+ raw_buf, gc_buf = rffi.alloc_buffer(BASE_LINE_SIZE)
+ try:
+ c = self._readline1(raw_buf)
+ if c >= 0:
+ return rffi.str_from_buffer(raw_buf, gc_buf,
+ BASE_LINE_SIZE, c)
+ #
+ # this is the rare case: the line is longer than BASE_LINE_SIZE
+ s = StringBuilder()
+ while True:
+ s.append_charpsize(raw_buf, BASE_LINE_SIZE - 1)
+ c = self._readline1(raw_buf)
+ if c >= 0:
+ break
+ #
+ s.append_charpsize(raw_buf, c)
+ return s.build()
+ finally:
+ rffi.keep_buffer_alive_until_here(raw_buf, gc_buf)
+ raise ValueError("I/O operation on closed file")
diff --git a/rpython/rlib/test/test_rfile.py b/rpython/rlib/test/test_rfile.py
--- a/rpython/rlib/test/test_rfile.py
+++ b/rpython/rlib/test/test_rfile.py
@@ -78,3 +78,100 @@
f()
self.interpret(f, [])
+
+ def test_fileno(self):
+ fname = str(self.tmpdir.join('file_5'))
+
+ def f():
+ f = open(fname, "w")
+ try:
+ return f.fileno()
+ finally:
+ f.close()
+
+ res = self.interpret(f, [])
+ assert res > 2
+
+ def test_tell(self):
+ fname = str(self.tmpdir.join('file_tell'))
+
+ def f():
+ f = open(fname, "w")
+ f.write("xyz")
+ try:
+ return f.tell()
+ finally:
+ f.close()
+
+ res = self.interpret(f, [])
+ assert res == 3
+
+ def test_flush(self):
+ fname = str(self.tmpdir.join('file_flush'))
+
+ def f():
+ f = open(fname, "w")
+ f.write("xyz")
+ f.flush()
+ f2 = open(fname)
+ assert f2.read() == "xyz"
+ f2.close()
+ f.close()
+
+ self.interpret(f, [])
+
+ def test_truncate(self):
+ fname = str(self.tmpdir.join('file_trunc'))
+
+ def f():
+ f = open(fname, "w")
+ f.write("xyz")
+ f.seek(0)
+ f.truncate(2)
+ f.close()
+ f2 = open(fname)
+ assert f2.read() == "xy"
+ f2.close()
+
+ f()
+ self.interpret(f, [])
+
+
+class TestDirect:
+ def setup_class(cls):
+ cls.tmpdir = udir.join('test_rfile_direct')
+ cls.tmpdir.ensure(dir=True)
+
+ def test_readline(self):
+ fname = str(self.tmpdir.join('file_readline'))
+ j = 0
+ expected = []
+ with open(fname, 'w') as f:
+ for i in range(250):
+ s = ''.join([chr(32+(k&63)) for k in range(j, j + i)])
+ j += 1
+ print >> f, s
+ expected = open(fname).readlines()
+ expected += ['', '']
+ assert len(expected) == 252
+
+ f = rfile.create_file(fname, 'r')
+ for j in range(252):
+ got = f.readline()
+ assert got == expected[j]
+ f.close()
+
+ def test_readline_without_eol_at_the_end(self):
+ fname = str(self.tmpdir.join('file_readline_without_eol_at_the_end'))
+ for n in [1, 10, 97, 98, 99, 100, 101, 102, 103, 150,
+ 196, 197, 198, 199, 200, 201, 202, 203, 204, 250]:
+ s = ''.join([chr(32+(k&63)) for k in range(n)])
+ with open(fname, 'wb') as f:
+ f.write(s)
+
+ f = rfile.create_file(fname, 'r')
+ got = f.readline()
+ assert got == s
+ got = f.readline()
+ assert got == ''
+ f.close()
diff --git a/rpython/rlib/types.py b/rpython/rlib/types.py
--- a/rpython/rlib/types.py
+++ b/rpython/rlib/types.py
@@ -39,8 +39,12 @@
return model.SomeUnicodeString(no_nul=True)
-def str():
- return model.SomeString()
+def str(can_be_None=False):
+ return model.SomeString(can_be_None=can_be_None)
+
+
+def bytearray():
+ return model.SomeByteArray()
def str0():
diff --git a/rpython/rtyper/lltypesystem/rfile.py
b/rpython/rtyper/lltypesystem/rfile.py
deleted file mode 100644
--- a/rpython/rtyper/lltypesystem/rfile.py
+++ /dev/null
@@ -1,195 +0,0 @@
-
-import os
-from rpython.rlib import rposix
-from rpython.rlib.rarithmetic import r_uint
-from rpython.annotator import model as annmodel
-from rpython.rtyper.rtyper import Repr
-from rpython.rlib.rstring import StringBuilder
-from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
-from rpython.rtyper.lltypesystem.rstr import string_repr, STR
-from rpython.translator.tool.cbuild import ExternalCompilationInfo
-from rpython.rtyper.annlowlevel import hlstr
-from rpython.rtyper.lltypesystem.lloperation import llop
-
-FILE = lltype.Struct('FILE') # opaque type maybe
-FILE_WRAPPER = lltype.GcStruct("FileWrapper", ('file', lltype.Ptr(FILE)))
-
-eci = ExternalCompilationInfo(includes=['stdio.h'])
-
-def llexternal(*args):
- return rffi.llexternal(*args, compilation_info=eci)
-
-c_open = llexternal('fopen', [rffi.CCHARP, rffi.CCHARP], lltype.Ptr(FILE))
-c_close = llexternal('fclose', [lltype.Ptr(FILE)], rffi.INT)
-c_write = llexternal('fwrite', [rffi.CCHARP, rffi.SIZE_T, rffi.SIZE_T,
- lltype.Ptr(FILE)], rffi.SIZE_T)
-c_read = llexternal('fread', [rffi.CCHARP, rffi.SIZE_T, rffi.SIZE_T,
- lltype.Ptr(FILE)], rffi.SIZE_T)
-c_feof = llexternal('feof', [lltype.Ptr(FILE)], rffi.INT)
-c_ferror = llexternal('ferror', [lltype.Ptr(FILE)], rffi.INT)
-c_clearerror = llexternal('clearerr', [lltype.Ptr(FILE)], lltype.Void)
-c_fseek = llexternal('fseek', [lltype.Ptr(FILE), rffi.LONG, rffi.INT],
- rffi.INT)
-c_tmpfile = llexternal('tmpfile', [], lltype.Ptr(FILE))
-
-def ll_open(name, mode):
- file_wrapper = lltype.malloc(FILE_WRAPPER)
- ll_name = rffi.str2charp(name)
- ll_mode = rffi.str2charp(mode)
- try:
- ll_f = c_open(ll_name, ll_mode)
- if not ll_f:
- errno = rposix.get_errno()
- raise OSError(errno, os.strerror(errno))
- file_wrapper.file = ll_f
- finally:
- lltype.free(ll_name, flavor='raw')
- lltype.free(ll_mode, flavor='raw')
- return file_wrapper
-
-def ll_tmpfile():
- file_wrapper = lltype.malloc(FILE_WRAPPER)
- res = c_tmpfile()
- if not res:
- errno = rposix.get_errno()
- raise OSError(errno, os.strerror(errno))
- file_wrapper.file = res
- return file_wrapper
-
-def ll_write(file_wrapper, value):
- ll_file = file_wrapper.file
- if not ll_file:
- raise ValueError("I/O operation on closed file")
- value = hlstr(value)
- assert value is not None
- ll_value = rffi.get_nonmovingbuffer(value)
- try:
- # note that since we got a nonmoving buffer, it is either raw
- # or already cannot move, so the arithmetics below are fine
- total_bytes = 0
- ll_current = ll_value
- while total_bytes < len(value):
- bytes = c_write(ll_current, 1, len(value) - r_uint(total_bytes),
- ll_file)
- if bytes == 0:
- errno = rposix.get_errno()
- raise OSError(errno, os.strerror(errno))
- total_bytes += bytes
- ll_current = rffi.cast(rffi.CCHARP,
- rffi.cast(lltype.Unsigned, ll_value) +
- total_bytes)
- finally:
- rffi.free_nonmovingbuffer(value, ll_value)
-
-BASE_BUF_SIZE = 4096
-
-def ll_read(file_wrapper, size):
- ll_file = file_wrapper.file
- if not ll_file:
- raise ValueError("I/O operation on closed file")
- if size < 0:
- # read the entire contents
- buf = lltype.malloc(rffi.CCHARP.TO, BASE_BUF_SIZE, flavor='raw')
- try:
- s = StringBuilder()
- while True:
- returned_size = c_read(buf, 1, BASE_BUF_SIZE, ll_file)
- if returned_size == 0:
- if c_feof(ll_file):
- # ok, finished
- return s.build()
- errno = c_ferror(ll_file)
- c_clearerror(ll_file)
- raise OSError(errno, os.strerror(errno))
- s.append_charpsize(buf, returned_size)
- finally:
- lltype.free(buf, flavor='raw')
- else:
- raw_buf, gc_buf = rffi.alloc_buffer(size)
- try:
- returned_size = c_read(raw_buf, 1, size, ll_file)
- if returned_size == 0:
- if not c_feof(ll_file):
- errno = c_ferror(ll_file)
- raise OSError(errno, os.strerror(errno))
- s = rffi.str_from_buffer(raw_buf, gc_buf, size,
- rffi.cast(lltype.Signed, returned_size))
- finally:
- rffi.keep_buffer_alive_until_here(raw_buf, gc_buf)
- return s
-def ll_seek(file_wrapper, pos, whence):
- ll_file = file_wrapper.file
- if not ll_file:
- raise ValueError("I/O operation on closed file")
- res = c_fseek(ll_file, pos, whence)
- if res == -1:
- errno = rposix.get_errno()
- raise OSError(errno, os.strerror(errno))
-
-def ll_close(file_wrapper):
- if file_wrapper.file:
- # double close is allowed
- res = c_close(file_wrapper.file)
- file_wrapper.file = lltype.nullptr(FILE)
- if res == -1:
- errno = rposix.get_errno()
- raise OSError(errno, os.strerror(errno))
-
-class FileRepr(Repr):
- lowleveltype = lltype.Ptr(FILE_WRAPPER)
-
- def __init__(self, typer):
- Repr.__init__(self)
-
- def rtype_constructor(self, hop):
- repr = hop.rtyper.getrepr(annmodel.SomeString())
- arg_0 = hop.inputarg(repr, 0)
- if len(hop.args_v) == 1:
- arg_1 = hop.inputconst(string_repr, "r")
- else:
- arg_1 = hop.inputarg(repr, 1)
- hop.exception_is_here()
- open = hop.rtyper.getannmixlevel().delayedfunction(
- ll_open, [annmodel.SomeString()] * 2,
- annmodel.SomePtr(self.lowleveltype))
- v_open = hop.inputconst(lltype.typeOf(open), open)
- return hop.genop('direct_call', [v_open, arg_0, arg_1],
- resulttype=self)
-
- def rtype_tempfile(self, hop):
- tmpfile = hop.rtyper.getannmixlevel().delayedfunction(
- ll_tmpfile, [], annmodel.SomePtr(self.lowleveltype))
- v_tmpfile = hop.inputconst(lltype.typeOf(tmpfile), tmpfile)
- hop.exception_is_here()
- return hop.genop('direct_call', [v_tmpfile], resulttype=self)
-
-
- def rtype_method_write(self, hop):
- args_v = hop.inputargs(self, string_repr)
- hop.exception_is_here()
- return hop.gendirectcall(ll_write, *args_v)
-
- def rtype_method_close(self, hop):
- r_self = hop.inputarg(self, 0)
- hop.exception_is_here()
- return hop.gendirectcall(ll_close, r_self)
-
- def rtype_method_read(self, hop):
- r_self = hop.inputarg(self, 0)
- if len(hop.args_v) != 2:
- arg_1 = hop.inputconst(lltype.Signed, -1)
- else:
- arg_1 = hop.inputarg(lltype.Signed, 1)
- hop.exception_is_here()
- return hop.gendirectcall(ll_read, r_self, arg_1)
-
- def rtype_method_seek(self, hop):
- r_self = hop.inputarg(self, 0)
- arg_1 = hop.inputarg(lltype.Signed, 1)
- if len(hop.args_v) != 3:
- arg_2 = hop.inputconst(lltype.Signed, os.SEEK_SET)
- else:
- arg_2 = hop.inputarg(lltype.Signed, 2)
- hop.exception_is_here()
- return hop.gendirectcall(ll_seek, r_self, arg_1, arg_2)
-
diff --git a/rpython/rtyper/module/ll_os.py b/rpython/rtyper/module/ll_os.py
--- a/rpython/rtyper/module/ll_os.py
+++ b/rpython/rtyper/module/ll_os.py
@@ -1685,7 +1685,7 @@
def tmpnam_llimpl():
return rffi.charp2str(os_tmpnam(lltype.nullptr(rffi.CCHARP.TO)))
- return extdef([], None, llimpl=tmpnam_llimpl,
+ return extdef([], str, llimpl=tmpnam_llimpl,
export_name="ll_os.ll_os_tmpnam")
# --------------------------- os.stat & variants ---------------------------
diff --git a/rpython/translator/tool/graphpage.py
b/rpython/translator/tool/graphpage.py
--- a/rpython/translator/tool/graphpage.py
+++ b/rpython/translator/tool/graphpage.py
@@ -200,7 +200,7 @@
dotgen.emit_edge(nameof(cdef), nameof(prevcdef), color="red")
prevcdef = cdef
cdef = cdef.basedef
-
+
self.source = dotgen.generate(target=None)
def followlink(self, name):
@@ -224,7 +224,7 @@
dotgen.emit('mclimit=15.0')
self.do_compute(dotgen, *args, **kwds)
-
+
self.source = dotgen.generate(target=None)
# link the function names to the individual flow graphs
@@ -264,7 +264,7 @@
data = self.labelof(classdef, classdef.shortname)
dotgen.emit_node(nameof(classdef), label=data, shape="box")
dotgen.emit_edge(nameof(classdef.basedef), nameof(classdef))
-
+
def labelof(self, obj, objname):
name = objname
i = 1
@@ -409,22 +409,11 @@
elif isinstance(obj, Link):
try_show(obj.prevblock)
elif isinstance(obj, Block):
- import gc
- pending = [obj] # pending blocks
- seen = {obj: True, None: True}
- for x in pending:
- for y in gc.get_referrers(x):
- if isinstance(y, FunctionGraph):
- y.show()
- return
- elif isinstance(y, Link):
- block = y.prevblock
- if block not in seen:
- pending.append(block)
- seen[block] = True
- elif isinstance(y, dict):
- pending.append(y) # go back from the dict to the real obj
- graph = IncompleteGraph(pending)
+ graph = obj.get_graph()
+ if isinstance(graph, FunctionGraph):
+ graph.show()
+ return
+ graph = IncompleteGraph(graph)
SingleGraphPage(graph).display()
else:
raise TypeError("try_show(%r object)" % (type(obj).__name__,))
@@ -449,7 +438,7 @@
seen[block] = True
return pending
else:
- raise TypeError("try_get_functiongraph(%r object)" %
(type(obj).__name__,))
+ raise TypeError("try_get_functiongraph(%r object)" %
(type(obj).__name__,))
class IncompleteGraph:
name = '(incomplete graph)'
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit