summaryrefslogtreecommitdiffstats
path: root/Tools/faqwiz
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2010-08-02 22:28:01 (GMT)
committerGeorg Brandl <georg@python.org>2010-08-02 22:28:01 (GMT)
commite27c906c52a5827294037100662a7b0ccb303a47 (patch)
tree42f3d416500e5b57ab7100f3da2a28a1455b836d /Tools/faqwiz
parent0063958c2ed210a0d70da2ab26f660a092888cf0 (diff)
downloadcpython-e27c906c52a5827294037100662a7b0ccb303a47.zip
cpython-e27c906c52a5827294037100662a7b0ccb303a47.tar.gz
cpython-e27c906c52a5827294037100662a7b0ccb303a47.tar.bz2
Remove faqwiz tool.
Diffstat (limited to 'Tools/faqwiz')
-rw-r--r--Tools/faqwiz/README114
-rw-r--r--Tools/faqwiz/faqconf.py577
-rw-r--r--Tools/faqwiz/faqcust.py1
-rwxr-xr-xTools/faqwiz/faqw.py33
-rw-r--r--Tools/faqwiz/faqwiz.py840
-rwxr-xr-xTools/faqwiz/move-faqwiz.sh55
6 files changed, 0 insertions, 1620 deletions
diff --git a/Tools/faqwiz/README b/Tools/faqwiz/README
deleted file mode 100644
index a1e4d44..0000000
--- a/Tools/faqwiz/README
+++ /dev/null
@@ -1,114 +0,0 @@
-FAQ Wizard
-----------
-
-Author: Guido van Rossum <guido@python.org>
-Version: 1.0
-Date: 6 April 1998
-
-
-This is a CGI program that maintains a user-editable FAQ. It uses RCS
-to keep track of changes to individual FAQ entries. It is fully
-configurable; everything you might want to change when using this
-program to maintain some other FAQ than the Python FAQ is contained in
-the configuration module, faqconf.py.
-
-Note that the bulk of the code is not an executable script; it's an
-importable module. The actual script in cgi-bin is minimal.
-
-Files:
-
-faqw.py executable script to be edited and installed in cgi-bin
-faqwiz.py main module, lives in same directory as FAQ entry files
-faqconf.py main configuration module
-faqcust.py additional local customization module (optional)
-move-faqwiz.sh Script to move faqwiz entries.
-
-
-What's New?
------------
-
-Version 1.0 corrects some minor bugs and uses tab-agnostic
-indentation; it is otherwise unchanged from version 0.9.0.
-
-Version 0.9.0 uses the re module (Perl style regular expressions) for
-all its regular expression needs, instead of the regex and regsub
-modules (Emacs style). This affects the syntax for regular
-expressions entered by the user as search strings (with "regular
-expression" checked), hence the version number jump.
-
-
-Setup Information
------------------
-
-This assumes you are familiar with Python, with your http server, and
-with running CGI scripts under your http server. You need Python 1.5
-or better.
-
-Select a place where the Python modules that constitute the FAQ wizard
-will live (the directory where you unpacked it is an obvious choice).
-This will be called the SRCDIR. This directory should not be writable
-by other users of your system (since they would be able to execute
-arbitrary code by invoking the FAQ wizard's CGI script).
-
-Create a dedicated working directory, preferably one that's not
-directly reachable from your http server. This will be called the
-FAQDIR. Create a subdirectory named RCS. Make both the working
-directory and the RCS subdirectory wrld-writable. (This is essential,
-since the FAQ wizard runs as use nobody, and needs to create
-additional files here!)
-
-Edit faqconf.py to reflect your setup. You only need to edit the top
-part, up till the line of all dashes. The comments should guide you
-in your edits. (Actually, you can also choose to add your changes to
-faqcust.py and leave faqconf.py alone. This is essential if you are
-maintaining multiple FAQs; see below.)
-
-Don't forget to edit the SECTION_TITLES variables to reflect the set
-of section titles for your FAQ!
-
-Next, edit faqw.py to reflect the pathname of your Python interpreter
-and the values for SRCDIR and FAQDIR that you just chose. Then
-install faqw.py in your cgi-bin directory. Make sure that it is
-world-executable. You should now be able to connect to the FAQ wizard
-by entering the following URL in your web client (subsituting the
-appropriate host and port for "your.web.server", and perhaps
-specifying a different directory for "cgi-bin" if local conventions so
-dictate):
-
- http://your.web.server/cgi-bin/faqw.py
-
-If you are unable to get this working, check your server's error_log
-file. The documentation for Python's cgi module in the Python Library
-Reference Manual gives plentyu additional information about installing
-and debugging CGI scripts, including setup debugging. This
-documentation is repeated in the doc string in the cgi module; try
-``import cgi; print cgi.__doc__''.
-
-Assuming this works, you should now be able to add the first entry to
-your FAQ using the FAQ wizard interface. This creates a file
-faq01.001.htp in your working directory and an RCS revision history
-file faq01.001.htp,v in the RCS subdirectory. You can now exercise
-the other FAQ wizard features (search, index, whole FAQ, what's new,
-roulette, and so on).
-
-
-Maintaining Multiple FAQs
--------------------------
-
-If you have multiple FAQs, you need a separate FAQDIR per FAQ, and a
-different customization file per FAQ. The easiest thing to do would
-be to have the faqcust.py for each FAQ live in the FAQDIR for that
-FAQ, but that creates some security concerns, since the FAQDIR must be
-world writable: *if* someone who breaks into your system (or a
-legitimate user) manages to edit the faqcust.py file they can get
-arbitrary code to execute through the FAQ wizard. Therefore, you will
-need a more complex setup.
-
-The best way is probably to have a directory that is only writable by
-you for each FAQ, where you place the copy of faqcust.py for that FAQ,
-and have a world-writable subdirectory DATA for the data. You then
-set FAQDIR to point to the DATA directory and change the faqw.py
-bootstrap script to add FAQDIR/.. to sys.path (in front of SRCDIR, so
-the dummy faqcust.py from SRCDIR is ignored).
-
---Guido van Rossum (home page: http://www.python.org/~guido/)
diff --git a/Tools/faqwiz/faqconf.py b/Tools/faqwiz/faqconf.py
deleted file mode 100644
index d1acd80..0000000
--- a/Tools/faqwiz/faqconf.py
+++ /dev/null
@@ -1,577 +0,0 @@
-"""FAQ Wizard customization module.
-
-Edit this file to customize the FAQ Wizard. For normal purposes, you
-should only have to change the FAQ section titles and the small group
-of parameters below it.
-
-"""
-
-# Titles of FAQ sections
-
-SECTION_TITLES = {
- # SectionNumber : SectionTitle; need at least one entry
- 1: "General information and availability",
-}
-
-# Parameters you definitely want to change
-
-SHORTNAME = "Generic" # FAQ name with "FAQ" omitted
-PASSWORD = "" # Password for editing
-OWNERNAME = "FAQ owner" # Name for feedback
-OWNEREMAIL = "nobody@anywhere.org" # Email for feedback
-HOMEURL = "http://www.python.org" # Related home page
-HOMENAME = "Python home" # Name of related home page
-RCSBINDIR = "/usr/local/bin/" # Directory containing RCS commands
- # (must end in a slash)
-
-# Parameters you can normally leave alone
-
-MAXHITS = 10 # Max #hits to be shown directly
-COOKIE_LIFETIME = 28*24*3600 # Cookie expiration in seconds
- # (28*24*3600 = 28 days = 4 weeks)
-PROCESS_PREFORMAT = 1 # toggle whether preformatted text
- # will replace urls and emails with
- # HTML links
-
-# Markers appended to title to indicate recently change
-# (may contain HTML, e.g. <IMG>); and corresponding
-
-MARK_VERY_RECENT = " **" # Changed very recently
-MARK_RECENT = " *" # Changed recently
-DT_VERY_RECENT = 24*3600 # 24 hours
-DT_RECENT = 7*24*3600 # 7 days
-
-EXPLAIN_MARKS = """
-<P>(Entries marked with ** were changed within the last 24 hours;
-entries marked with * were changed within the last 7 days.)
-<P>
-"""
-
-# Version -- don't change unless you edit faqwiz.py
-
-WIZVERSION = "1.0.4" # FAQ Wizard version
-
-import os, sys
-if os.name in ['nt',]:
- # On NT we'll probably be running python from a batch file,
- # so sys.argv[0] is not helpful
- FAQCGI = 'faq.bat' # Relative URL of the FAQ cgi script
- # LOGNAME is not typically set on NT
- os.environ[ 'LOGNAME' ] = "FAQWizard"
-else:
- # This parameter is normally overwritten with a dynamic value
- FAQCGI = 'faqw.py' # Relative URL of the FAQ cgi script
- FAQCGI = os.path.basename(sys.argv[0]) or FAQCGI
-del os, sys
-
-# Perl (re module) style regular expression to recognize FAQ entry
-# files: group(1) should be the section number, group(2) should be the
-# question number. Both should be fixed width so simple-minded
-# sorting yields the right order.
-
-OKFILENAME = r"^faq(\d\d)\.(\d\d\d)\.htp$"
-
-# Format to construct a FAQ entry file name
-
-NEWFILENAME = "faq%02d.%03d.htp"
-
-# Load local customizations on top of the previous parameters
-
-try:
- from faqcust import *
-except ImportError:
- pass
-
-# Calculated parameter names
-
-COOKIE_NAME = SHORTNAME + "-FAQ-Wizard" # Name used for Netscape cookie
-FAQNAME = SHORTNAME + " FAQ" # Name of the FAQ
-
-# ----------------------------------------------------------------------
-
-# Anything below this point normally needn't be changed; you would
-# change this if you were to create e.g. a French translation or if
-# you just aren't happy with the text generated by the FAQ Wizard.
-
-# Most strings here are subject to substitution (string%dictionary)
-
-# RCS commands
-
-import os
-if os.name in ['nt', ]:
- SH_RLOG = RCSBINDIR + "rlog %(file)s < NUL"
- SH_RLOG_H = RCSBINDIR + "rlog -h %(file)s < NUL"
- SH_RDIFF = RCSBINDIR + "rcsdiff -r%(prev)s -r%(rev)s %(file)s < NUL"
- SH_REVISION = RCSBINDIR + "co -p%(rev)s %(file)s < NUL"
- ### Have to use co -l, or the file is not marked rw on NT
- SH_LOCK = RCSBINDIR + "co -l %(file)s < NUL"
- SH_CHECKIN = RCSBINDIR + "ci -u %(file)s < %(tfn)s"
-else:
- SH_RLOG = RCSBINDIR + "rlog %(file)s </dev/null 2>&1"
- SH_RLOG_H = RCSBINDIR + "rlog -h %(file)s </dev/null 2>&1"
- SH_RDIFF = RCSBINDIR + "rcsdiff -r%(prev)s -r%(rev)s %(file)s </dev/null 2>&1"
- SH_REVISION = RCSBINDIR + "co -p%(rev)s %(file)s </dev/null 2>&1"
- SH_LOCK = RCSBINDIR + "rcs -l %(file)s </dev/null 2>&1"
- SH_CHECKIN = RCSBINDIR + "ci -u %(file)s <%(tfn)s 2>&1"
-del os
-
-# Titles for various output pages (not subject to substitution)
-
-T_HOME = FAQNAME + " Wizard " + WIZVERSION
-T_ERROR = "Sorry, an error occurred"
-T_ROULETTE = FAQNAME + " Roulette"
-T_ALL = "The Whole " + FAQNAME
-T_INDEX = FAQNAME + " Index"
-T_SEARCH = FAQNAME + " Search Results"
-T_RECENT = "What's New in the " + FAQNAME
-T_SHOW = FAQNAME + " Entry"
-T_LOG = "RCS log for %s entry" % FAQNAME
-T_REVISION = "RCS revision for %s entry" % FAQNAME
-T_DIFF = "RCS diff for %s entry" % FAQNAME
-T_ADD = "Add an entry to the " + FAQNAME
-T_DELETE = "Deleting an entry from the " + FAQNAME
-T_EDIT = FAQNAME + " Edit Wizard"
-T_REVIEW = T_EDIT + " - Review Changes"
-T_COMMITTED = T_EDIT + " - Changes Committed"
-T_COMMITFAILED = T_EDIT + " - Commit Failed"
-T_CANTCOMMIT = T_EDIT + " - Commit Rejected"
-T_HELP = T_EDIT + " - Help"
-
-# Generic prologue and epilogue
-
-PROLOGUE = '''
-<HTML>
-<HEAD>
-<TITLE>%(title)s</TITLE>
-</HEAD>
-
-<BODY
- BGCOLOR="#FFFFFF"
- TEXT="#000000"
- LINK="#AA0000"
- VLINK="#906A6A">
-<H1>%(title)s</H1>
-'''
-
-EPILOGUE = '''
-<HR>
-<A HREF="%(HOMEURL)s">%(HOMENAME)s</A> /
-<A HREF="%(FAQCGI)s?req=home">%(FAQNAME)s Wizard %(WIZVERSION)s</A> /
-Feedback to <A HREF="mailto:%(OWNEREMAIL)s">%(OWNERNAME)s</A>
-
-</BODY>
-</HTML>
-'''
-
-# Home page
-
-HOME = """
-<H2>Search the %(FAQNAME)s:</H2>
-
-<BLOCKQUOTE>
-
-<FORM ACTION="%(FAQCGI)s">
- <INPUT TYPE=text NAME=query>
- <INPUT TYPE=submit VALUE="Search"><BR>
- <INPUT TYPE=radio NAME=querytype VALUE=simple CHECKED>
- Simple string
- /
- <INPUT TYPE=radio NAME=querytype VALUE=regex>
- Regular expression
- /<BR>
- <INPUT TYPE=radio NAME=querytype VALUE=anykeywords>
- Keywords (any)
- /
- <INPUT TYPE=radio NAME=querytype VALUE=allkeywords>
- Keywords (all)
- <BR>
- <INPUT TYPE=radio NAME=casefold VALUE=yes CHECKED>
- Fold case
- /
- <INPUT TYPE=radio NAME=casefold VALUE=no>
- Case sensitive
- <BR>
- <INPUT TYPE=hidden NAME=req VALUE=search>
-</FORM>
-
-</BLOCKQUOTE>
-
-<HR>
-
-<H2>Other forms of %(FAQNAME)s access:</H2>
-
-<UL>
-<LI><A HREF="%(FAQCGI)s?req=index">FAQ index</A>
-<LI><A HREF="%(FAQCGI)s?req=all">The whole FAQ</A>
-<LI><A HREF="%(FAQCGI)s?req=recent">What's new in the FAQ?</A>
-<LI><A HREF="%(FAQCGI)s?req=roulette">FAQ roulette</A>
-<LI><A HREF="%(FAQCGI)s?req=add">Add a FAQ entry</A>
-<LI><A HREF="%(FAQCGI)s?req=delete">Delete a FAQ entry</A>
-</UL>
-"""
-
-# Index formatting
-
-INDEX_SECTION = """
-<P>
-<HR>
-<H2>%(sec)s. %(title)s</H2>
-<UL>
-"""
-
-INDEX_ADDSECTION = """
-<P>
-<LI><A HREF="%(FAQCGI)s?req=new&amp;section=%(sec)s">Add new entry</A>
-(at this point)
-"""
-
-INDEX_ENDSECTION = """
-</UL>
-"""
-
-INDEX_ENTRY = """\
-<LI><A HREF="%(FAQCGI)s?req=show&amp;file=%(file)s">%(title)s</A>
-"""
-
-LOCAL_ENTRY = """\
-<LI><A HREF="#%(sec)s.%(num)s">%(title)s</A>
-"""
-
-# Entry formatting
-
-ENTRY_HEADER1 = """
-<HR>
-<H2><A NAME="%(sec)s.%(num)s">%(title)s</A>\
-"""
-
-ENTRY_HEADER2 = """\
-</H2>
-"""
-
-ENTRY_FOOTER = """
-<A HREF="%(FAQCGI)s?req=edit&amp;file=%(file)s">Edit this entry</A> /
-<A HREF="%(FAQCGI)s?req=log&amp;file=%(file)s">Log info</A>
-"""
-
-ENTRY_LOGINFO = """
-/ Last changed on %(last_changed_date)s by
-<A HREF="mailto:%(last_changed_email)s">%(last_changed_author)s</A>
-"""
-
-# Search
-
-NO_HITS = """
-No hits.
-"""
-
-ONE_HIT = """
-Your search matched the following entry:
-"""
-
-FEW_HITS = """
-Your search matched the following %(count)s entries:
-"""
-
-MANY_HITS = """
-Your search matched more than %(MAXHITS)s entries.
-The %(count)s matching entries are presented here ordered by section:
-"""
-
-# RCS log and diff
-
-LOG = """
-Click on a revision line to see the diff between that revision and the
-previous one.
-"""
-
-REVISIONLINK = """\
-<A HREF="%(FAQCGI)s?req=revision&amp;file=%(file)s&amp;rev=%(rev)s"
->%(line)s</A>\
-"""
-DIFFLINK = """\
- (<A HREF="%(FAQCGI)s?req=diff&amp;file=%(file)s&amp;\
-prev=%(prev)s&amp;rev=%(rev)s"
->diff -r%(prev)s -r%(rev)s</A>)\
-"""
-
-# Recently changed entries
-
-NO_RECENT = """
-<HR>
-No %(FAQNAME)s entries were changed in the last %(period)s.
-"""
-
-VIEW_MENU = """
-<HR>
-View entries changed in the last...
-<UL>
-<LI><A HREF="%(FAQCGI)s?req=recent&amp;days=1">24 hours</A>
-<LI><A HREF="%(FAQCGI)s?req=recent&amp;days=2">2 days</A>
-<LI><A HREF="%(FAQCGI)s?req=recent&amp;days=3">3 days</A>
-<LI><A HREF="%(FAQCGI)s?req=recent&amp;days=7">week</A>
-<LI><A HREF="%(FAQCGI)s?req=recent&amp;days=28">4 weeks</A>
-<LI><A HREF="%(FAQCGI)s?req=recent&amp;days=365250">millennium</A>
-</UL>
-"""
-
-ONE_RECENT = VIEW_MENU + """
-The following %(FAQNAME)s entry was changed in the last %(period)s:
-"""
-
-SOME_RECENT = VIEW_MENU + """
-The following %(count)s %(FAQNAME)s entries were changed
-in the last %(period)s, most recently changed shown first:
-"""
-
-TAIL_RECENT = VIEW_MENU
-
-# Last changed banner on "all" (strftime format)
-LAST_CHANGED = "Last changed on %c %Z"
-
-# "Compat" command prologue (this has no <BODY> tag)
-COMPAT = """
-<H1>The whole %(FAQNAME)s</H1>
-See also the <A HREF="%(FAQCGI)s?req=home">%(FAQNAME)s Wizard</A>.
-<P>
-"""
-
-# Editing
-
-EDITHEAD = """
-<A HREF="%(FAQCGI)s?req=help">Click for Help</A>
-"""
-
-REVIEWHEAD = EDITHEAD
-
-
-EDITFORM1 = """
-<FORM ACTION="%(FAQCGI)s" METHOD=POST>
-<INPUT TYPE=hidden NAME=req VALUE=review>
-<INPUT TYPE=hidden NAME=file VALUE=%(file)s>
-<INPUT TYPE=hidden NAME=editversion VALUE=%(editversion)s>
-<HR>
-"""
-
-EDITFORM2 = """
-Title: <INPUT TYPE=text SIZE=70 NAME=title VALUE="%(title)s"><BR>
-<TEXTAREA COLS=72 ROWS=20 NAME=body>%(body)s
-</TEXTAREA><BR>
-Log message (reason for the change):<BR>
-<TEXTAREA COLS=72 ROWS=5 NAME=log>%(log)s
-</TEXTAREA><BR>
-Please provide the following information for logging purposes:
-<TABLE FRAME=none COLS=2>
- <TR>
- <TD>Name:
- <TD><INPUT TYPE=text SIZE=40 NAME=author VALUE="%(author)s">
- <TR>
- <TD>Email:
- <TD><INPUT TYPE=text SIZE=40 NAME=email VALUE="%(email)s">
- <TR>
- <TD>Password:
- <TD><INPUT TYPE=password SIZE=20 NAME=password VALUE="%(password)s">
-</TABLE>
-
-<INPUT TYPE=submit NAME=review VALUE="Preview Edit">
-Click this button to preview your changes.
-"""
-
-EDITFORM3 = """
-</FORM>
-"""
-
-COMMIT = """
-<INPUT TYPE=submit NAME=commit VALUE="Commit">
-Click this button to commit your changes.
-<HR>
-"""
-
-NOCOMMIT_HEAD = """
-To commit your changes, please correct the following errors in the
-form below and click the Preview Edit button.
-<UL>
-"""
-NOCOMMIT_TAIL = """
-</UL>
-<HR>
-"""
-
-CANTCOMMIT_HEAD = """
-Some required information is missing:
-<UL>
-"""
-NEED_PASSWD = "<LI>You must provide the correct password.\n"
-NEED_AUTHOR = "<LI>You must enter your name.\n"
-NEED_EMAIL = "<LI>You must enter your email address.\n"
-NEED_LOG = "<LI>You must enter a log message.\n"
-CANTCOMMIT_TAIL = """
-</UL>
-Please use your browser's Back command to correct the form and commit
-again.
-"""
-
-NEWCONFLICT = """
-<P>
-You are creating a new entry, but the entry number specified is not
-correct.
-<P>
-The two most common causes of this problem are:
-<UL>
-<LI>After creating the entry yourself, you went back in your browser,
- edited the entry some more, and clicked Commit again.
-<LI>Someone else started creating a new entry in the same section and
- committed before you did.
-</UL>
-(It is also possible that the last entry in the section was physically
-deleted, but this should not happen except through manual intervention
-by the FAQ maintainer.)
-<P>
-<A HREF="%(FAQCGI)s?req=new&amp;section=%(sec)s">Click here to try
-again.</A>
-<P>
-"""
-
-VERSIONCONFLICT = """
-<P>
-You edited version %(editversion)s but the current version is %(version)s.
-<P>
-The two most common causes of this problem are:
-<UL>
-<LI>After committing a change, you went back in your browser,
- edited the entry some more, and clicked Commit again.
-<LI>Someone else started editing the same entry and committed
- before you did.
-</UL>
-<P>
-<A HREF="%(FAQCGI)s?req=show&amp;file=%(file)s">Click here to reload
-the entry and try again.</A>
-<P>
-"""
-
-CANTWRITE = """
-Can't write file %(file)s (%(why)s).
-"""
-
-FILEHEADER = """\
-Title: %(title)s
-Last-Changed-Date: %(date)s
-Last-Changed-Author: %(author)s
-Last-Changed-Email: %(email)s
-Last-Changed-Remote-Host: %(REMOTE_HOST)s
-Last-Changed-Remote-Address: %(REMOTE_ADDR)s
-"""
-
-LOGHEADER = """\
-Last-Changed-Date: %(date)s
-Last-Changed-Author: %(author)s
-Last-Changed-Email: %(email)s
-Last-Changed-Remote-Host: %(REMOTE_HOST)s
-Last-Changed-Remote-Address: %(REMOTE_ADDR)s
-
-%(log)s
-"""
-
-COMMITTED = """
-Your changes have been committed.
-"""
-
-COMMITFAILED = """
-Exit status %(sts)s.
-"""
-
-# Add/Delete
-
-ADD_HEAD = """
-At the moment, new entries can only be added at the end of a section.
-This is because the entry numbers are also their
-unique identifiers -- it's a bad idea to renumber entries.
-<P>
-Click on the section to which you want to add a new entry:
-<UL>
-"""
-
-ADD_SECTION = """\
-<LI><A HREF="%(FAQCGI)s?req=new&amp;section=%(section)s">%(section)s. %(title)s</A>
-"""
-
-ADD_TAIL = """
-</UL>
-"""
-
-ROULETTE = """
-<P>Hit your browser's Reload button to play again.<P>
-"""
-
-DELETE = """
-At the moment, there's no direct way to delete entries.
-This is because the entry numbers are also their
-unique identifiers -- it's a bad idea to renumber entries.
-<P>
-If you really think an entry needs to be deleted,
-change the title to "(deleted)" and make the body
-empty (keep the entry number in the title though).
-"""
-
-# Help file for the FAQ Edit Wizard
-
-HELP = """
-Using the %(FAQNAME)s Edit Wizard speaks mostly for itself. Here are
-some answers to questions you are likely to ask:
-
-<P><HR>
-
-<H2>I can review an entry but I can't commit it.</H2>
-
-The commit button only appears if the following conditions are met:
-
-<UL>
-
-<LI>The Name field is not empty.
-
-<LI>The Email field contains at least an @ character.
-
-<LI>The Log message box is not empty.
-
-<LI>The Password field contains the proper password.
-
-</UL>
-
-<P><HR>
-
-<H2>What is the password?</H2>
-
-At the moment, only PSA members will be told the password. This is a
-good time to join the PSA! See <A
-HREF="http://www.python.org/psa/">the PSA home page</A>.
-
-<P><HR>
-
-<H2>Can I use HTML in the FAQ entry?</H2>
-
-Yes, if you include it in &lt;HTML&rt; and &lt;/HTML&gt; tags.
-<P>
-Also, if you include a URL or an email address in the text it will
-automatigally become an anchor of the right type. Also, *word*
-is made italic (but only for single alphabetic words).
-
-<P><HR>
-
-<H2>How do I delineate paragraphs?</H2>
-
-Use blank lines to separate paragraphs.
-
-<P><HR>
-
-<H2>How do I enter example text?</H2>
-
-Any line that begins with a space or tab is assumed to be part of
-literal text. Blocks of literal text delineated by blank lines are
-placed inside &lt;PRE&gt;...&lt;/PRE&gt;.
-"""
-
-# Load local customizations again, in case they set some other variables
-
-try:
- from faqcust import *
-except ImportError:
- pass
diff --git a/Tools/faqwiz/faqcust.py b/Tools/faqwiz/faqcust.py
deleted file mode 100644
index 8f16781..0000000
--- a/Tools/faqwiz/faqcust.py
+++ /dev/null
@@ -1 +0,0 @@
-# Add your customizations here -- modified copies of what's in faqconf.py.
diff --git a/Tools/faqwiz/faqw.py b/Tools/faqwiz/faqw.py
deleted file mode 100755
index 01536c0..0000000
--- a/Tools/faqwiz/faqw.py
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/usr/bin/env python3
-
-"""FAQ wizard bootstrap."""
-
-# This is a longer version of the bootstrap script given at the end of
-# faqwin.py; it prints timing statistics at the end of the regular CGI
-# script's output (so you can monitor how it is doing).
-
-# This script should be placed in your cgi-bin directory and made
-# executable.
-
-# You need to edit the first line and the lines that define FAQDIR and
-# SRCDIR, below: change /usr/local/bin/python to where your Python
-# interpreter lives, change the value for FAQDIR to where your FAQ
-# lives, and change the value for SRCDIR to where your faqwiz.py
-# module lives. The faqconf.py and faqcust.py files live there, too.
-
-import os
-t1 = os.times() # If this doesn't work, just get rid of the timing code!
-try:
- FAQDIR = "/usr/people/guido/python/FAQ"
- SRCDIR = "/usr/people/guido/python/src/Tools/faqwiz"
- import os, sys
- os.chdir(FAQDIR)
- sys.path.insert(0, SRCDIR)
- import faqwiz
-except SystemExit as n:
- sys.exit(n)
-except:
- t, v, tb = sys.exc_info()
- print()
- import cgi
- cgi.print_exception(t, v, tb)
diff --git a/Tools/faqwiz/faqwiz.py b/Tools/faqwiz/faqwiz.py
deleted file mode 100644
index b9ab65d..0000000
--- a/Tools/faqwiz/faqwiz.py
+++ /dev/null
@@ -1,840 +0,0 @@
-"""Generic FAQ Wizard.
-
-This is a CGI program that maintains a user-editable FAQ. It uses RCS
-to keep track of changes to individual FAQ entries. It is fully
-configurable; everything you might want to change when using this
-program to maintain some other FAQ than the Python FAQ is contained in
-the configuration module, faqconf.py.
-
-Note that this is not an executable script; it's an importable module.
-The actual script to place in cgi-bin is faqw.py.
-
-"""
-
-import sys, time, os, stat, re, cgi, faqconf
-from faqconf import * # This imports all uppercase names
-now = time.time()
-
-class FileError:
- def __init__(self, file):
- self.file = file
-
-class InvalidFile(FileError):
- pass
-
-class NoSuchSection(FileError):
- def __init__(self, section):
- FileError.__init__(self, NEWFILENAME %(section, 1))
- self.section = section
-
-class NoSuchFile(FileError):
- def __init__(self, file, why=None):
- FileError.__init__(self, file)
- self.why = why
-
-def escape(s):
- s = s.replace('&', '&amp;')
- s = s.replace('<', '&lt;')
- s = s.replace('>', '&gt;')
- return s
-
-def escapeq(s):
- s = escape(s)
- s = s.replace('"', '&quot;')
- return s
-
-def _interpolate(format, args, kw):
- try:
- quote = kw['_quote']
- except KeyError:
- quote = 1
- d = (kw,) + args + (faqconf.__dict__,)
- m = MagicDict(d, quote)
- return format % m
-
-def interpolate(format, *args, **kw):
- return _interpolate(format, args, kw)
-
-def emit(format, *args, **kw):
- try:
- f = kw['_file']
- except KeyError:
- f = sys.stdout
- f.write(_interpolate(format, args, kw))
-
-translate_prog = None
-
-def translate(text, pre=0):
- global translate_prog
- if not translate_prog:
- translate_prog = prog = re.compile(
- r'\b(http|ftp|https)://\S+(\b|/)|\b[-.\w]+@[-.\w]+')
- else:
- prog = translate_prog
- i = 0
- list = []
- while 1:
- m = prog.search(text, i)
- if not m:
- break
- j = m.start()
- list.append(escape(text[i:j]))
- i = j
- url = m.group(0)
- while url[-1] in '();:,.?\'"<>':
- url = url[:-1]
- i = i + len(url)
- url = escape(url)
- if not pre or (pre and PROCESS_PREFORMAT):
- if ':' in url:
- repl = '<A HREF="%s">%s</A>' % (url, url)
- else:
- repl = '<A HREF="mailto:%s">%s</A>' % (url, url)
- else:
- repl = url
- list.append(repl)
- j = len(text)
- list.append(escape(text[i:j]))
- return ''.join(list)
-
-def emphasize(line):
- return re.sub(r'\*([a-zA-Z]+)\*', r'<I>\1</I>', line)
-
-revparse_prog = None
-
-def revparse(rev):
- global revparse_prog
- if not revparse_prog:
- revparse_prog = re.compile(r'^(\d{1,3})\.(\d{1,4})$')
- m = revparse_prog.match(rev)
- if not m:
- return None
- [major, minor] = map(int, m.group(1, 2))
- return major, minor
-
-logon = 0
-def log(text):
- if logon:
- logfile = open("logfile", "a")
- logfile.write(text + "\n")
- logfile.close()
-
-def load_cookies():
- if 'HTTP_COOKIE' not in os.environ:
- return {}
- raw = os.environ['HTTP_COOKIE']
- words = [s.strip() for s in raw.split(';')]
- cookies = {}
- for word in words:
- i = word.find('=')
- if i >= 0:
- key, value = word[:i], word[i+1:]
- cookies[key] = value
- return cookies
-
-def load_my_cookie():
- cookies = load_cookies()
- try:
- value = cookies[COOKIE_NAME]
- except KeyError:
- return {}
- import urllib.parse
- value = urllib.parse.unquote(value)
- words = value.split('/')
- while len(words) < 3:
- words.append('')
- author = '/'.join(words[:-2])
- email = words[-2]
- password = words[-1]
- return {'author': author,
- 'email': email,
- 'password': password}
-
-def send_my_cookie(ui):
- name = COOKIE_NAME
- value = "%s/%s/%s" % (ui.author, ui.email, ui.password)
- import urllib.parse
- value = urllib.parse.quote(value)
- then = now + COOKIE_LIFETIME
- gmt = time.gmtime(then)
- path = os.environ.get('SCRIPT_NAME', '/cgi-bin/')
- print("Set-Cookie: %s=%s; path=%s;" % (name, value, path), end=' ')
- print(time.strftime("expires=%a, %d-%b-%y %X GMT", gmt))
-
-class MagicDict:
-
- def __init__(self, d, quote):
- self.__d = d
- self.__quote = quote
-
- def __getitem__(self, key):
- for d in self.__d:
- try:
- value = d[key]
- if value:
- value = str(value)
- if self.__quote:
- value = escapeq(value)
- return value
- except KeyError:
- pass
- return ''
-
-class UserInput:
-
- def __init__(self):
- self.__form = cgi.FieldStorage()
- #log("\n\nbody: " + self.body)
-
- def __getattr__(self, name):
- if name[0] == '_':
- raise AttributeError
- try:
- value = self.__form[name].value
- except (TypeError, KeyError):
- value = ''
- else:
- value = value.strip()
- setattr(self, name, value)
- return value
-
- def __getitem__(self, key):
- return getattr(self, key)
-
-class FaqEntry:
-
- def __init__(self, fp, file, sec_num):
- self.file = file
- self.sec, self.num = sec_num
- if fp:
- import email
- self.__headers = email.message_from_file(fp)
- self.body = fp.read().strip()
- else:
- self.__headers = {'title': "%d.%d. " % sec_num}
- self.body = ''
-
- def __getattr__(self, name):
- if name[0] == '_':
- raise AttributeError
- key = '-'.join(name.split('_'))
- try:
- value = self.__headers[key]
- except KeyError:
- value = ''
- setattr(self, name, value)
- return value
-
- def __getitem__(self, key):
- return getattr(self, key)
-
- def load_version(self):
- command = interpolate(SH_RLOG_H, self)
- p = os.popen(command)
- version = ''
- while 1:
- line = p.readline()
- if not line:
- break
- if line[:5] == 'head:':
- version = line[5:].strip()
- p.close()
- self.version = version
-
- def getmtime(self):
- if not self.last_changed_date:
- return 0
- try:
- return os.stat(self.file)[stat.ST_MTIME]
- except os.error:
- return 0
-
- def emit_marks(self):
- mtime = self.getmtime()
- if mtime >= now - DT_VERY_RECENT:
- emit(MARK_VERY_RECENT, self)
- elif mtime >= now - DT_RECENT:
- emit(MARK_RECENT, self)
-
- def show(self, edit=1):
- emit(ENTRY_HEADER1, self)
- self.emit_marks()
- emit(ENTRY_HEADER2, self)
- pre = 0
- raw = 0
- for line in self.body.split('\n'):
- # Allow the user to insert raw html into a FAQ answer
- # (Skip Montanaro, with changes by Guido)
- tag = line.rstrip().lower()
- if tag == '<html>':
- raw = 1
- continue
- if tag == '</html>':
- raw = 0
- continue
- if raw:
- print(line)
- continue
- if not line.strip():
- if pre:
- print('</PRE>')
- pre = 0
- else:
- print('<P>')
- else:
- if not line[0].isspace():
- if pre:
- print('</PRE>')
- pre = 0
- else:
- if not pre:
- print('<PRE>')
- pre = 1
- if '/' in line or '@' in line:
- line = translate(line, pre)
- elif '<' in line or '&' in line:
- line = escape(line)
- if not pre and '*' in line:
- line = emphasize(line)
- print(line)
- if pre:
- print('</PRE>')
- pre = 0
- if edit:
- print('<P>')
- emit(ENTRY_FOOTER, self)
- if self.last_changed_date:
- emit(ENTRY_LOGINFO, self)
- print('<P>')
-
-class FaqDir:
-
- entryclass = FaqEntry
-
- __okprog = re.compile(OKFILENAME)
-
- def __init__(self, dir=os.curdir):
- self.__dir = dir
- self.__files = None
-
- def __fill(self):
- if self.__files is not None:
- return
- self.__files = files = []
- okprog = self.__okprog
- for file in os.listdir(self.__dir):
- if self.__okprog.match(file):
- files.append(file)
- files.sort()
-
- def good(self, file):
- return self.__okprog.match(file)
-
- def parse(self, file):
- m = self.good(file)
- if not m:
- return None
- sec, num = m.group(1, 2)
- return int(sec), int(num)
-
- def list(self):
- # XXX Caller shouldn't modify result
- self.__fill()
- return self.__files
-
- def open(self, file):
- sec_num = self.parse(file)
- if not sec_num:
- raise InvalidFile(file)
- try:
- fp = open(file)
- except IOError as msg:
- raise NoSuchFile(file, msg)
- try:
- return self.entryclass(fp, file, sec_num)
- finally:
- fp.close()
-
- def show(self, file, edit=1):
- self.open(file).show(edit=edit)
-
- def new(self, section):
- if section not in SECTION_TITLES:
- raise NoSuchSection(section)
- maxnum = 0
- for file in self.list():
- sec, num = self.parse(file)
- if sec == section:
- maxnum = max(maxnum, num)
- sec_num = (section, maxnum+1)
- file = NEWFILENAME % sec_num
- return self.entryclass(None, file, sec_num)
-
-class FaqWizard:
-
- def __init__(self):
- self.ui = UserInput()
- self.dir = FaqDir()
-
- def go(self):
- print('Content-type: text/html')
- req = self.ui.req or 'home'
- mname = 'do_%s' % req
- try:
- meth = getattr(self, mname)
- except AttributeError:
- self.error("Bad request type %r." % (req,))
- else:
- try:
- meth()
- except InvalidFile as exc:
- self.error("Invalid entry file name %s" % exc.file)
- except NoSuchFile as exc:
- self.error("No entry with file name %s" % exc.file)
- except NoSuchSection as exc:
- self.error("No section number %s" % exc.section)
- self.epilogue()
-
- def error(self, message, **kw):
- self.prologue(T_ERROR)
- emit(message, kw)
-
- def prologue(self, title, entry=None, **kw):
- emit(PROLOGUE, entry, kwdict=kw, title=escape(title))
-
- def epilogue(self):
- emit(EPILOGUE)
-
- def do_home(self):
- self.prologue(T_HOME)
- emit(HOME)
-
- def do_debug(self):
- self.prologue("FAQ Wizard Debugging")
- form = cgi.FieldStorage()
- cgi.print_form(form)
- cgi.print_environ(os.environ)
- cgi.print_directory()
- cgi.print_arguments()
-
- def do_search(self):
- query = self.ui.query
- if not query:
- self.error("Empty query string!")
- return
- if self.ui.querytype == 'simple':
- query = re.escape(query)
- queries = [query]
- elif self.ui.querytype in ('anykeywords', 'allkeywords'):
- words = [_f for _f in re.split('\W+', query) if _f]
- if not words:
- self.error("No keywords specified!")
- return
- words = [r'\b%s\b' % w for w in words]
- if self.ui.querytype[:3] == 'any':
- queries = ['|'.join(words)]
- else:
- # Each of the individual queries must match
- queries = words
- else:
- # Default to regular expression
- queries = [query]
- self.prologue(T_SEARCH)
- progs = []
- for query in queries:
- if self.ui.casefold == 'no':
- p = re.compile(query)
- else:
- p = re.compile(query, re.IGNORECASE)
- progs.append(p)
- hits = []
- for file in self.dir.list():
- try:
- entry = self.dir.open(file)
- except FileError:
- constants
- for p in progs:
- if not p.search(entry.title) and not p.search(entry.body):
- break
- else:
- hits.append(file)
- if not hits:
- emit(NO_HITS, self.ui, count=0)
- elif len(hits) <= MAXHITS:
- if len(hits) == 1:
- emit(ONE_HIT, count=1)
- else:
- emit(FEW_HITS, count=len(hits))
- self.format_all(hits, headers=0)
- else:
- emit(MANY_HITS, count=len(hits))
- self.format_index(hits)
-
- def do_all(self):
- self.prologue(T_ALL)
- files = self.dir.list()
- self.last_changed(files)
- self.format_index(files, localrefs=1)
- self.format_all(files)
-
- def do_compat(self):
- files = self.dir.list()
- emit(COMPAT)
- self.last_changed(files)
- self.format_index(files, localrefs=1)
- self.format_all(files, edit=0)
- sys.exit(0) # XXX Hack to suppress epilogue
-
- def last_changed(self, files):
- latest = 0
- for file in files:
- entry = self.dir.open(file)
- if entry:
- mtime = mtime = entry.getmtime()
- if mtime > latest:
- latest = mtime
- print(time.strftime(LAST_CHANGED, time.localtime(latest)))
- emit(EXPLAIN_MARKS)
-
- def format_all(self, files, edit=1, headers=1):
- sec = 0
- for file in files:
- try:
- entry = self.dir.open(file)
- except NoSuchFile:
- continue
- if headers and entry.sec != sec:
- sec = entry.sec
- try:
- title = SECTION_TITLES[sec]
- except KeyError:
- title = "Untitled"
- emit("\n<HR>\n<H1>%(sec)s. %(title)s</H1>\n",
- sec=sec, title=title)
- entry.show(edit=edit)
-
- def do_index(self):
- self.prologue(T_INDEX)
- files = self.dir.list()
- self.last_changed(files)
- self.format_index(files, add=1)
-
- def format_index(self, files, add=0, localrefs=0):
- sec = 0
- for file in files:
- try:
- entry = self.dir.open(file)
- except NoSuchFile:
- continue
- if entry.sec != sec:
- if sec:
- if add:
- emit(INDEX_ADDSECTION, sec=sec)
- emit(INDEX_ENDSECTION, sec=sec)
- sec = entry.sec
- try:
- title = SECTION_TITLES[sec]
- except KeyError:
- title = "Untitled"
- emit(INDEX_SECTION, sec=sec, title=title)
- if localrefs:
- emit(LOCAL_ENTRY, entry)
- else:
- emit(INDEX_ENTRY, entry)
- entry.emit_marks()
- if sec:
- if add:
- emit(INDEX_ADDSECTION, sec=sec)
- emit(INDEX_ENDSECTION, sec=sec)
-
- def do_recent(self):
- if not self.ui.days:
- days = 1
- else:
- days = float(self.ui.days)
- try:
- cutoff = now - days * 24 * 3600
- except OverflowError:
- cutoff = 0
- list = []
- for file in self.dir.list():
- entry = self.dir.open(file)
- if not entry:
- continue
- mtime = entry.getmtime()
- if mtime >= cutoff:
- list.append((mtime, file))
- list.sort()
- list.reverse()
- self.prologue(T_RECENT)
- if days <= 1:
- period = "%.2g hours" % (days*24)
- else:
- period = "%.6g days" % days
- if not list:
- emit(NO_RECENT, period=period)
- elif len(list) == 1:
- emit(ONE_RECENT, period=period)
- else:
- emit(SOME_RECENT, period=period, count=len(list))
- self.format_all([mtime_file[1] for mtime_file in list], headers=0)
- emit(TAIL_RECENT)
-
- def do_roulette(self):
- import random
- files = self.dir.list()
- if not files:
- self.error("No entries.")
- return
- file = random.choice(files)
- self.prologue(T_ROULETTE)
- emit(ROULETTE)
- self.dir.show(file)
-
- def do_help(self):
- self.prologue(T_HELP)
- emit(HELP)
-
- def do_show(self):
- entry = self.dir.open(self.ui.file)
- self.prologue(T_SHOW)
- entry.show()
-
- def do_add(self):
- self.prologue(T_ADD)
- emit(ADD_HEAD)
- sections = sorted(SECTION_TITLES.items())
- for section, title in sections:
- emit(ADD_SECTION, section=section, title=title)
- emit(ADD_TAIL)
-
- def do_delete(self):
- self.prologue(T_DELETE)
- emit(DELETE)
-
- def do_log(self):
- entry = self.dir.open(self.ui.file)
- self.prologue(T_LOG, entry)
- emit(LOG, entry)
- self.rlog(interpolate(SH_RLOG, entry), entry)
-
- def rlog(self, command, entry=None):
- output = os.popen(command).read()
- sys.stdout.write('<PRE>')
- athead = 0
- lines = output.split('\n')
- while lines and not lines[-1]:
- del lines[-1]
- if lines:
- line = lines[-1]
- if line[:1] == '=' and len(line) >= 40 and \
- line == line[0]*len(line):
- del lines[-1]
- headrev = None
- for line in lines:
- if entry and athead and line[:9] == 'revision ':
- rev = line[9:].split()
- mami = revparse(rev)
- if not mami:
- print(line)
- else:
- emit(REVISIONLINK, entry, rev=rev, line=line)
- if mami[1] > 1:
- prev = "%d.%d" % (mami[0], mami[1]-1)
- emit(DIFFLINK, entry, prev=prev, rev=rev)
- if headrev:
- emit(DIFFLINK, entry, prev=rev, rev=headrev)
- else:
- headrev = rev
- print()
- athead = 0
- else:
- athead = 0
- if line[:1] == '-' and len(line) >= 20 and \
- line == len(line) * line[0]:
- athead = 1
- sys.stdout.write('<HR>')
- else:
- print(line)
- print('</PRE>')
-
- def do_revision(self):
- entry = self.dir.open(self.ui.file)
- rev = self.ui.rev
- mami = revparse(rev)
- if not mami:
- self.error("Invalid revision number: %r." % (rev,))
- self.prologue(T_REVISION, entry)
- self.shell(interpolate(SH_REVISION, entry, rev=rev))
-
- def do_diff(self):
- entry = self.dir.open(self.ui.file)
- prev = self.ui.prev
- rev = self.ui.rev
- mami = revparse(rev)
- if not mami:
- self.error("Invalid revision number: %r." % (rev,))
- if prev:
- if not revparse(prev):
- self.error("Invalid previous revision number: %r." % (prev,))
- else:
- prev = '%d.%d' % (mami[0], mami[1])
- self.prologue(T_DIFF, entry)
- self.shell(interpolate(SH_RDIFF, entry, rev=rev, prev=prev))
-
- def shell(self, command):
- output = os.popen(command).read()
- sys.stdout.write('<PRE>')
- print(escape(output))
- print('</PRE>')
-
- def do_new(self):
- entry = self.dir.new(section=int(self.ui.section))
- entry.version = '*new*'
- self.prologue(T_EDIT)
- emit(EDITHEAD)
- emit(EDITFORM1, entry, editversion=entry.version)
- emit(EDITFORM2, entry, load_my_cookie())
- emit(EDITFORM3)
- entry.show(edit=0)
-
- def do_edit(self):
- entry = self.dir.open(self.ui.file)
- entry.load_version()
- self.prologue(T_EDIT)
- emit(EDITHEAD)
- emit(EDITFORM1, entry, editversion=entry.version)
- emit(EDITFORM2, entry, load_my_cookie())
- emit(EDITFORM3)
- entry.show(edit=0)
-
- def do_review(self):
- send_my_cookie(self.ui)
- if self.ui.editversion == '*new*':
- sec, num = self.dir.parse(self.ui.file)
- entry = self.dir.new(section=sec)
- entry.version = "*new*"
- if entry.file != self.ui.file:
- self.error("Commit version conflict!")
- emit(NEWCONFLICT, self.ui, sec=sec, num=num)
- return
- else:
- entry = self.dir.open(self.ui.file)
- entry.load_version()
- # Check that the FAQ entry number didn't change
- if self.ui.title.split()[:1] != entry.title.split()[:1]:
- self.error("Don't change the entry number please!")
- return
- # Check that the edited version is the current version
- if entry.version != self.ui.editversion:
- self.error("Commit version conflict!")
- emit(VERSIONCONFLICT, entry, self.ui)
- return
- commit_ok = ((not PASSWORD
- or self.ui.password == PASSWORD)
- and self.ui.author
- and '@' in self.ui.email
- and self.ui.log)
- if self.ui.commit:
- if not commit_ok:
- self.cantcommit()
- else:
- self.commit(entry)
- return
- self.prologue(T_REVIEW)
- emit(REVIEWHEAD)
- entry.body = self.ui.body
- entry.title = self.ui.title
- entry.show(edit=0)
- emit(EDITFORM1, self.ui, entry)
- if commit_ok:
- emit(COMMIT)
- else:
- emit(NOCOMMIT_HEAD)
- self.errordetail()
- emit(NOCOMMIT_TAIL)
- emit(EDITFORM2, self.ui, entry, load_my_cookie())
- emit(EDITFORM3)
-
- def cantcommit(self):
- self.prologue(T_CANTCOMMIT)
- print(CANTCOMMIT_HEAD)
- self.errordetail()
- print(CANTCOMMIT_TAIL)
-
- def errordetail(self):
- if PASSWORD and self.ui.password != PASSWORD:
- emit(NEED_PASSWD)
- if not self.ui.log:
- emit(NEED_LOG)
- if not self.ui.author:
- emit(NEED_AUTHOR)
- if not self.ui.email:
- emit(NEED_EMAIL)
-
- def commit(self, entry):
- file = entry.file
- # Normalize line endings in body
- if '\r' in self.ui.body:
- self.ui.body = re.sub('\r\n?', '\n', self.ui.body)
- # Normalize whitespace in title
- self.ui.title = ' '.join(self.ui.title.split())
- # Check that there were any changes
- if self.ui.body == entry.body and self.ui.title == entry.title:
- self.error("You didn't make any changes!")
- return
-
- # need to lock here because otherwise the file exists and is not writable (on NT)
- command = interpolate(SH_LOCK, file=file)
- p = os.popen(command)
- output = p.read()
-
- try:
- os.unlink(file)
- except os.error:
- pass
- try:
- f = open(file, 'w')
- except IOError as why:
- self.error(CANTWRITE, file=file, why=why)
- return
- date = time.ctime(now)
- emit(FILEHEADER, self.ui, os.environ, date=date, _file=f, _quote=0)
- f.write('\n')
- f.write(self.ui.body)
- f.write('\n')
- f.close()
-
- import tempfile
- tf = tempfile.NamedTemporaryFile()
- emit(LOGHEADER, self.ui, os.environ, date=date, _file=tf)
- tf.flush()
- tf.seek(0)
-
- command = interpolate(SH_CHECKIN, file=file, tfn=tf.name)
- log("\n\n" + command)
- p = os.popen(command)
- output = p.read()
- sts = p.close()
- log("output: " + output)
- log("done: " + str(sts))
- log("TempFile:\n" + tf.read() + "end")
-
- if not sts:
- self.prologue(T_COMMITTED)
- emit(COMMITTED)
- else:
- self.error(T_COMMITFAILED)
- emit(COMMITFAILED, sts=sts)
- print('<PRE>%s</PRE>' % escape(output))
-
- try:
- os.unlink(tf.name)
- except os.error:
- pass
-
- entry = self.dir.open(file)
- entry.show()
-
-wiz = FaqWizard()
-wiz.go()
diff --git a/Tools/faqwiz/move-faqwiz.sh b/Tools/faqwiz/move-faqwiz.sh
deleted file mode 100755
index b3bcc92..0000000
--- a/Tools/faqwiz/move-faqwiz.sh
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/bin/sh
-#
-# Christian Reis <kiko@async.com.br>
-#
-# Moves
-#
-# Example:
-#
-# blackjesus:~> ./move-faqwiz.sh 2\.1 3\.2
-# Moving FAQ question 02.001 to 03.002
-
-if [ x$2 = x ]; then
- echo "Need 2 args: original_version final_version."
- exit 2
-fi
-
-if [ ! -d data -o ! -d data/RCS ]; then
- echo "Run this inside the faqwiz data/ directory's parent dir."
- exit 2
-fi
-
-cut_n_pad() {
- t=`echo $1 | cut -d. -f $2`
- export $3=`echo $t | awk "{ tmp = \\$0; l = length(tmp); for (i = 0; i < $2-l+1; i++) { tmp = "0".tmp } print tmp }"`
-}
-
-cut_n_pad $1 1 prefix1
-cut_n_pad $1 2 suffix1
-cut_n_pad $2 1 prefix2
-cut_n_pad $2 2 suffix2
-if which tempfile >/dev/null; then
- tmpfile=$(tempfile -d .)
-elif [ -n "$RANDOM" ]; then
- tmpfile=tmp$RANDOM.tmp
-else
- tmpfile=tmp$$.tmp
-fi
-file1=faq$prefix1.$suffix1.htp
-file2=faq$prefix2.$suffix2.htp
-
-echo "Moving FAQ question $prefix1.$suffix1 to $prefix2.$suffix2"
-
-sed -e "s/$1\./$2\./g" data/$file1 > ${tmpfile}1
-sed -e "s/$1\./$2\./g" data/RCS/$file1,v > ${tmpfile}2
-
-if [ -f data/$file2 ]; then
- echo "Target FAQ exists. Won't clobber."
- exit 2
-fi
-
-mv ${tmpfile}1 data/$file2
-mv ${tmpfile}2 data/RCS/$file2,v
-mv data/$file1 data/$file1.orig
-mv data/RCS/$file1,v data/RCS/$file1,v.orig
-