view tests/test-debugrename.t @ 14007:d764463b433e

atomictempfile: avoid infinite recursion in __del__(). The problem is that a programmer using atomictempfile directly can make an innocent everyday mistake -- not enough args to the constructor -- which escalates badly. You would expect a simple TypeError crash in that case, but you actually get an infinite recursion that is surprisingly difficult to kill: it happens between __del__() and __getattr__(), and Python does not handle infinite recursion from __del__() well. The fix is to not implement __getattr__(), but instead assign instance attributes for the methods we wish to delegate to the builtin file type: write() and fileno(). I've audited mercurial.* and hgext.* and found no users of atomictempfile using methods other than write() and rename(). I audited third-party extensions and found one (snap) passing an atomictempfile to util.fstat(), so I also threw in fileno(). The last time I submitted a similar patch, Matt proposed that we make atomictempfile a subclass of file instead of wrapping it. Rejected on grounds of unnecessary complexity: for one thing, it would make the Windows implementation of posixfile quite a bit more complex. It would have to become a subclass of file rather than a simple function -- but since it's written in C, this is non-obvious and non-trivial. Furthermore, there's nothing wrong with wrapping objects and delegating methods: it's a well-established pattern that works just fine in many cases. Subclassing is not the answer to all of life's problems.
author Greg Ward <greg@gerg.ca>
date Sun, 24 Apr 2011 19:25:10 -0400
parents 5d9bc49b0b1e
children 55c6ebd11cb9
line wrap: on
line source

  $ hg init
  $ echo a > a
  $ hg ci -Am t
  adding a

  $ hg mv a b
  $ hg ci -Am t1
  $ hg debugrename b
  b renamed from a:b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3

  $ hg mv b a
  $ hg ci -Am t2
  $ hg debugrename a
  a renamed from b:37d9b5d994eab34eda9c16b195ace52c7b129980

  $ hg debugrename --rev 1 b
  b renamed from a:b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3