#!/usr/bin/env python3 # -*- coding: utf-8 -*- """Build IPv6 RFC bibliography""" # Version: 2023-05-23 - original # Version: 2023-07-29 - check age of index # Version: 2023-07-31 - added STD/BCP numbers; # caught more RFCs; cosmetics # Version: 2023-08-01 - catch by WG acronym ######################################################## # Copyright (C) 2023 Brian E. Carpenter. # All rights reserved. # # Redistribution and use in source and binary forms, with # or without modification, are permitted provided that the # following conditions are met: # # 1. Redistributions of source code must retain the above # copyright notice, this list of conditions and the following # disclaimer. # # 2. Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials # provided with the distribution. # # 3. Neither the name of the copyright holder nor the names of # its contributors may be used to endorse or promote products # derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS # AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL # THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # ######################################################## from tkinter import Tk from tkinter.filedialog import askdirectory from tkinter.messagebox import askokcancel, askyesno, showinfo import time import os def logit(msg): """Add a message to the log file""" global flog, printing flog.write(msg+"\n") if printing: print(msg) def logitw(msg): """Add a warning message to the log file""" global warnings logit("WARNING: "+msg) warnings += 1 def dprint(*msg): """ Diagnostic print """ global printing if printing: print(*msg) def crash(msg): """Log and crash""" printing = True logit("CRASH "+msg) flog.close() exit() def rf(f): """Return a file as a list of strings""" file = open(f, "r",encoding='utf-8', errors='replace') l = file.readlines() file.close() #ensure last line has a newline if l[-1][-1] != "\n": l[-1] += "\n" return l def wf(f,l): """Write list of strings to file""" file = open(f, "w",encoding='utf-8') for line in l: file.write(line+"\n") file.close() logit("'"+f+"' written") def field(fname, block): """Extract named field from XML block""" if fname in block: _,temp = block.split("<"+fname+">", maxsplit=1) result,_ = temp.split("", maxsplit=1) return result return "" def title(block): """Extract title from XML block""" return field("title", block) def doc_id(block): """Extract doc-id from XML block""" return field("doc-id", block) def interesting(block): """Save interesting RFC data from XML block""" global stds, bcps, infos, exps if "UNKNOWN" in block: return None elif "HISTORIC" in block: return False elif "" in block: return False elif "IPv6" in title(block) or "IP Version 6" in title(block) or (field("wg_acronym", block) in wgs): #print(block) status = field("current-status", block) if "is-also" in block: also,_ = field("is-also", block).split("")[1].split(" 60*60*24*30: logitw("rfc-index.xml is >30 days old") whole = rf(path) except: try: if askyesno(title=T, message = "OK to download RFC index?/n(15 MB temp file)"): import urllib.request urllib.request.urlretrieve("http://www.rfc-editor.org/rfc/rfc-index.xml", "tempRx.xml") whole = rf("tempRx.xml") os.remove("tempRx.xml") else: crash("Cannot run without RFC index") except: crash("rfc-index.xml not found") timestamp = time.strftime("%Y-%m-%d %H:%M:%S UTC%z",time.localtime()) for line in whole: #print(line) if (not inrfc) and (not "" in line): continue inrfc = True new += line if inrfc and "" in line: #end of an rfc entry if interesting(new): count += 1 inrfc = False numberfound = False new = '' continue logit(str(count)+" IPv6 RFCs found") if len(stds)+len(bcps)+len(infos)+len(exps) != count: logitw("Warning: count mismatch") md = ["## RFC bibliography","", """This section is a machine-generated list of all current RFCs that mention IPv6 in their title or come from the major IPv6 working groups. Obsolete RFCs are not included. There are subsections for Standards, BCPs, Informational and Experimental RFCs. Be *cautious* about old Informational or Experimental RFCs - they may be misleading as well as out of date."""] md += ["","RFCbib6 run at "+timestamp] md += ["","### Standards Track",""] md += stds md += ["", "### Best Current Practice", ""] md += bcps md += ["", "### Informational", ""] md += infos md += ["", "### Experimental", ""] md += exps md += ["", "", "### [Chapter Contents](20.%20Further%20Reading.md)"] wf("20. Further Reading/RFC bibliography.md", md) ######### Close log and exit flog.close() if warnings: warn = str(warnings)+" warning(s)\n" else: warn = "" showinfo(title=T, message = warn+"Check RFCbib6.log, then run makeBook.")