[PATCH 3 of 3 RFC] setup: install & build documentation using docutils

Martin Geisler mg at lazybytes.net
Tue Nov 24 09:51:37 CST 2009


Dan Villiom Podlaski Christiansen <danchr at gmail.com> writes:

> On 22 Nov 2009, at 22:23, Martin Geisler wrote:
>
>>> +    def finalize_options (self):
>>> +        # bit of a hack for turning "lib.<whatever>" into "data.<whatever>"
>>> +        undefined = self.build_dir is None
>>> +        self.set_undefined_options('build',
>>> +                                   ('build_lib', 'build_dir'),
>>> +                                   ('force', 'force'))
>>> +        if undefined:
>>> +            self.build_dir = self.build_dir.replace('lib', 'data')
>> 
>> Why is this hack necessary and what problem does it solve?
>
> Strictly speaking, it's not necessary.

Right -- seperate patch then, please :-)

> It does, however, let me put temporary data files in a separate build
> directory. Generally speaking, I consider polluting the source
> directory with generated files or build products a bad habit.

Yes, it is a very nice feature to support out-of-tree builds. But I
guess your self.build_dir is only used by the gendoc-related code, not
the rest of Distutils? If so, then perhaps we should look into a more
general solution.

>>> +    def gendoc(self, output):
>>> +        from doc import gendoc
>>> +        from cStringIO import StringIO
>>> +
>>> +        s = StringIO()
>>> +        gendoc.show_doc(s)
>>> +        s = s.getvalue()
>>> +
>>> +        # only write to the file if the output has changed
>>> +        if not (os.path.exists(output) and file(output).read() == s):
>>> +            file(output, 'w').write(s)
>> 
>> Perhaps we could use self.make_file here like you do below?
>
> Well, yes and no. ‘make_file’ requires the dependancies to be known,
> and they aren't. This step is quite fast, so I don't think it's a
> problem to execute it in every build.

Yeah, it's not that it will slow things down... I'm just trying to keep
things simple. What about this instead:

   def gendoc(self, output):
        from doc import gendoc

        fp = open(output, 'w')
        gendoc.show_doc(fp)
        fp.close()

That is about as simple as it gets.

>> We should not import the manpage writer from Docutils, we have some
>> patches that are not yet applied upstream:
>> 
>>  http://sf.net/tracker/?func=detail&aid=2894087&group_id=38414&atid=422032
>
> I haven't checked the exact changes, but I've changed this nonetheless.

Thanks.

>>> +            datafiles.append((join('man', 'man' + manfile.rsplit('.', 1)[1]),
>>> +                              [manfile]))
>> 
>> I think manfile.rsplit('.', 1)[1] is the same as srcfile[-5]?
>
> For the two first, I used the ‘fnmatch’ module.

Okay, that sounds like an improvement over our own regexps.

> For the last one, not quite; you missed the [1] ;) It extracts the
> category C from ‘abcdef.C.txt’. I've changed this to make it a bit
> cleaner and more readable by using os.path.splitext().

Sounds good.

>>> +            # extract dependancies from docutils
>>> +            dependancies = [srcfile] + settings.record_dependencies.list
>>> +
>>> +            # generate the documentation files; using distutils to avoid
>>> +            # unnecessary processing
>>> +            self.make_file(infiles=[srcfile] + dependancies, outfile=htmlfile,
>> 
>> You already have srcfile in the dependancies list. Please remember to
>> correct the name as timeless pointed out :-)
>
> Yeah, this was the inconsistency I mentioned in my response to
> timeless; I've already fixed the spellbug with a mighty ‘sed’ line :)

Excellent :-)

>> Is this code there in order to avoid parsing the documents twice? I
>> guess you could have used docutils.core.publish_programmatically or
>> one of the other publish_* function in that module?
>
> Indeed, it avoids parsing twice. There's also another advantage which
> the ‘publish_programmatically’ API doesn't provide; we use the
> docutils API to always parse and extract dependencies, but avoid
> generation when the output is up-to-date w.r.t. its dependancies.
> Should I elaborate on this in a comment or two?

Sure, you can put in a small comment. My original question was triggered
by the amount of code, which seems to duplicate code from Docutils.

> One thing that just occurred to me: It would be advantageous to
> generalise as much as possible of these commands.

I actually see all this as somewhat internal to Mercurial. We're using
it to build our manpages, which are assembled by extracting
documentation from our docstrings. That's all, right now.

> Then, we could include bundle them for extensions to rely on. As a
> first, tiny step towards it, I've moved both ‘gendoc’ and ‘rst2man’
> into a sub-package of ‘mercurial’.

Please don't move too fast -- it's a *feature* that these things are
fairly self-contained. At least that's how I see it. Right now it's easy
to call gendoc.py with different locales from test-gendoc, and we should
keep it simple.

-- 
Martin Geisler

VIFF (Virtual Ideal Functionality Framework) brings easy and efficient
SMPC (Secure Multiparty Computation) to Python. See: http://viff.dk/.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: not available
URL: <http://selenic.com/pipermail/mercurial-devel/attachments/20091124/f92898ec/attachment.pgp>


More information about the Mercurial-devel mailing list