[Distutils] Access to Python config info

Fred L. Drake Fred L. Drake, Jr." <fdrake@acm.org
Thu, 17 Dec 1998 12:37:59 -0500 (EST)


--udwOQwHuZC
Content-Type: text/plain; charset=us-ascii
Content-Description: message body text
Content-Transfer-Encoding: 7bit


Greg Stein writes:
 > I don't see much of a rationale for *not* doing this at install time.
 > The file is a bunch of constants that are easily determined when you
 > build/install Python.

  Yes.  It can include code to regenerate the "right stuff" when run
as a script as well.  Running it as a script can be done at the end of 
installation.

 > There is a caveat for trying to get it to function with 1.5.2, but I
 > don't believe that changes the long-term interface, which I maintain are
 > simple names/values.

  What's the caveat?

 > Note that these files are always installed at
 > $(exec_prefix)/lib/python$(version)/config/ (as far as I can tell,
 > that's fixed).

  I think you're right.
  I've attached a sysconfig.py that works on Unix.  Someone familiar
with other platforms will need to make it work there as well by adding 
additional _init_<name>() functions; <name> should be os.name.  When
run as a script, it rewrites itself with the discovered information.


  -Fred

--
Fred L. Drake, Jr.	     <fdrake@acm.org>
Corporation for National Research Initiatives
1895 Preston White Dr.	    Reston, VA  20191


--udwOQwHuZC
Content-Type: text/plain
Content-Description: preliminary sysconfig.py
Content-Disposition: inline;
	filename="sysconfig.py"
Content-Transfer-Encoding: 7bit

"""Prototype sysconfig module that loads information when run as a script,
but only defines constants when imported.

This should be run as a script as one of the last steps of the Python
installation process.
"""

# START DATA
# END DATA

def _init_posix():
    import os
    import re
    import sys

    g = globals()

    version = sys.version[:3]
    config_dir = os.path.join(
        sys.exec_prefix, "lib", "python" + version, "config")

    # load the installed config.h:
    define_rx = re.compile("#define ([A-Z][A-Z0-9_]+) (.*)\n")
    undef_rx = re.compile("/[*] #undef ([A-Z][A-Z0-9_]+) [*]/\n")
    fp = open(os.path.join(config_dir, "config.h"))

    while 1:
        line = fp.readline()
        if not line:
            break
        m = define_rx.match(line)
        if m:
            n, v = m.group(1, 2)
            if v == "1":
                g[n] = 1
            else:
                g[n] = v
        else:
            m = undef_rx.match(line)
            if m:
                g[m.group(1)] = 0

    # load the installed Makefile.pre.in:
    variable_rx = re.compile("([a-zA-Z][a-zA-Z0-9_]+)\s*=\s*(.*)\n")
    done = {}
    notdone = {}
    fp = open(os.path.join(config_dir, "Makefile"))

    while 1:
        line = fp.readline()
        if not line:
            break
        m = variable_rx.match(line)
        if m:
            n, v = m.group(1, 2)
            if "$" in v:
                notdone[n] = v
            else:
                done[n] = v

    # do variable interpolation here
    findvar1_rx = re.compile(r"\$.([A-Za-z][A-Za-z0-9_]*).")
    findvar2_rx = re.compile(r"\$.([A-Za-z][A-Za-z0-9_]*)}")
    while notdone:
        for name in notdone.keys():
            value = notdone[name]
            m = findvar1_rx.search(value)
            if not m:
                m = findvar2_rx.search(value)
            if m:
                n = m.group(1)
                if done.has_key(n):
                    after = value[m.end():]
                    value = value[:m.start()] + done[n] + after
                    if "$" in after:
                        notdone[name] = value
                    else:
                        done[name] = value
                        del notdone[name]
                elif notdone.has_key(n):
                    # get it on a subsequent round
                    pass
                else:
                    done[n] = ""
                    after = value[m.end():]
                    value = value[:m.start()] + after
                    if "$" in after:
                        notdone[name] = value
                    else:
                        done[name] = value
                        del notdone[name]
            else:
                del notdone[name]

    # save the results in the global dictionary
    g.update(done)

    # save the results in the source file
    filename = os.path.splitext(sys.argv[0])[0] + ".py"
    lines = open(filename).readlines()
    start = lines.index("# START DATA\n")
    end = lines.index("# END DATA\n")
    newdata = []
    items = g.items()
    items.sort()
    for name, value in items:
        if name[0] != "_":
            newdata.append("%s = %s\n" % (name, `value`))
    lines[start+1:end] = newdata
    open(filename, "w").writelines(lines)


if __name__ == "__main__":
    import os
    exec "_init_%s()" % os.name
del _init_posix

--udwOQwHuZC--