Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #112229 > unrolled thread

make an object read only

Started byRobin Becker <robin@reportlab.com>
First post2016-08-02 08:12 -0700
Last post2016-08-07 16:40 -0700
Articles 8 — 7 participants

Back to article view | Back to comp.lang.python


Contents

  make an object read only Robin Becker <robin@reportlab.com> - 2016-08-02 08:12 -0700
    Re: make an object read only "dfh@forestfield.co.uk" <dfh@forestfield.co.uk> - 2016-08-02 09:28 -0700
    Re: make an object read only Steven D'Aprano <steve+python@pearwood.info> - 2016-08-03 02:36 +1000
    Re: make an object read only dieter <dieter@handshake.de> - 2016-08-03 09:57 +0200
    Re: make an object read only Lawrence D’Oliveiro <lawrencedo99@gmail.com> - 2016-08-04 17:03 -0700
      Re: make an object read only Robin Becker <robin@reportlab.com> - 2016-08-05 09:51 +0100
      Re: make an object read only Antoon Pardon <antoon.pardon@rece.vub.ac.be> - 2016-08-05 11:04 +0200
      Re: make an object read only Rick Johnson <rantingrickjohnson@gmail.com> - 2016-08-07 16:40 -0700

#112229 — make an object read only

FromRobin Becker <robin@reportlab.com>
Date2016-08-02 08:12 -0700
Subjectmake an object read only
Message-ID<c6a0318e-af2c-4390-ab4c-a6e0fa35891a@googlegroups.com>
A reportlab user found he was doing the wrong thing by calling canvas.save 
repeatedly, our documentation says you should not use Canvas objects after the 
save method has been used. The user had mixed results :(

It would be better to make the canvas object completely immutable all the way 
down when save has been called, but I think that's quite hard as these objects 
have quite a large and varied set of attributes, lists other objects 
dictionaries etc etc.

I can think of some strategies for making the object unusable eg changing it's 
class and getting rid of __dict__, but that disallows referencing valid 
properties eg pagesize, fontName, etc etc.

Is there a way to recursively turn everything immutable?
-- 
Robin Becker

[toc] | [next] | [standalone]


#112231

From"dfh@forestfield.co.uk" <dfh@forestfield.co.uk>
Date2016-08-02 09:28 -0700
Message-ID<ba5e83a4-9ca4-4617-a0ce-a09843ef1314@googlegroups.com>
In reply to#112229
On Tuesday, 2 August 2016 16:13:01 UTC+1, Robin Becker  wrote:
> A reportlab user found he was doing the wrong thing by calling canvas.save 
> repeatedly, our documentation says you should not use Canvas objects after the 
> save method has been used. The user had mixed results :(
> 
> It would be better to make the canvas object completely immutable all the way 
> down when save has been called, ......
> 
> Is there a way to recursively turn everything immutable?
> -- 
> Robin Becker

Years ago I contributed a recipe to the O'Reilly Python Cookbook, 2nd Ed - 6.12 Checking an Instance for any State Changes. My original submission was rather more naive than that but Alex Martelli, one of the editors, rather took a fancy to the idea and knocked into the more presentable shape that got published. I'm wondering whether there would be any way of turning this idea around to achieve what you want.
--
Regards
David Hughes
Forestfield Software

[toc] | [prev] | [next] | [standalone]


#112232

FromSteven D'Aprano <steve+python@pearwood.info>
Date2016-08-03 02:36 +1000
Message-ID<57a0cc10$0$1610$c3e8da3$5496439d@news.astraweb.com>
In reply to#112229
On Wed, 3 Aug 2016 01:12 am, Robin Becker wrote:

> A reportlab user found he was doing the wrong thing by calling canvas.save
> repeatedly, our documentation says you should not use Canvas objects after
> the save method has been used. The user had mixed results :( 
> 
> It would be better to make the canvas object completely immutable all the
> way down when save has been called, but I think that's quite hard as these
> objects have quite a large and varied set of attributes, lists other
> objects dictionaries etc etc.

If save() is the only problematic method, that's easy to fix:

class X:
    def _bad_save(self):
        raise RuntimeError("I told you not to call save() more than once!")

    def save(self):
        # do the actual saving
        # then replace the method:
        self.save = self._bad_save


Hmmm... clever as that is, it's probably not clever enough, as users can
still call the unbound save method:

X.save(instance)

So back to the really old-fashioned way:

class X:
    def __init__(self):
        self._saved = False

    def save(self):
        if self._saved:
            raise RuntimeError("*wack with clue stick*")
        else:
            # do the actual saving
            self._saved = True


> I can think of some strategies for making the object unusable eg changing
> it's class and getting rid of __dict__, but that disallows referencing
> valid properties eg pagesize, fontName, etc etc.

It shouldn't disallow anything.

class X:
     # implementation of everything, properties, etc.
     # as they are expected to work before saving

     def save(self):
         # do the actual save
         self.__class__ = SavedX


class SavedX(X):
    # Override just the bits that need neutering
    # including save

    def save(self):
        raise RuntimeError("stop that!")



The tricky bit may be preventing writes to the instance __dict__. I don't
think it is practical to allow the user to add arbitrary attributes to the
instance up to the point they call save(), then prevent them from doing the
same. You might be able to get it to work, but with difficulty.

Better to fix save() so you can call it multiple times without breaking the
instance. If you can't do that, the least-worst alternative would be to use
__slots__ for both X and SavedX so that the user can't add new attributes
at all.

But really, the right way to do this is to fix the class so that save() can
be called multiple times. In your editor, does selecting Save twice corrupt
the file you're working on?


> Is there a way to recursively turn everything immutable?

First you have to come up with a way to turn everything immutable. (Good
luck with that.) Then apply it recursively to the object and all its
attributes.




-- 
Steve
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.

[toc] | [prev] | [next] | [standalone]


#112264

Fromdieter <dieter@handshake.de>
Date2016-08-03 09:57 +0200
Message-ID<mailman.132.1470211075.6033.python-list@python.org>
In reply to#112229
Robin Becker <robin@reportlab.com> writes:

> A reportlab user found he was doing the wrong thing by calling canvas.save 
> repeatedly, our documentation says you should not use Canvas objects after the 
> save method has been used. The user had mixed results :(
>
> It would be better to make the canvas object completely immutable all the way 
> down when save has been called, but I think that's quite hard as these objects 
> have quite a large and varied set of attributes, lists other objects 
> dictionaries etc etc.

If changing things happen at an elementary level (by assigning to
the object's instance attributes), then you could implement
your on "__setattr__/__delattr__" methods. There, you could check
whether you are ready to allow the change or reject it.

[toc] | [prev] | [next] | [standalone]


#112358

FromLawrence D’Oliveiro <lawrencedo99@gmail.com>
Date2016-08-04 17:03 -0700
Message-ID<d75425f2-5c20-40f7-8a83-581737e37034@googlegroups.com>
In reply to#112229
On Wednesday, August 3, 2016 at 3:13:01 AM UTC+12, Robin Becker wrote:
> A reportlab user found he was doing the wrong thing by calling
> canvas.save repeatedly, our documentation says you should not use Canvas
> objects after the save method has been used. The user had mixed results :(

As GvR has said: “we’re all consenting adults here”.

In other words, we”re capable of coping with the consequences of our actions.

[toc] | [prev] | [next] | [standalone]


#112372

FromRobin Becker <robin@reportlab.com>
Date2016-08-05 09:51 +0100
Message-ID<mailman.189.1470387119.6033.python-list@python.org>
In reply to#112358
On 05/08/2016 01:03, Lawrence D’Oliveiro wrote:
........
>> objects after the save method has been used. The user had mixed results :(
>
> As GvR has said: “we’re all consenting adults here”.
>
> In other words, we”re capable of coping with the consequences of our actions.
>

agreed :)
-- 
Robin Becker

[toc] | [prev] | [next] | [standalone]


#112373

FromAntoon Pardon <antoon.pardon@rece.vub.ac.be>
Date2016-08-05 11:04 +0200
Message-ID<mailman.190.1470387911.6033.python-list@python.org>
In reply to#112358
Op 05-08-16 om 02:03 schreef Lawrence D’Oliveiro:
> On Wednesday, August 3, 2016 at 3:13:01 AM UTC+12, Robin Becker wrote:
>> A reportlab user found he was doing the wrong thing by calling
>> canvas.save repeatedly, our documentation says you should not use Canvas
>> objects after the save method has been used. The user had mixed results :(
> As GvR has said: “we’re all consenting adults here”.

No we are not. GvR only uses this when his desired level of protection is
lower than others. If the other's desired level of protection is lower than
GvR's the all consenting adults goes down the drain.

> In other words, we”re capable of coping with the consequences of our actions.

Which doesn't support anything. Python has features that makes it in some
situations easier to cope with those consequences than when that feature
wouldn't be present. So there is nothing wrong in argueing for a feature
that would do the same.

-- 
Antoon.

[toc] | [prev] | [next] | [standalone]


#112465

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2016-08-07 16:40 -0700
Message-ID<9d057783-fbeb-437c-b357-da5a84c98aeb@googlegroups.com>
In reply to#112358
On Thursday, August 4, 2016 at 7:03:32 PM UTC-5, Lawrence D’Oliveiro wrote:
> As GvR has said: “we’re all consenting adults here”.

But as we've learned from animal farm, some are more consenting than others.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web