Package: releaselogparser
Release Log ParserSoftware packages usually include textual files describing noteworthy
changes in each subsequent release. There exist several variants (or
formats) of such files.This package provides Python framework for parsing the most often used
formats of such release log files. Support for any new format can be
easily added.Release LogsRelease Logis a textual file included in a software package, which
contains descriptions of existing releases of the package. Such a
file is normally included in each distributed archive of the package
and is present in its VCS repository.Little or no effort has been invested into standartization of release
log formats. There exists a plethora of variations which differ more
or less considerably. The choice of a particular variation for a given
package depends mostly on the language this package is written in and
the distribution system adopted for this package. Authors’ preferences
play certain role as well.Despite the diversity of release log formats, similarities between
them overnumber their differences. The following observations hold true:Release logs are plaintext files.Within a file, each release is described by a separate entry.Each such entry consists of a heading, containing at least the
version number and date of the release, and a textual block discussing
the changes introduced with this release.Entries are arranged in reverse chronological order, the most
recent release being described first.Format of the headings is consistent throughout the given release
log.Entry description is usually a list of changes. However, more
verbose and general descriptions may also appear within it. In
general, it is safest to assume the description to be an opaque block
of arbitrary text.Release logs can contain additional textual information before the
first release entry (a “prologue”) and after the last release entry
(an “epilogue”).Supported FormatsMost frequently used release log formats can be grouped into three
main families:GNU-stylerelease logsThese are normally used by GNU software. Such log files are usually named
“NEWS”. Example heading lines are:version 1.30 - Sergey Poznyakoff, 2017-12-17
Version 1.18 - 2018-08-21
* Version 4.2, 2014-05-23Perl-stylerelease logsThese are the “Changes” files included in each Perl package
distributed via CPAN. Example heading lines:2.00 2018-03-08
1.01 Sat Jul  7 19:11:35 2018Python packagerelease logsThe “CHANGES.txt” files found in many Python packages. Example heading
lines:v2.0.1, 2014/12/14 – Update token generator
2.7 (23 June 2018)The special feature of the first heading variant is that the first
line of the changeset description follows the heading on the same
physical line. Quite often this is the only line in the description.UsageTheReleaseLogclass is a fabric returning actual release history
implementation, depending on the first argument to its constructor.
Typical usage:rl = ReleaseLog('GNU', content, count=1)The two mandatory arguments are the format name and the list of lines
obtained from the release log file.Valid format names for this version ofreleaselogparserare:GNU,NEWSGNU-style news file.CPAN,ChangesPerl-style release log.Python,pythonPython-style release log.Supported keyword arguments are:start =NStart parsing from the entryN. Entries are numbered from 0.stop =NStop parsing on the entryN.count =NCollect at mostNentriesIf all three keywords are given, the actual range of history entries
is computed as[start, min(start+count, stop)]Two derived classes are provided that read input data from various
sources:classReleaseLogFileTheReleaseLogFileclass reads release log from the file:rl = ReleaseLogFile(fmt, file [, kwargs...])Here,fmtis the name of the format,fileis the name of the
input file, andkwargsare keyword arguments described above.classReleaseLogURLTheReleaseLogURLclass reads log entries from a URL:rl = ReleaseLogURL(fmt, url [, kwargs...])Acessing release informationThe returned object can be indexed to obtain particular log
entries. Indices start with 0, which corresponds to the most recent
entry, e.g.:entry = cl[0]Theentryis an object of classRelease, which has three
attributes:versionRelease version number.dateDate and time of the release (a datetime object)descrTextual description of the release - a list of lines.The obtained entry can be printed as string, e.g.:print(entry)The output format is as shown in the example below:Version 1.0, released at 2018-08-19 15:30:00ExampleThe following simple program reads release log entries from the fileNEWSand prints them on the standard output:from releaselogparser.input import ReleaseLogFile

for log in ReleaseLogFile('GNU', 'NEWS'):
    print(log)
    print('\n'.join(log.descr))Extending Release LogImplementing support for new release log format is fairly easy. To do
so, provide a class inherited fromReleaseHistory. This base class has
the following attributes:formatList of names for this format. Names from this list can be used
interchangeably to identify this log format, e.g. as a first
argument to theReleaseLogor derived constructor.filenameName of the file used normally for release logs in this format.headerCompiled regular expression that returns a match for
history entry heading lines. The expression must contain two named
groups:version, which returns part of the string corresponding
to the release version number, anddate, returning its
timestamp.If it contains a named grouprest, part of the header string
corresponding to this group will be added to thedescrlist of
the created history entry.end_of_entry_rxCompiled regular expression that matches end of entry. Can beNone, if not needed.The file with the definition of the inherited class must be placed in
the directoryreleaselogparser/formatreachable from the Python search path
for module files.The following example implements a simplified version of CHANGES.txt log
format:import re
from releaselogparser import ReleaseHistory

class ChangesLogFormat(ReleaseHistory):
    format = ['changes']
    filename = 'CHANGES.txt'
    header = re.compile("""^[vV](?P<version>\d[\d.]*)\s*
                        ,\s*
                        (?P<date>.*?)
                        \s+-+\s*
                        (?P<rest>.*)$
                        """, re.X)More sophisticated implementations can overload theparse_headermethod of the parent class. This method is defined as follows:def parse_header(self, line):If the inputlineis an entry header, the method should return
a triplet:(date, version, first_line)wheredateis textual representation of the date of the release,versionis the release version string, andfirst_lineis the
first line of the description (can be None).If the line is not a valid entry header, the method returns(None, None, None).ThereleaselogutilityThereleaselogtool reads release logs in various formats from a
given file or URL. Its usage is:releaselog [OPTIONS] FILE-or-URLThe argument is treated as file name by default. To read from a URL,
use the--urloption.Options:-HFORMAT,--format=FORMATRead logs in the given format.-fN,--from=N,--start=NStart fromNth entry.-tN,--to=N,--stop=NEnd onNth entry.-nCOUNT,--count=COUNTRead at most that much entries.-u,--urlTreat argument as URL-l,--listList supported formats--versionShow program version number and exit.-h,--helpShow a short help message and exit.