From: Jeff A. <ja...@fa...> - 2012-10-21 08:32:50
|
One of the tests of the io module opens a file then overrides flush in the file object. (It does this to prove that flush is called by close.) The test is the equivalent of this standalone example: import io def shanks() : raise(ValueError("Bang!")) f = io.FileIO("x.tmp", "w") f.write(b'Hello') f.flush = shanks f.close() When I run this in Python 2.7 the ValueError is indeed raised, but in my Jython development environment, where I am implementing FileIO as an exposed built-in, the program fails at the assignment to f.flush with "TypeError: readonly attribute". My implementation of flush is exposed (actually from _io.IOBase) like this: @ExposedMethod(doc = PyIOBase.flush_doc) final void _IOBase_flush() { ioDelegate.checkClosed(); ioDelegate.flush(); } When I single-step through f.flush = shanks, Jython has resolved f.flush to a PyMethodDescr that has no capability to be assigned, although (looking into PyObject.__setattr__) either possession of an instance-level dictionary or the right kind of descriptor have something to do with it. A similar experiment in with list.pop in Python 2.7 shows that not every method attribute of every type should be assignable. How do I make "flush" assignable? How do I know when particular method (or all the methods of a particular type) should permit or resist assignment? Jeff Allen |
From: Jeff A. <ja...@fa...> - 2012-10-21 22:18:08
|
Thanks for the response Julian. I'm sure that's right, but here the descriptor arises from a semi-magical process behind the @ExposedMethod annotation, and I don't know how to influence it. I've gone for this (in _io.IOBase): @ExposedGet protected PyObject __dict__ = new PyStringMap(); @Override public PyObject fastGetDict() { return __dict__; } But since examples like this are rare in the Jython code base, and almost all in "framework" classes like PyInstance, it would be good to have confirmation from someone with a knowledge of the Jython implementation. It does seem to work in the example, though. Jeff On 21/10/2012 21:13, Julian Kennedy wrote: > I can only comment on the descriptor part. About making flush > assignable. If its a descriptor, then implementing __set__ method on > the descriptor should make it assignable as far as I understand. Not > sure how the descriptor is implemented in the jython code, but that is > what one would do in a python descriptor class. > > On 21 October 2012 10:31, Jeff Allen<ja...py...@fa...> wrote: >> One of the tests of the io module opens a file then overrides flush in >> the file object. (It does this to prove that flush is called by close.) >> The test is the equivalent of this standalone example: >> >> import io >> >> def shanks() : >> >> raise(ValueError("Bang!")) >> >> >> f = io.FileIO("x.tmp", "w") >> >> f.write(b'Hello') >> >> f.flush = shanks >> >> f.close() >> >> >> When I run this in Python 2.7 the ValueError is indeed raised, but in my >> Jython development environment, where I am implementing FileIO as an >> exposed built-in, the program fails at the assignment to f.flush with >> "TypeError: readonly attribute". >> >> My implementation of flush is exposed (actually from _io.IOBase) like this: >> >> @ExposedMethod(doc = PyIOBase.flush_doc) >> >> final void _IOBase_flush() { >> >> ioDelegate.checkClosed(); >> >> ioDelegate.flush(); >> >> } >> >> When I single-step through f.flush = shanks, Jython has resolved f.flush >> to a PyMethodDescr that has no capability to be assigned, although >> (looking into PyObject.__setattr__) either possession of an >> instance-level dictionary or the right kind of descriptor have something >> to do with it. >> >> A similar experiment in with list.pop in Python 2.7 shows that not every >> method attribute of every type should be assignable. >> >> How do I make "flush" assignable? >> >> How do I know when a particular method (or all the methods of a particular >> type) should permit or resist assignment? >> >> Jeff Allen >> >> >> >> ------------------------------------------------------------------------------ >> Everyone hates slow websites. So do we. >> Make your web apps faster with AppDynamics >> Download AppDynamics Lite for free today: >> http://p.sf.net/sfu/appdyn_sfd2d_oct >> _______________________________________________ >> Jython-dev mailing list >> Jyt...@li... >> https://lists.sourceforge.net/lists/listinfo/jython-dev |
From: Philip J. <pj...@un...> - 2012-10-21 23:44:01
|
On Oct 21, 2012, at 1:31 AM, Jeff Allen wrote: > One of the tests of the io module opens a file then overrides flush in > the file object. (It does this to prove that flush is called by close.) > The test is the equivalent of this standalone example: > > import io > > def shanks() : > > raise(ValueError("Bang!")) > > > f = io.FileIO("x.tmp", "w") > > f.write(b'Hello') > > f.flush = shanks > > f.close() > > > When I run this in Python 2.7 the ValueError is indeed raised, but in my > Jython development environment, where I am implementing FileIO as an > exposed built-in, the program fails at the assignment to f.flush with > "TypeError: readonly attribute". This is about test_flush_error_on_close, right? FYI it's actually testing that BufferedReader/Writer.close call the overwritten flush method. If that's implemented in Java you can call obj.invoke("write", buf) and that will do what you want, doing a full lookup of the method descriptor in the obj's __dict__ -- Philip Jenvey |
From: Jeff A. <ja...@fa...> - 2012-10-22 08:18:09
|
On 22/10/2012 00:44, Philip Jenvey wrote: > On Oct 21, 2012, at 1:31 AM, Jeff Allen wrote: > >> One of the tests of the io module opens a file then overrides flush in >> the file object. ... in my >> Jython development environment, where I am implementing FileIO as an >> exposed built-in, the program fails at the assignment to f.flush with >> "TypeError: readonly attribute". > This is about test_flush_error_on_close, right? FYI it's actually testing that BufferedReader/Writer.close call the overwritten flush method. > > If that's implemented in Java you can call obj.invoke("write", buf) and that will do what you want, doing a full lookup of the method descriptor in the obj's __dict__ > > -- > Philip Jenvey Hi Philip: That's right, but there are 3 variants of test_flush_error_on_close, and it's the one in IOTest, where f is a Java _io.PyFileIO that was giving me trouble. I'm reasonably sure my call to invoke("flush") is correct, but the missing link was to give PyFileIO a __dict__ attribute at instance level, which I've chosen to do in my base class PyIOBase (see post at 2246 UTC). However, I wonder if I've done this quite correctly, and whether I should I still ask for a dictionary in my _io.*.derived specifications if the base class has one. Suspect not and that putting Python subclasses of _io._IOBase through the same code will reveal that. Jeff |
From: Philip J. <pj...@un...> - 2012-10-22 19:25:12
|
On Oct 22, 2012, at 1:17 AM, Jeff Allen wrote: > On 22/10/2012 00:44, Philip Jenvey wrote: >> On Oct 21, 2012, at 1:31 AM, Jeff Allen wrote: >> >>> One of the tests of the io module opens a file then overrides flush in >>> the file object. ... in my >>> Jython development environment, where I am implementing FileIO as an >>> exposed built-in, the program fails at the assignment to f.flush with >>> "TypeError: readonly attribute". >> This is about test_flush_error_on_close, right? FYI it's actually testing that BufferedReader/Writer.close call the overwritten flush method. >> >> If that's implemented in Java you can call obj.invoke("write", buf) and that will do what you want, doing a full lookup of the method descriptor in the obj's __dict__ >> >> -- >> Philip Jenvey > Hi Philip: > > That's right, but there are 3 variants of test_flush_error_on_close, > and it's the one in IOTest, where f is a Java _io.PyFileIO that was > giving me trouble. I'm reasonably sure my call to invoke("flush") is > correct, but the missing link was to give PyFileIO a __dict__ attribute > at instance level, which I've chosen to do in my base class PyIOBase > (see post at 2246 UTC). > > However, I wonder if I've done this quite correctly, and whether I > should I still ask for a dictionary in my _io.*.derived specifications > if the base class has one. Suspect not and that putting Python > subclasses of _io._IOBase through the same code will reveal that. Oh I see, my fault. You won't need 'have_dict' in the derived. PyBaseException is probably the simplest example of this to look at, although it lazily creates its dictionary -- Philip Jenvey |