[Zope] Content-length

Brian Lloyd Brian@digicool.com
Tue, 11 Apr 2000 10:29:08 -0400


> I am using a sub-set of Zope 2.16 i.e. ZPublisher, 
> DocumentTemplate with a standard CGI calling convention via 
> Apache on NT(no PCGI or FastCGI at this point). I want to use 
> the TreeTag with this so I have been playing around with it 
> and have it partially working so far.
> 
> I am having an amusing? problem. The TreeTag outputs multiple 
> lines separating them with '\n'. When the Publish module 
> calculates the content length it sees one character per new 
> line for example it evaluates 'this\nis\na\ntest\n' properly 
> as being 15 chars in length. However when sys.stdout writes 
> it, it converts '\n' to '\r\n' this being Windows and all. So 
> my 15 character string has now been effectively lengthed to 
> 19 characters and the displayed output is truncated by 4 characters.
> 
> I tried replacing '\n'  with os.linesep and this works for 
> the tree code but has no effect on the rest of the stuff that 
> gets generated.
> 
> I am sure I am not the first to run in to this, does anyone 
> have a solution they wish to share? I know I can fix this 
> with a regular expression substitution but I would like to 
> avoid that if I can.

Hi Robert - 

Zope itself has a little bit easier time dealing with this, since
the win32 binary distribution contains its own Python binary. The
root of the problem is that by default, IO is done in *text mode*
(which as you've seen, means that win32 will helpfully translate
all \n's to \r\n's for you). Zope's bundled Python binary uses 
binary mode by default, mainly because at the time we began shipping
a bundled binary you couldn't set the mode manually from Python.

As of 1.5.2 though, you can. I think that adding the following at
the beginning of your code (before anything goes to sys.stdout) 
should take care of your problem:

# If on windows, set the line-end translation mode
# to binary to avoid unintended help from windows.
# If we're not on windows, msvcrt will fail to import
# and it won't matter.
try:
  import sys, os, msvcrt
  msvcrt.setmode(sys.stdin,  os.O_BINARY)
  msvcrt.setmode(sys.stdout, os.O_BINARY)
  msvcrt.setmode(sys.stderr, os.O_BINARY)
except:
  pass


Hope this helps!


Brian Lloyd        brian@digicool.com
Software Engineer  540.371.6909              
Digital Creations  http://www.digicool.com