irclog2html-2.17.2/ 0000755 0001750 0001750 00000000000 13457570524 013075 5 ustar mg mg 0000000 0000000 irclog2html-2.17.2/.coveragerc 0000664 0001750 0001750 00000000272 13301516174 015206 0 ustar mg mg 0000000 0000000 [run]
source = irclog2html
[report]
omit = */tests/*,*/xchatlogsplit.py
exclude_lines =
pragma: nocover
except ImportError:
except NameError:
if __name__ == .__main__.:
irclog2html-2.17.2/appveyor.yml 0000664 0001750 0001750 00000000660 13457567511 015473 0 ustar mg mg 0000000 0000000 version: build-{build}-{branch}
environment:
matrix:
# https://www.appveyor.com/docs/installed-software#python lists available
# versions
- PYTHON: "C:\\Python27"
- PYTHON: "C:\\Python35"
- PYTHON: "C:\\Python36"
- PYTHON: "C:\\Python37"
init:
- "echo %PYTHON%"
install:
- "set PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
- python --version
- pip install tox
build: off
test_script:
- tox -e py
irclog2html-2.17.2/.travis.yml 0000664 0001750 0001750 00000000607 13457567510 015214 0 ustar mg mg 0000000 0000000 language: python
dist: xenial
python:
- 2.7
- 3.5
- 3.6
- 3.7
- pypy2.7-6.0.0
- pypy3.5-6.0.0
install:
- pip install zope.testrunner coverage coveralls zope.testing mock
- pip install -e .
script:
- coverage run --source=irclog2html -m zope.testrunner --test-path=src
after_script:
- coveralls
- coverage report -m
notifications:
email: false
irclog2html-2.17.2/PKG-INFO 0000644 0001750 0001750 00000036236 13457570524 014204 0 ustar mg mg 0000000 0000000 Metadata-Version: 2.1
Name: irclog2html
Version: 2.17.2
Summary: Convert IRC logs to HTML
Home-page: https://mg.pov.lt/irclog2html/
Author: Marius Gedminas
Author-email: marius@gedmin.as
License: GPL v2 or later
Description: ===========
irclog2html
===========
Converts IRC log files to HTML with pretty colours.
Quick start
===========
Installation::
pip install irclog2html
Quick usage for a single log file::
irclog2html --help
irclog2html filename.log (produces filename.log.html)
Mass-conversion of logs (one file per day, with YYYY-MM-DD in the filename)
with next/prev links, with mtime checks, usable from cron::
logs2html directory/ (looks for *.log and *.log.gz, produces *.log.html)
Configuration files
===================
Since you probably don't want to keep specifying the same options on the
command line every time you run logs2html, you can create a config file.
For example::
-t 'IRC logs for #mychannel'
-p 'IRC logs for #mychannel for '
# the following needs some extra Apache setup to enable the CGI/WSGI script
--searchbox
# where we keep the logs
/full/path/to/directory/
Use it like this::
logs2html -c /path/to/mychannel.conf
Lines starting with a ``#`` are ignored. Other lines are interpreted as
command-line options.
The order matters: options on the command line before the ``-c FILE`` will
be overriden by option in the config file. Options specified after ``-c FILE``
will override the options in the config file.
You can include more than one config file by repeating ``-c FILE``. You
can include config files from other config files. You can even create loops of
config files and then watch and laugh manically as logs2html sits there burning
your CPU.
CGI script for log searching
============================
.. warning::
The script can be easily abused to cause a denial of service attack; it
parses *all* log files every time you perform a search.
You can generate search boxes on IRC log pages by passing the ``--searchbox``
option to ``logs2html``. Here's an example Apache config snippet that makes
it work::
RewriteRule ^/my-irclog/search/$ /my-irclog/search [R,L]
ScriptAlias /my-irclog/search /usr/local/bin/irclogsearch
SetEnv IRCLOG_LOCATION "/var/www/my-irclog/"
# Uncomment the following if your log files use a different format
#SetEnv IRCLOG_GLOB "*.log.????-??-??"
# (this will also automatically handle *.log.????-??-??.gz)
WSGI script for log serving
===========================
.. warning::
The script can be easily abused to cause a denial of service attack; it
parses *all* log files every time you perform a search.
There's now an experimental WSGI script that can generate HTML for the
logs on the fly. You can use it if you don't like cron scripts and CGI.
Here's an example Apache config snippet::
WSGIScriptAlias /irclogs /usr/local/bin/irclogserver
SetEnv IRCLOG_LOCATION "/var/www/my-irclog/"
# Uncomment the following if your log files use a different format
#SetEnv IRCLOG_GLOB "*.log.????-??-??"
# (this will also automatically handle *.log.????-??-??.gz)
Currently it has certain downsides:
- configuration is very limited, e.g you cannot specify titles or styles
or enable dircproxy mode
- HTML files in the irc log directory will take precedence over
dynamically-generated logs even if they're older than the corresponding
log file (but on the plus side you can use that to have dynamic search
via WSGI, but keep statically-generated HTML files with your own config
tweaks)
WSGI script for multi-channel log serving
=========================================
.. warning::
The script can be easily abused to cause a denial of service attack; it
parses *all* log files every time you perform a search.
The experimental WSGI script can serve logs for multiple channels::
WSGIScriptAlias /irclogs /usr/local/bin/irclogserver
SetEnv IRCLOG_CHAN_DIR "/var/www/my-irclog/"
# Uncomment the following if your log files use a different format
#SetEnv IRCLOG_GLOB "*.log.????-??-??"
# (this will also automatically handle *.log.????-??-??.gz)
Now ``/irclogs`` will show a list of channels (subdirectories under
``/var/www/my-irclog/``), and ``/irclogs/channel/`` will show the
date index for that channel.
Misc
====
Website: https://mg.pov.lt/irclog2html/
Bug tracker:
https://github.com/mgedmin/irclog2html/issues
Licence: GPL v2 or later (https://www.gnu.org/copyleft/gpl.html)
|buildstatus|_ |appveyor|_ |coverage|_
.. |buildstatus| image:: https://api.travis-ci.org/mgedmin/irclog2html.svg?branch=master
.. _buildstatus: https://travis-ci.org/mgedmin/irclog2html
.. |appveyor| image:: https://ci.appveyor.com/api/projects/status/github/mgedmin/irclog2html?branch=master&svg=true
.. _appveyor: https://ci.appveyor.com/project/mgedmin/irclog2html
.. |coverage| image:: https://coveralls.io/repos/mgedmin/irclog2html/badge.svg?branch=master
.. _coverage: https://coveralls.io/r/mgedmin/irclog2html
Changelog
=========
2.17.2 (2019-04-23)
-------------------
- Drop support for Python 3.4.
2.17.1 (2018-11-25)
-------------------
- Add support for Python 3.7.
- Drop support for Python 3.3.
- Support ``python -m irclog2html`` as shortcut for
``python -m irclog2html.irclog2html``.
- Make irclogserver ignore hidden directories (such as .git).
2.17.0 (2018-02-21)
-------------------
- Support `ii `_ logs which use Unix
timestamps (https://github.com/mgedmin/irclog2html/pull/21).
Pull request by Cédric Krier.
2.16.0 (2017-12-20)
-------------------
- Support Python 3.6.
- Fix for duplicated lines with the same time where the resulting HTML ``id``
anchors would evolve into long form like "t22:24:49-2-3-4-5-6-7-8-9-10"
instead of "t22:24:49-10" resulting in significant output file size growth
in some cases.
- Add --output-dir (-o) parameter to logs2html so you can place the generated
HTML files in a directory different from the input directory.
2.15.3 (2016-12-08)
-------------------
- In some circumstances parts of a message up to the last '>' could be lost
(https://github.com/mgedmin/irclog2html/issues/19).
2.15.2 (2016-10-07)
-------------------
- ``irclogserver`` channel list is now split into old channels and active
channels, detected by checking whether the directory modification date
is newer or older than 7 days.
- 2nd-level headings now have the same color as 1st-level headings.
- ``irclogserver`` no longer shows a 404 if you omit the trailing ``/``
after a channel name in the URL.
2.15.1 (2016-09-25)
-------------------
- Lines with the same timestamp now get different HTML anchors
(https://github.com/mgedmin/irclog2html/issues/17). Thanks
to Bryan Bishop for the original pull request.
2.15.0 (2016-09-25)
-------------------
- There's a new ``irclogserver`` script that can be used to serve
dynamically-generated IRC logs and perform search. It can also be
deployed via WSGI. Portions contributed by Albertas Agejevas
(https://github.com/mgedmin/irclog2html/pull/9).
- Index pages group the logs by month
(https://github.com/mgedmin/irclog2html/issues/12).
- Drop support for Python 2.6.
2.14.0 (2014-12-12)
-------------------
- Add -o option to specify the output file name. Patch by Moises Silva
(https://github.com/mgedmin/irclog2html/pull/7).
2.13.1 (2014-02-01)
-------------------
- Add support for Windows (e.g. refrain from creating latest.log.html
symlinks).
2.13.0 (2013-12-18)
-------------------
- Handle gzipped files transparently
(https://github.com/mgedmin/irclog2html/issues/5).
2.12.1 (2013-03-22)
-------------------
* Fix AttributeError in irclogsearch on Python 2.7
(https://github.com/mgedmin/irclog2html/issues/1).
2.12.0 (2013-03-18)
-------------------
* Moved to Github.
* Add support for Python 3.3.
* Drop support for Python 2.4 and 2.5.
* Fix URL linkifier to not include trailing punctuation (LP#1155906).
2.11.1 (2013-03-17)
-------------------
* logs2html also accepts filenames that contain YYYYMMDD dates (in addition to
YYYY-MM-DD). Patch by Holger Just. Fixes LP#1031642.
2.11.0 (2012-07-30)
-------------------
* irclogsearch can be told about the filename pattern of log files via an
environment variable (IRCLOG_GLOB). Patch by Jonathan Kinred.
2.10.0 (2012-02-12)
-------------------
* New option: --glob-pattern. Patch by Albertas Agejevas.
Fixes LP#912310.
* Links in logs are marked with rel="nofollow". Patch by Matt Wheeler.
Fixes LP#914553.
* New option: --version.
* New option: -c, --config=FILE.
2.9.2 (2011-01-16)
------------------
* Support XChat Latin/Unicode hybrid encoding (http://xchat.org/encoding/).
Fixes LP#703622.
* irclog2html copies irclog.css file into the destination directory.
Fixes LP#608727.
2.9.1 (2010-08-06)
------------------
* Make sure irclog.css is installed in the right place; logs2html needs it.
2.9 (2010-08-06)
----------------
* Restructured source tree, made irclogs2html into a package, added setup.py,
buildout.cfg, bootstrap.py, Makefile, HACKING.txt; moved old porting test
suite into a subdirectory (porting).
* logs2html copies irclog.css file into the destination directory.
* Released into PyPI.
2.8 (2010-07-22)
----------------
* Added README.txt and CHANGES.txt.
* Support dircproxy log files (new date format: "[15 Jan 08:42]",
strip ident and IP address from nicknames). Patch by Paul Frields.
* New option: --dircproxy also makes irclog2html strip a single leading
'+' or '-' from messages.
2.7.1 (2009-04-30)
------------------
* Bug in logs2html.py error reporting, reported by Ondrej Baudys.
2.7 (2008-06-10)
----------------
* New style: mediawiki. Patch by Ian Weller.
2.6 (2007-10-30)
----------------
* Support another date format (Oct 17 10:53:26). Patch by Matthew Barnes.
2.5.1 (2007-03-22)
------------------
* logs2html.py: add a stable link to the latest log file
(suggested by Chris Foster).
2.5 (2007-01-22)
----------------
* New option: --searchbox.
* Search CGI script improvements (e.g. put newest matches on top).
2.4 (2006-12-11)
----------------
* Added a sample CGI script for brute-force log searches.
2.3 (2005-03-08)
----------------
* Use xhtmltable style by default.
* Added a copy of the navbar at the bottom.
2.2 (2005-02-04)
----------------
* Support supybot's ChannelLogger date format (e.g. 02-Feb-2004).
* Fixed broken timestamp hyperlinks in xhtml/xhtmltable styles.
* CSS tweaks.
2.1mg (2005-01-09)
------------------
* Ported irclog2html.pl version 2.1 by Jeff Waugh from Perl to Python.
* New styles: xhtml, xhtmltable.
* New options: --title, --{prev,index,next}-{url,title}
* Removed hardcoded nick colour preferences for jdub, cantaker and chuckd
* Bugfix: colours are preserver accross nick changes (irclog2html.pl tried to
do that, but had a bug in a regex)
* Added ISO8601 timestamp support (e.g. 2005-01-09T12:43:11).
* More careful URL linkification (stop at ', ", ), >).
* Added logs2html.py script for mass-conversion of logs.
* Added support for xchat log files.
* Added xchatlogsplit.py script for splitting xchat logs on day boundaries so they're suitable as input for logs2html.py.
Keywords: irc log colorizer html wsgi
Platform: any
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Provides-Extra: test
irclog2html-2.17.2/tox.ini 0000664 0001750 0001750 00000001140 13457567503 014411 0 ustar mg mg 0000000 0000000 [tox]
envlist = py27, py35, py36, py37, pypy, pypy3
[testenv]
deps =
zope.testrunner
zope.testing
mock
commands =
zope-testrunner --test-path=src {posargs:-v}
[testenv:py]
commands =
python --version
zope-testrunner --test-path=src {posargs:-v}
[testenv:coverage]
basepython = python2
usedevelop = true
deps =
{[testenv]deps}
coverage
commands =
coverage run {posargs} -m zope.testrunner --test-path=src
[testenv:coverage3]
basepython = python3
usedevelop = true
deps = {[testenv:coverage]deps}
commands =
coverage run {posargs} -m zope.testrunner --test-path=src
irclog2html-2.17.2/.gitignore 0000664 0001750 0001750 00000000340 12765062021 015051 0 ustar mg mg 0000000 0000000 parts/
eggs/
develop-eggs/
irclog2html.egg-info/
bin/
.installed.cfg
testcases/*.log.html
testcases/index.html
testcases/irclog.css
dist/
tmp/
build/
temp/
distribute-0.6.10.tar.gz
.tox/
python/
*.pyc
__pycache__/
.coverage
irclog2html-2.17.2/CHANGES.rst 0000644 0001750 0001750 00000014234 13457570472 014705 0 ustar mg mg 0000000 0000000 Changelog
=========
2.17.2 (2019-04-23)
-------------------
- Drop support for Python 3.4.
2.17.1 (2018-11-25)
-------------------
- Add support for Python 3.7.
- Drop support for Python 3.3.
- Support ``python -m irclog2html`` as shortcut for
``python -m irclog2html.irclog2html``.
- Make irclogserver ignore hidden directories (such as .git).
2.17.0 (2018-02-21)
-------------------
- Support `ii `_ logs which use Unix
timestamps (https://github.com/mgedmin/irclog2html/pull/21).
Pull request by Cédric Krier.
2.16.0 (2017-12-20)
-------------------
- Support Python 3.6.
- Fix for duplicated lines with the same time where the resulting HTML ``id``
anchors would evolve into long form like "t22:24:49-2-3-4-5-6-7-8-9-10"
instead of "t22:24:49-10" resulting in significant output file size growth
in some cases.
- Add --output-dir (-o) parameter to logs2html so you can place the generated
HTML files in a directory different from the input directory.
2.15.3 (2016-12-08)
-------------------
- In some circumstances parts of a message up to the last '>' could be lost
(https://github.com/mgedmin/irclog2html/issues/19).
2.15.2 (2016-10-07)
-------------------
- ``irclogserver`` channel list is now split into old channels and active
channels, detected by checking whether the directory modification date
is newer or older than 7 days.
- 2nd-level headings now have the same color as 1st-level headings.
- ``irclogserver`` no longer shows a 404 if you omit the trailing ``/``
after a channel name in the URL.
2.15.1 (2016-09-25)
-------------------
- Lines with the same timestamp now get different HTML anchors
(https://github.com/mgedmin/irclog2html/issues/17). Thanks
to Bryan Bishop for the original pull request.
2.15.0 (2016-09-25)
-------------------
- There's a new ``irclogserver`` script that can be used to serve
dynamically-generated IRC logs and perform search. It can also be
deployed via WSGI. Portions contributed by Albertas Agejevas
(https://github.com/mgedmin/irclog2html/pull/9).
- Index pages group the logs by month
(https://github.com/mgedmin/irclog2html/issues/12).
- Drop support for Python 2.6.
2.14.0 (2014-12-12)
-------------------
- Add -o option to specify the output file name. Patch by Moises Silva
(https://github.com/mgedmin/irclog2html/pull/7).
2.13.1 (2014-02-01)
-------------------
- Add support for Windows (e.g. refrain from creating latest.log.html
symlinks).
2.13.0 (2013-12-18)
-------------------
- Handle gzipped files transparently
(https://github.com/mgedmin/irclog2html/issues/5).
2.12.1 (2013-03-22)
-------------------
* Fix AttributeError in irclogsearch on Python 2.7
(https://github.com/mgedmin/irclog2html/issues/1).
2.12.0 (2013-03-18)
-------------------
* Moved to Github.
* Add support for Python 3.3.
* Drop support for Python 2.4 and 2.5.
* Fix URL linkifier to not include trailing punctuation (LP#1155906).
2.11.1 (2013-03-17)
-------------------
* logs2html also accepts filenames that contain YYYYMMDD dates (in addition to
YYYY-MM-DD). Patch by Holger Just. Fixes LP#1031642.
2.11.0 (2012-07-30)
-------------------
* irclogsearch can be told about the filename pattern of log files via an
environment variable (IRCLOG_GLOB). Patch by Jonathan Kinred.
2.10.0 (2012-02-12)
-------------------
* New option: --glob-pattern. Patch by Albertas Agejevas.
Fixes LP#912310.
* Links in logs are marked with rel="nofollow". Patch by Matt Wheeler.
Fixes LP#914553.
* New option: --version.
* New option: -c, --config=FILE.
2.9.2 (2011-01-16)
------------------
* Support XChat Latin/Unicode hybrid encoding (http://xchat.org/encoding/).
Fixes LP#703622.
* irclog2html copies irclog.css file into the destination directory.
Fixes LP#608727.
2.9.1 (2010-08-06)
------------------
* Make sure irclog.css is installed in the right place; logs2html needs it.
2.9 (2010-08-06)
----------------
* Restructured source tree, made irclogs2html into a package, added setup.py,
buildout.cfg, bootstrap.py, Makefile, HACKING.txt; moved old porting test
suite into a subdirectory (porting).
* logs2html copies irclog.css file into the destination directory.
* Released into PyPI.
2.8 (2010-07-22)
----------------
* Added README.txt and CHANGES.txt.
* Support dircproxy log files (new date format: "[15 Jan 08:42]",
strip ident and IP address from nicknames). Patch by Paul Frields.
* New option: --dircproxy also makes irclog2html strip a single leading
'+' or '-' from messages.
2.7.1 (2009-04-30)
------------------
* Bug in logs2html.py error reporting, reported by Ondrej Baudys.
2.7 (2008-06-10)
----------------
* New style: mediawiki. Patch by Ian Weller.
2.6 (2007-10-30)
----------------
* Support another date format (Oct 17 10:53:26). Patch by Matthew Barnes.
2.5.1 (2007-03-22)
------------------
* logs2html.py: add a stable link to the latest log file
(suggested by Chris Foster).
2.5 (2007-01-22)
----------------
* New option: --searchbox.
* Search CGI script improvements (e.g. put newest matches on top).
2.4 (2006-12-11)
----------------
* Added a sample CGI script for brute-force log searches.
2.3 (2005-03-08)
----------------
* Use xhtmltable style by default.
* Added a copy of the navbar at the bottom.
2.2 (2005-02-04)
----------------
* Support supybot's ChannelLogger date format (e.g. 02-Feb-2004).
* Fixed broken timestamp hyperlinks in xhtml/xhtmltable styles.
* CSS tweaks.
2.1mg (2005-01-09)
------------------
* Ported irclog2html.pl version 2.1 by Jeff Waugh from Perl to Python.
* New styles: xhtml, xhtmltable.
* New options: --title, --{prev,index,next}-{url,title}
* Removed hardcoded nick colour preferences for jdub, cantaker and chuckd
* Bugfix: colours are preserver accross nick changes (irclog2html.pl tried to
do that, but had a bug in a regex)
* Added ISO8601 timestamp support (e.g. 2005-01-09T12:43:11).
* More careful URL linkification (stop at ', ", ), >).
* Added logs2html.py script for mass-conversion of logs.
* Added support for xchat log files.
* Added xchatlogsplit.py script for splitting xchat logs on day boundaries so they're suitable as input for logs2html.py.
irclog2html-2.17.2/setup.cfg 0000664 0001750 0001750 00000000744 13457570524 014725 0 ustar mg mg 0000000 0000000 [bdist_wheel]
universal = 1
[metadata]
license_file = COPYING
[flake8]
doctests = yes
extend-ignore = E261,E501
[zest.releaser]
python-file-with-version = src/irclog2html/_version.py
[tool:pytest]
norecursedirs = .* *.egg-info parts eggs develop-eggs bin dist tmp build temp python porting
python_functions = !test_suite
addopts = --doctest-modules --ignore=bootstrap.py --ignore=setup.py
doctest_optionflags = NORMALIZE_WHITESPACE ELLIPSIS
[egg_info]
tag_build =
tag_date = 0
irclog2html-2.17.2/Makefile 0000644 0001750 0001750 00000003072 13376525103 014530 0 ustar mg mg 0000000 0000000 PYTHON = python
PAGER = less -RFX
TESTFLAGS = -v
FILE_WITH_VERSION = src/irclog2html/_version.py
FILE_WITH_CHANGELOG = CHANGES.rst
scripts = bin/test bin/irclog2html bin/logs2html bin/irclogsearch bin/irclogserver
SHELL = /bin/bash -o pipefail
ifneq "$(TERM)" "dumb"
is_tty = $(shell test -t 2 && echo 1)
endif
.PHONY: default
default: all
.PHONY: all
all: $(scripts)
.PHONY: check test
check test: bin/test flake8
ifdef is_tty
bin/test $(TESTFLAGS) -c | $(PAGER)
else
bin/test $(TESTFLAGS)
endif
.PHONY: flake8 lint
flake8 lint:
flake8 src setup.py
.PHONY: test-all-pythons
test-all-pythons:
tox
.PHONY: coverage
coverage:
tox -e coverage,coverage3 -- -p
coverage combine
coverage report -m --fail-under=100
.PHONY: diff-cover
diff-cover: coverage
tox -e coverage,coverage3 -- -p
coverage combine
coverage xml
diff-cover coverage.xml
.PHONY: clean
clean:
rm -f testcases/*.html testcases/*.css
.PHONY: releasechecklist
releasechecklist: check-date # also release.mk will add other checks
include release.mk
.PHONY: check-date
check-date:
@date_line="__date__ = '`date +%Y-%m-%d`'" && \
grep -q "^$$date_line$$" $(FILE_WITH_VERSION) || { \
echo "$(FILE_WITH_VERSION) doesn't specify $$date_line"; exit 1; }
python:
virtualenv -p $(PYTHON) python
python/bin/virtualenv:
python/bin/pip install -U setuptools virtualenv
bin/buildout: python bootstrap.py
python/bin/pip install -U setuptools
python/bin/python bootstrap.py
touch -c $@
$(scripts): bin/buildout buildout.cfg setup.py python/bin/virtualenv
bin/buildout
touch -c $(scripts)
irclog2html-2.17.2/bootstrap.py 0000664 0001750 0001750 00000016442 12544765616 015501 0 ustar mg mg 0000000 0000000 ##############################################################################
#
# Copyright (c) 2006 Zope Foundation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Bootstrap a buildout-based project
Simply run this script in a directory containing a buildout.cfg.
The script accepts buildout command-line options, so you can
use the -c option to specify an alternate configuration file.
"""
import os
import shutil
import sys
import tempfile
from optparse import OptionParser
__version__ = '2015-07-01'
# See zc.buildout's changelog if this version is up to date.
tmpeggs = tempfile.mkdtemp(prefix='bootstrap-')
usage = '''\
[DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
Bootstraps a buildout-based project.
Simply run this script in a directory containing a buildout.cfg, using the
Python that you want bin/buildout to use.
Note that by using --find-links to point to local resources, you can keep
this script from going over the network.
'''
parser = OptionParser(usage=usage)
parser.add_option("--version",
action="store_true", default=False,
help=("Return bootstrap.py version."))
parser.add_option("-t", "--accept-buildout-test-releases",
dest='accept_buildout_test_releases',
action="store_true", default=False,
help=("Normally, if you do not specify a --version, the "
"bootstrap script and buildout gets the newest "
"*final* versions of zc.buildout and its recipes and "
"extensions for you. If you use this flag, "
"bootstrap and buildout will get the newest releases "
"even if they are alphas or betas."))
parser.add_option("-c", "--config-file",
help=("Specify the path to the buildout configuration "
"file to be used."))
parser.add_option("-f", "--find-links",
help=("Specify a URL to search for buildout releases"))
parser.add_option("--allow-site-packages",
action="store_true", default=False,
help=("Let bootstrap.py use existing site packages"))
parser.add_option("--buildout-version",
help="Use a specific zc.buildout version")
parser.add_option("--setuptools-version",
help="Use a specific setuptools version")
parser.add_option("--setuptools-to-dir",
help=("Allow for re-use of existing directory of "
"setuptools versions"))
options, args = parser.parse_args()
if options.version:
print("bootstrap.py version %s" % __version__)
sys.exit(0)
######################################################################
# load/install setuptools
try:
from urllib.request import urlopen
except ImportError:
from urllib2 import urlopen
ez = {}
if os.path.exists('ez_setup.py'):
exec(open('ez_setup.py').read(), ez)
else:
exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez)
if not options.allow_site_packages:
# ez_setup imports site, which adds site packages
# this will remove them from the path to ensure that incompatible versions
# of setuptools are not in the path
import site
# inside a virtualenv, there is no 'getsitepackages'.
# We can't remove these reliably
if hasattr(site, 'getsitepackages'):
for sitepackage_path in site.getsitepackages():
# Strip all site-packages directories from sys.path that
# are not sys.prefix; this is because on Windows
# sys.prefix is a site-package directory.
if sitepackage_path != sys.prefix:
sys.path[:] = [x for x in sys.path
if sitepackage_path not in x]
setup_args = dict(to_dir=tmpeggs, download_delay=0)
if options.setuptools_version is not None:
setup_args['version'] = options.setuptools_version
if options.setuptools_to_dir is not None:
setup_args['to_dir'] = options.setuptools_to_dir
ez['use_setuptools'](**setup_args)
import setuptools
import pkg_resources
# This does not (always?) update the default working set. We will
# do it.
for path in sys.path:
if path not in pkg_resources.working_set.entries:
pkg_resources.working_set.add_entry(path)
######################################################################
# Install buildout
ws = pkg_resources.working_set
setuptools_path = ws.find(
pkg_resources.Requirement.parse('setuptools')).location
# Fix sys.path here as easy_install.pth added before PYTHONPATH
cmd = [sys.executable, '-c',
'import sys; sys.path[0:0] = [%r]; ' % setuptools_path +
'from setuptools.command.easy_install import main; main()',
'-mZqNxd', tmpeggs]
find_links = os.environ.get(
'bootstrap-testing-find-links',
options.find_links or
('http://downloads.buildout.org/'
if options.accept_buildout_test_releases else None)
)
if find_links:
cmd.extend(['-f', find_links])
requirement = 'zc.buildout'
version = options.buildout_version
if version is None and not options.accept_buildout_test_releases:
# Figure out the most recent final version of zc.buildout.
import setuptools.package_index
_final_parts = '*final-', '*final'
def _final_version(parsed_version):
try:
return not parsed_version.is_prerelease
except AttributeError:
# Older setuptools
for part in parsed_version:
if (part[:1] == '*') and (part not in _final_parts):
return False
return True
index = setuptools.package_index.PackageIndex(
search_path=[setuptools_path])
if find_links:
index.add_find_links((find_links,))
req = pkg_resources.Requirement.parse(requirement)
if index.obtain(req) is not None:
best = []
bestv = None
for dist in index[req.project_name]:
distv = dist.parsed_version
if _final_version(distv):
if bestv is None or distv > bestv:
best = [dist]
bestv = distv
elif distv == bestv:
best.append(dist)
if best:
best.sort()
version = best[-1].version
if version:
requirement = '=='.join((requirement, version))
cmd.append(requirement)
import subprocess
if subprocess.call(cmd) != 0:
raise Exception(
"Failed to execute command:\n%s" % repr(cmd)[1:-1])
######################################################################
# Import and run buildout
ws.add_entry(tmpeggs)
ws.require(requirement)
import zc.buildout.buildout
if not [a for a in args if '=' not in a]:
args.append('bootstrap')
# if -c was provided, we push it back into args for buildout' main function
if options.config_file is not None:
args[0:0] = ['-c', options.config_file]
zc.buildout.buildout.main(args)
shutil.rmtree(tmpeggs)
irclog2html-2.17.2/buildout.cfg 0000664 0001750 0001750 00000000250 13236050371 015370 0 ustar mg mg 0000000 0000000 [buildout]
develop = .
parts = irclog2html test
[irclog2html]
recipe = zc.recipe.egg
eggs = irclog2html
[test]
recipe = zc.recipe.testrunner
eggs = irclog2html[test]
irclog2html-2.17.2/src/ 0000755 0001750 0001750 00000000000 13457570524 013664 5 ustar mg mg 0000000 0000000 irclog2html-2.17.2/src/irclog2html.egg-info/ 0000755 0001750 0001750 00000000000 13457570524 017604 5 ustar mg mg 0000000 0000000 irclog2html-2.17.2/src/irclog2html.egg-info/SOURCES.txt 0000664 0001750 0001750 00000002637 13457570524 021502 0 ustar mg mg 0000000 0000000 .coveragerc
.gitignore
.travis.yml
CHANGES.rst
COPYING
HACKING.rst
MANIFEST.in
Makefile
README.rst
appveyor.yml
bootstrap.py
buildout.cfg
release.mk
setup.cfg
setup.py
tox.ini
porting/HISTORY.txt
porting/irclog2html.pl
porting/irclog2html.py
porting/test.py
porting/testcases/dircproxy-example.log
porting/testcases/test1.log
porting/testcases/test2.log
src/irclog2html/__init__.py
src/irclog2html/__main__.py
src/irclog2html/_version.py
src/irclog2html/irclog.css
src/irclog2html/irclog2html.py
src/irclog2html/irclogsearch.py
src/irclog2html/irclogserver.py
src/irclog2html/logs2html.py
src/irclog2html/xchatlogsplit.py
src/irclog2html.egg-info/PKG-INFO
src/irclog2html.egg-info/SOURCES.txt
src/irclog2html.egg-info/dependency_links.txt
src/irclog2html.egg-info/entry_points.txt
src/irclog2html.egg-info/not-zip-safe
src/irclog2html.egg-info/pbr.json
src/irclog2html.egg-info/requires.txt
src/irclog2html.egg-info/top_level.txt
src/irclog2html/tests/__init__.py
src/irclog2html/tests/sample.cfg
src/irclog2html/tests/sample.log
src/irclog2html/tests/test_irclog2html.py
src/irclog2html/tests/test_irclogsearch.py
src/irclog2html/tests/test_irclogserver.py
src/irclog2html/tests/test_logs2html.py
src/irclog2html/tests/test_main.py
testcases/2005-01-08-test1.log
testcases/2005-01-09-test2.log
testcases/2009-01-14-dircproxy.log
testcases/2009-01-15-dircproxy.log
testcases/2009-01-16-dircproxy.log
testcases/2011-01-16-hybrid-charset.log irclog2html-2.17.2/src/irclog2html.egg-info/PKG-INFO 0000664 0001750 0001750 00000036236 13457570524 020715 0 ustar mg mg 0000000 0000000 Metadata-Version: 2.1
Name: irclog2html
Version: 2.17.2
Summary: Convert IRC logs to HTML
Home-page: https://mg.pov.lt/irclog2html/
Author: Marius Gedminas
Author-email: marius@gedmin.as
License: GPL v2 or later
Description: ===========
irclog2html
===========
Converts IRC log files to HTML with pretty colours.
Quick start
===========
Installation::
pip install irclog2html
Quick usage for a single log file::
irclog2html --help
irclog2html filename.log (produces filename.log.html)
Mass-conversion of logs (one file per day, with YYYY-MM-DD in the filename)
with next/prev links, with mtime checks, usable from cron::
logs2html directory/ (looks for *.log and *.log.gz, produces *.log.html)
Configuration files
===================
Since you probably don't want to keep specifying the same options on the
command line every time you run logs2html, you can create a config file.
For example::
-t 'IRC logs for #mychannel'
-p 'IRC logs for #mychannel for '
# the following needs some extra Apache setup to enable the CGI/WSGI script
--searchbox
# where we keep the logs
/full/path/to/directory/
Use it like this::
logs2html -c /path/to/mychannel.conf
Lines starting with a ``#`` are ignored. Other lines are interpreted as
command-line options.
The order matters: options on the command line before the ``-c FILE`` will
be overriden by option in the config file. Options specified after ``-c FILE``
will override the options in the config file.
You can include more than one config file by repeating ``-c FILE``. You
can include config files from other config files. You can even create loops of
config files and then watch and laugh manically as logs2html sits there burning
your CPU.
CGI script for log searching
============================
.. warning::
The script can be easily abused to cause a denial of service attack; it
parses *all* log files every time you perform a search.
You can generate search boxes on IRC log pages by passing the ``--searchbox``
option to ``logs2html``. Here's an example Apache config snippet that makes
it work::
RewriteRule ^/my-irclog/search/$ /my-irclog/search [R,L]
ScriptAlias /my-irclog/search /usr/local/bin/irclogsearch
SetEnv IRCLOG_LOCATION "/var/www/my-irclog/"
# Uncomment the following if your log files use a different format
#SetEnv IRCLOG_GLOB "*.log.????-??-??"
# (this will also automatically handle *.log.????-??-??.gz)
WSGI script for log serving
===========================
.. warning::
The script can be easily abused to cause a denial of service attack; it
parses *all* log files every time you perform a search.
There's now an experimental WSGI script that can generate HTML for the
logs on the fly. You can use it if you don't like cron scripts and CGI.
Here's an example Apache config snippet::
WSGIScriptAlias /irclogs /usr/local/bin/irclogserver
SetEnv IRCLOG_LOCATION "/var/www/my-irclog/"
# Uncomment the following if your log files use a different format
#SetEnv IRCLOG_GLOB "*.log.????-??-??"
# (this will also automatically handle *.log.????-??-??.gz)
Currently it has certain downsides:
- configuration is very limited, e.g you cannot specify titles or styles
or enable dircproxy mode
- HTML files in the irc log directory will take precedence over
dynamically-generated logs even if they're older than the corresponding
log file (but on the plus side you can use that to have dynamic search
via WSGI, but keep statically-generated HTML files with your own config
tweaks)
WSGI script for multi-channel log serving
=========================================
.. warning::
The script can be easily abused to cause a denial of service attack; it
parses *all* log files every time you perform a search.
The experimental WSGI script can serve logs for multiple channels::
WSGIScriptAlias /irclogs /usr/local/bin/irclogserver
SetEnv IRCLOG_CHAN_DIR "/var/www/my-irclog/"
# Uncomment the following if your log files use a different format
#SetEnv IRCLOG_GLOB "*.log.????-??-??"
# (this will also automatically handle *.log.????-??-??.gz)
Now ``/irclogs`` will show a list of channels (subdirectories under
``/var/www/my-irclog/``), and ``/irclogs/channel/`` will show the
date index for that channel.
Misc
====
Website: https://mg.pov.lt/irclog2html/
Bug tracker:
https://github.com/mgedmin/irclog2html/issues
Licence: GPL v2 or later (https://www.gnu.org/copyleft/gpl.html)
|buildstatus|_ |appveyor|_ |coverage|_
.. |buildstatus| image:: https://api.travis-ci.org/mgedmin/irclog2html.svg?branch=master
.. _buildstatus: https://travis-ci.org/mgedmin/irclog2html
.. |appveyor| image:: https://ci.appveyor.com/api/projects/status/github/mgedmin/irclog2html?branch=master&svg=true
.. _appveyor: https://ci.appveyor.com/project/mgedmin/irclog2html
.. |coverage| image:: https://coveralls.io/repos/mgedmin/irclog2html/badge.svg?branch=master
.. _coverage: https://coveralls.io/r/mgedmin/irclog2html
Changelog
=========
2.17.2 (2019-04-23)
-------------------
- Drop support for Python 3.4.
2.17.1 (2018-11-25)
-------------------
- Add support for Python 3.7.
- Drop support for Python 3.3.
- Support ``python -m irclog2html`` as shortcut for
``python -m irclog2html.irclog2html``.
- Make irclogserver ignore hidden directories (such as .git).
2.17.0 (2018-02-21)
-------------------
- Support `ii `_ logs which use Unix
timestamps (https://github.com/mgedmin/irclog2html/pull/21).
Pull request by Cédric Krier.
2.16.0 (2017-12-20)
-------------------
- Support Python 3.6.
- Fix for duplicated lines with the same time where the resulting HTML ``id``
anchors would evolve into long form like "t22:24:49-2-3-4-5-6-7-8-9-10"
instead of "t22:24:49-10" resulting in significant output file size growth
in some cases.
- Add --output-dir (-o) parameter to logs2html so you can place the generated
HTML files in a directory different from the input directory.
2.15.3 (2016-12-08)
-------------------
- In some circumstances parts of a message up to the last '>' could be lost
(https://github.com/mgedmin/irclog2html/issues/19).
2.15.2 (2016-10-07)
-------------------
- ``irclogserver`` channel list is now split into old channels and active
channels, detected by checking whether the directory modification date
is newer or older than 7 days.
- 2nd-level headings now have the same color as 1st-level headings.
- ``irclogserver`` no longer shows a 404 if you omit the trailing ``/``
after a channel name in the URL.
2.15.1 (2016-09-25)
-------------------
- Lines with the same timestamp now get different HTML anchors
(https://github.com/mgedmin/irclog2html/issues/17). Thanks
to Bryan Bishop for the original pull request.
2.15.0 (2016-09-25)
-------------------
- There's a new ``irclogserver`` script that can be used to serve
dynamically-generated IRC logs and perform search. It can also be
deployed via WSGI. Portions contributed by Albertas Agejevas
(https://github.com/mgedmin/irclog2html/pull/9).
- Index pages group the logs by month
(https://github.com/mgedmin/irclog2html/issues/12).
- Drop support for Python 2.6.
2.14.0 (2014-12-12)
-------------------
- Add -o option to specify the output file name. Patch by Moises Silva
(https://github.com/mgedmin/irclog2html/pull/7).
2.13.1 (2014-02-01)
-------------------
- Add support for Windows (e.g. refrain from creating latest.log.html
symlinks).
2.13.0 (2013-12-18)
-------------------
- Handle gzipped files transparently
(https://github.com/mgedmin/irclog2html/issues/5).
2.12.1 (2013-03-22)
-------------------
* Fix AttributeError in irclogsearch on Python 2.7
(https://github.com/mgedmin/irclog2html/issues/1).
2.12.0 (2013-03-18)
-------------------
* Moved to Github.
* Add support for Python 3.3.
* Drop support for Python 2.4 and 2.5.
* Fix URL linkifier to not include trailing punctuation (LP#1155906).
2.11.1 (2013-03-17)
-------------------
* logs2html also accepts filenames that contain YYYYMMDD dates (in addition to
YYYY-MM-DD). Patch by Holger Just. Fixes LP#1031642.
2.11.0 (2012-07-30)
-------------------
* irclogsearch can be told about the filename pattern of log files via an
environment variable (IRCLOG_GLOB). Patch by Jonathan Kinred.
2.10.0 (2012-02-12)
-------------------
* New option: --glob-pattern. Patch by Albertas Agejevas.
Fixes LP#912310.
* Links in logs are marked with rel="nofollow". Patch by Matt Wheeler.
Fixes LP#914553.
* New option: --version.
* New option: -c, --config=FILE.
2.9.2 (2011-01-16)
------------------
* Support XChat Latin/Unicode hybrid encoding (http://xchat.org/encoding/).
Fixes LP#703622.
* irclog2html copies irclog.css file into the destination directory.
Fixes LP#608727.
2.9.1 (2010-08-06)
------------------
* Make sure irclog.css is installed in the right place; logs2html needs it.
2.9 (2010-08-06)
----------------
* Restructured source tree, made irclogs2html into a package, added setup.py,
buildout.cfg, bootstrap.py, Makefile, HACKING.txt; moved old porting test
suite into a subdirectory (porting).
* logs2html copies irclog.css file into the destination directory.
* Released into PyPI.
2.8 (2010-07-22)
----------------
* Added README.txt and CHANGES.txt.
* Support dircproxy log files (new date format: "[15 Jan 08:42]",
strip ident and IP address from nicknames). Patch by Paul Frields.
* New option: --dircproxy also makes irclog2html strip a single leading
'+' or '-' from messages.
2.7.1 (2009-04-30)
------------------
* Bug in logs2html.py error reporting, reported by Ondrej Baudys.
2.7 (2008-06-10)
----------------
* New style: mediawiki. Patch by Ian Weller.
2.6 (2007-10-30)
----------------
* Support another date format (Oct 17 10:53:26). Patch by Matthew Barnes.
2.5.1 (2007-03-22)
------------------
* logs2html.py: add a stable link to the latest log file
(suggested by Chris Foster).
2.5 (2007-01-22)
----------------
* New option: --searchbox.
* Search CGI script improvements (e.g. put newest matches on top).
2.4 (2006-12-11)
----------------
* Added a sample CGI script for brute-force log searches.
2.3 (2005-03-08)
----------------
* Use xhtmltable style by default.
* Added a copy of the navbar at the bottom.
2.2 (2005-02-04)
----------------
* Support supybot's ChannelLogger date format (e.g. 02-Feb-2004).
* Fixed broken timestamp hyperlinks in xhtml/xhtmltable styles.
* CSS tweaks.
2.1mg (2005-01-09)
------------------
* Ported irclog2html.pl version 2.1 by Jeff Waugh from Perl to Python.
* New styles: xhtml, xhtmltable.
* New options: --title, --{prev,index,next}-{url,title}
* Removed hardcoded nick colour preferences for jdub, cantaker and chuckd
* Bugfix: colours are preserver accross nick changes (irclog2html.pl tried to
do that, but had a bug in a regex)
* Added ISO8601 timestamp support (e.g. 2005-01-09T12:43:11).
* More careful URL linkification (stop at ', ", ), >).
* Added logs2html.py script for mass-conversion of logs.
* Added support for xchat log files.
* Added xchatlogsplit.py script for splitting xchat logs on day boundaries so they're suitable as input for logs2html.py.
Keywords: irc log colorizer html wsgi
Platform: any
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Provides-Extra: test
irclog2html-2.17.2/src/irclog2html.egg-info/not-zip-safe 0000664 0001750 0001750 00000000001 12765063775 022042 0 ustar mg mg 0000000 0000000
irclog2html-2.17.2/src/irclog2html.egg-info/dependency_links.txt 0000664 0001750 0001750 00000000001 13457570524 023654 0 ustar mg mg 0000000 0000000
irclog2html-2.17.2/src/irclog2html.egg-info/requires.txt 0000664 0001750 0001750 00000000032 13457570524 022201 0 ustar mg mg 0000000 0000000
[test]
mock
zope.testing
irclog2html-2.17.2/src/irclog2html.egg-info/entry_points.txt 0000664 0001750 0001750 00000000353 13457570524 023105 0 ustar mg mg 0000000 0000000
[console_scripts]
irclog2html = irclog2html.irclog2html:main
logs2html = irclog2html.logs2html:main
irclogsearch = irclog2html.irclogsearch:main
irclogserver = irclog2html.irclogserver:main
irclog2html-2.17.2/src/irclog2html.egg-info/pbr.json 0000664 0001750 0001750 00000000057 13032432552 021251 0 ustar mg mg 0000000 0000000 {"is_release": false, "git_version": "4c1a3fa"} irclog2html-2.17.2/src/irclog2html.egg-info/top_level.txt 0000664 0001750 0001750 00000000014 13457570524 022333 0 ustar mg mg 0000000 0000000 irclog2html
irclog2html-2.17.2/src/irclog2html/ 0000755 0001750 0001750 00000000000 13457570524 016112 5 ustar mg mg 0000000 0000000 irclog2html-2.17.2/src/irclog2html/__init__.py 0000664 0001750 0001750 00000000000 12765062021 020200 0 ustar mg mg 0000000 0000000 irclog2html-2.17.2/src/irclog2html/_version.py 0000644 0001750 0001750 00000000137 13457570472 020313 0 ustar mg mg 0000000 0000000 __version__ = '2.17.2'
__date__ = '2019-04-23'
__homepage__ = 'https://mg.pov.lt/irclog2html/'
irclog2html-2.17.2/src/irclog2html/xchatlogsplit.py 0000755 0001750 0001750 00000005574 13457570472 021371 0 ustar mg mg 0000000 0000000 #!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
Split xchat2 log file into daily log files suitable as input for logs2html.py.
Usage: xchatlogsplit.py filename
XXX code is ugly
This is more of an example than a real script, although I have used it to
restore some actual IRC chat log history from my xchat logs.
"""
from __future__ import print_function
import sys
import time
import os
import re
import locale
from warnings import warn
STAMP_RX = re.compile(r'^[*][*][*][*] ((BEGIN|ENDING) LOGGING AT|(LOGINIMAS|ŽURNALAS) (PRADĖTAS|BAIGTAS)) ')
def readxchatlogs(infile):
date = None
ymd = None
for line in infile:
m = STAMP_RX.match(line)
if m:
stamp = line[len(m.group(0)):].strip()
try:
t = time.strptime(stamp, '%a %b %d %H:%M:%S %Y')
except ValueError:
locale.setlocale(locale.LC_TIME, "")
t = time.strptime(stamp, '%a %b %d %H:%M:%S %Y')
locale.setlocale(locale.LC_TIME, "C")
ymd = t[:3]
date = time.strftime("%Y-%m-%d", t)
elif line.strip():
assert date, 'what year? got only %s' % line
try:
t = time.strptime(line[:len('Ddd YY HH:MM:SS'):], '%b %d %H:%M:%S')
except ValueError:
locale.setlocale(locale.LC_TIME, "")
try:
t = time.strptime(stamp, '%a %b %d %H:%M:%S %Y')
except ValueError:
warn("Skipping %s" % line.strip())
locale.setlocale(locale.LC_TIME, "C")
continue
locale.setlocale(locale.LC_TIME, "C")
t = (ymd[0], ) + t[1:]
if t[:3] < ymd: # new year wraparound
warn("Guessing that wraparound occurred: %s -> %s" % (ymd, t[:3]))
t = (ymd[0] + 1, ) + t[1:]
ymd = t[:3]
date = time.strftime("%Y-%m-%d", t)
line = line[len('Ddd YY '):]
elif not date:
continue
assert date
yield date, line
def main(argv=sys.argv):
if len(argv) < 2:
sys.exit(__doc__)
filename = argv[1]
prefix = os.path.basename(filename).split('-')[1].split('.')[0]
dir = os.path.dirname(filename)
prefix = os.path.join(dir, prefix)
curdate = None
outfile = None
with open(filename) as fp:
for date, line in readxchatlogs(fp):
if curdate != date:
if outfile:
outfile.close()
curdate = date
outfilename = prefix + "." + date + ".log"
if os.path.exists(outfilename):
sys.exit("refusing to overwrite %s" % outfilename)
outfile = open(outfilename, "a")
print(line, end=' ', file=outfile)
if outfile:
outfile.close()
if __name__ == '__main__':
main()
irclog2html-2.17.2/src/irclog2html/__main__.py 0000644 0001750 0001750 00000000105 13301515343 020162 0 ustar mg mg 0000000 0000000 from .irclog2html import main
if __name__ == '__main__':
main()
irclog2html-2.17.2/src/irclog2html/irclogserver.py 0000755 0001750 0001750 00000025016 13376525144 021177 0 ustar mg mg 0000000 0000000 #!/usr/bin/env python
"""
Serve IRC logs (WSGI app)
Expects to find logs matching the IRCLOG_GLOB pattern (default: *.log)
in the directory specified by the IRCLOG_LOCATION environment variable.
Expects the filenames to contain a ISO 8601 date (YYYY-MM-DD).
Apache configuration example:
WSGIScriptAlias /irclogs /path/to/irclogserver.py
# If you're serving the logs for one channel, specify this:
SetEnv IRCLOG_LOCATION /path/to/irclog/files/
# If you're serving the logs for many channels, specify this:
SetEnv IRCLOG_CHAN_DIR /path/to/irclog/channels/
# Uncomment the following if your log files use a different format
#SetEnv IRCLOG_GLOB "*.log.????-??-??"
"""
# Copyright (c) 2015-2016, Marius Gedminas and contributors
#
# Released under the terms of the GNU GPL v2 or later
# https://www.gnu.org/copyleft/gpl.html
from __future__ import print_function
import argparse
import cgi
import datetime
import io
import os
import time
from operator import attrgetter
from wsgiref.simple_server import make_server
try:
from urllib import quote_plus # Py2
except ImportError:
from urllib.parse import quote_plus # Py3
from ._version import __version__, __date__
from .irclog2html import (
CSS_FILE, LogParser, XHTMLTableStyle, convert_irc_log, escape,
)
from .logs2html import LogFile, Error, find_log_files, write_index
from .irclogsearch import (
DEFAULT_LOGFILE_PATH, DEFAULT_LOGFILE_PATTERN, search_page,
)
HEADER = u'''\
'''.format(version=__version__, date=__date__)
class Channel(object):
"""IRC channel."""
def __init__(self, name, path):
self.name = name
self.mtime = os.stat(os.path.join(path, name)).st_mtime
@property
def age(self):
return datetime.timedelta(seconds=time.time() - self.mtime)
def find_channels(path):
return sorted([
Channel(name, path) for name in os.listdir(path)
if not name.startswith('.') and os.path.isdir(os.path.join(path, name))
], key=attrgetter('name'))
def dir_listing(stream, path):
"""Primitive listing of subdirectories."""
print(HEADER, file=stream)
print(u"
IRC logs
", file=stream)
channels = find_channels(path)
old, new = [], []
for channel in channels:
if channel.age > datetime.timedelta(days=7):
old.append(channel)
else:
new.append(channel)
if not channels:
print(u"
", file=stream)
print(FOOTER, file=stream)
def log_listing(stream, path, pattern, channel=None):
"""Primitive listing of log files."""
logfiles = find_log_files(path, pattern)
logfiles.reverse()
if channel:
title = u"IRC logs of {channel}".format(channel=channel)
else:
title = u"IRC logs"
write_index(stream, title, logfiles, searchbox=True)
def dynamic_log(stream, path, pattern, channel=None):
"""Render HTML dynamically"""
lf = LogFile(path)
logfiles = find_log_files(os.path.dirname(path), pattern)
try:
idx = logfiles.index(lf)
lf.prev = logfiles[idx - 1] if idx > 0 else None
lf.next = logfiles[idx + 1] if idx + 1 < len(logfiles) else None
except ValueError:
pass
with open(path, 'rb') as f:
parser = LogParser(f)
formatter = XHTMLTableStyle(stream.buffer)
if channel:
title = u"IRC log of {channel}".format(channel=channel)
else:
title = u"IRC log"
title += u" for {date:%A, %Y-%m-%d}".format(date=lf.date)
prev = ('« {date:%A, %Y-%m-%d}'.format(date=lf.prev.date),
lf.prev.link) if lf.prev else ('', '')
next = ('{date:%A, %Y-%m-%d} »'.format(date=lf.next.date),
lf.next.link) if lf.next else ('', '')
index = ('Index', 'index.html')
convert_irc_log(parser, formatter, title, prev, index, next,
searchbox=True)
def parse_path(environ):
"""Return tuples (channel, filename).
The channel of None means default, the filename of None means 404.
"""
path = environ.get('PATH_INFO', '/')
path = path[1:] # Remove the leading slash
channel = None
if environ.get('IRCLOG_CHAN_DIR', os.environ.get('IRCLOG_CHAN_DIR')):
if '/' in path:
channel, path = path.split('/', 1)
if channel == '..' or path == '..' or '/' in path or '\\' in path:
return None, None
return channel, (path or 'index.html')
def application(environ, start_response):
"""WSGI application"""
def getenv(name, default=None):
return environ.get(name, os.environ.get(name, default))
chan_path = getenv('IRCLOG_CHAN_DIR')
logfile_path = getenv('IRCLOG_LOCATION') or DEFAULT_LOGFILE_PATH
logfile_pattern = getenv('IRCLOG_GLOB') or DEFAULT_LOGFILE_PATTERN
form = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ)
stream = io.TextIOWrapper(io.BytesIO(), 'ascii',
errors='xmlcharrefreplace',
line_buffering=True)
status = "200 Ok"
content_type = "text/html; charset=UTF-8"
headers = {}
result = []
channel, path = parse_path(environ)
if channel:
logfile_path = os.path.join(chan_path, channel)
if path is None:
status = "404 Not Found"
result = [b"Not found"]
content_type = "text/plain"
elif path == "index.html" and chan_path and channel is None:
dir_listing(stream, chan_path)
result = [stream.buffer.getvalue()]
elif path == 'search':
search_page(stream, form, logfile_path, logfile_pattern)
result = [stream.buffer.getvalue()]
elif path == 'irclog.css':
content_type = "text/css"
try:
with open(CSS_FILE, "rb") as f:
result = [f.read()]
except IOError: # pragma: nocover
status = "404 Not Found"
result = [b"Not found"]
content_type = "text/plain"
else:
full_path = os.path.join(logfile_path, path)
try:
with open(full_path, "rb") as f:
result = [f.read()]
except IOError:
if path == 'index.html':
log_listing(stream, logfile_path, logfile_pattern, channel)
result = [stream.buffer.getvalue()]
elif path.endswith('.html'):
try:
dynamic_log(stream, full_path[:-len('.html')],
logfile_pattern, channel=channel)
result = [stream.buffer.getvalue()]
except (Error, IOError):
# Error will be raised if the filename has no ISO-8601 date
status = "404 Not Found"
result = [b"Not found"]
content_type = "text/plain"
elif chan_path and not channel and os.path.isdir(os.path.join(chan_path, path)):
status = "302 Found"
headers["Location"] = quote_plus(path) + "/"
result = [b"Redirecting..."]
content_type = "text/plain"
else:
status = "404 Not Found"
result = [b"Not found"]
content_type = "text/plain"
else:
if path.endswith('.css'):
content_type = "text/css"
elif path.endswith('.log') or path.endswith('.txt'):
content_type = "text/plain; charset=UTF-8"
result = [LogParser.decode(line).encode('UTF-8')
for line in b''.join(result).splitlines(True)]
headers["Content-Type"] = content_type
# We need str() for Python 2 because of unicode_literals
headers = sorted((str(k), str(v)) for k, v in headers.items())
start_response(str(status), headers)
return result
def main(): # pragma: nocover
"""Simple web server for manual testing"""
parser = argparse.ArgumentParser(description="Serve IRC logs")
parser.add_argument(
'-p', '--port', type=int, default=8080,
help='listen on the specified port (default: 8080)')
parser.add_argument(
'-P', '--pattern',
help='IRC log file pattern (default: $IRCLOG_GLOB,'
' falling back to %s)' % DEFAULT_LOGFILE_PATTERN)
parser.add_argument(
'-m', '--multi', action='store_true',
help='serve logs for multiple channels in subdirectories'
' (default: when $IRCLOG_CHAN_DIR points to a path)')
parser.add_argument(
'path',
help='where to find IRC logs (default: $IRCLOG_LOCATION'
' or $IRCLOG_CHAN_DIR, falling back to %s)'
% DEFAULT_LOGFILE_PATH)
args = parser.parse_args()
srv = make_server('localhost', args.port, application)
print("Started at http://localhost:{port}/".format(port=args.port))
if args.multi:
os.environ['IRCLOG_CHAN_DIR'] = args.path
print("Serving IRC logs for multiple channels from {path}".format(
path=args.path))
else:
os.environ['IRCLOG_LOCATION'] = args.path
print("Serving IRC logs from {path}".format(path=args.path))
if args.pattern:
os.environ['IRCLOG_GLOB'] = args.pattern
print("Looking for files matching {pattern}".format(
pattern=args.pattern))
try:
srv.serve_forever()
except KeyboardInterrupt:
pass
if __name__ == '__main__':
main()
irclog2html-2.17.2/src/irclog2html/logs2html.py 0000755 0001750 0001750 00000024666 13376517161 020416 0 ustar mg mg 0000000 0000000 #!/usr/bin/env python
"""
Convert a directory with IRC logs to HTML.
Usage: logs2html.py pathname
Needs irclog2html.py. Produces an index page and a number of HTML-formatted
log files with navigational links.
Looks for *.log in a given directory. Needs an ISO 8601 date (YYYY-MM-DD or
YYYYMMDD) in the filename.
"""
from __future__ import print_function, unicode_literals
from operator import attrgetter
# Copyright (c) 2005--2013 Marius Gedminas
# latest.log.html symlink suggested by Chris Foster
#
# Released under the terms of the GNU GPL v2 or later
# https://www.gnu.org/copyleft/gpl.html
import os
import re
import sys
import glob
import datetime
import optparse
import shutil
try:
from urllib import quote
except ImportError:
from urllib.parse import quote
from . import irclog2html
from .irclog2html import VERSION, RELEASE, HOMEPAGE, escape
# If someone packages this for a Linux distro, they'll want to patch this to
# something like /usr/share/irclog2html/irclog.css, I imagine
CSS_FILE = os.path.join(os.path.dirname(__file__), 'irclog.css')
DATE_REGEXP = re.compile(r'^.*(\d\d\d\d)-?(\d\d)-?(\d\d)')
class Error(Exception):
"""Application error."""
class LogFile:
"""IRC log file."""
def __init__(self, filename):
self.filename = filename
basename = os.path.basename(filename)
m = DATE_REGEXP.match(basename)
if not m:
raise Error("File name does not contain a YYYY-MM-DD date: %s"
% filename)
self.date = datetime.date(*map(int, m.groups()))
self.link = irclog2html.pick_output_filename(basename)
self.title = self.date.strftime('%Y-%m-%d (%A)')
def __eq__(self, other):
return isinstance(other, LogFile) and other.filename == self.filename
def __ne__(self, other):
return not self.__eq__(other)
def newfile(self):
"""Check whether the log file is new.
The log file is new if the corresponding html file does not exist
or was just generated by self.generate. This implies that navigation
links for the previous/next file need to be updated.
"""
if not hasattr(self, '_newfile'):
# Only do this once, so that self.generate() does not change
# newness
self._newfile = not os.path.exists(self.filename + ".html")
return self._newfile
def uptodate(self):
"""Check whether the HTML version of the log is up to date."""
log_mtime = os.stat(self.filename).st_mtime
try:
html_mtime = os.stat(self.filename + ".html").st_mtime
except OSError:
return False
return html_mtime > log_mtime
def generate(self, style, title_prefix='', prev=None, next=None,
extra_args=()):
"""Generate HTML for this log file."""
self.newfile() # update newness flag and remember it
argv = ['irclog2html', '-s', style]
argv.extend(extra_args)
argv += ['-t', title_prefix + self.date.strftime('%A, %Y-%m-%d')]
if prev:
argv += ['--prev-url', prev.link,
'--prev-title',
'« ' + prev.date.strftime('%A, %Y-%m-%d')]
argv += ['--index-url=index.html', '--index-title=Index']
if next:
argv += ['--next-url', next.link,
'--next-title',
next.date.strftime('%A, %Y-%m-%d') + ' »']
argv += [self.filename]
irclog2html.main(argv)
def find_log_files(directory, pattern='*.log'):
"""Find all IRC log files in a given directory.
Returns a sorted list of LogFile objects (oldest first).
"""
pattern = os.path.join(directory, pattern)
# ISO 8601 dates sort the way we need them
return sorted([
LogFile(filename)
for filename in glob.glob(pattern) + glob.glob(pattern + '.gz')
], key=attrgetter('filename'))
def write_index(outfile, title, logfiles, searchbox=False, latest_log_link=None):
"""Write an index with links to all log files."""
print("""\
%(title)s
""" % {'VERSION': VERSION, 'RELEASE': RELEASE,
'title': escape(title), 'charset': 'UTF-8'}, file=outfile)
print('
%s
' % escape(title), file=outfile)
if searchbox:
print("""
""", file=outfile)
if latest_log_link:
link = escape(quote(latest_log_link))
print('
""" % {'VERSION': VERSION, 'RELEASE': RELEASE,
'HOMEPAGE': escape(HOMEPAGE)}, file=outfile)
def main(argv=sys.argv):
progname = 'logs2html'
parser = optparse.OptionParser("usage: %prog [options] directory",
version=VERSION,
prog=progname,
description="Colourises and converts all IRC"
" logs to HTML format for easy"
" web reading.")
parser.add_option('-c', '--config', action='callback', type='str',
metavar='FILE', callback=irclog2html.do_config_file,
help="read options from a config file")
parser.add_option('-s', '--style', dest="style", default="xhtmltable",
help="format log according to specific style"
" (default: xhtmltable); passes the style name"
" to irclog2html.py")
parser.add_option('-t', '--title', dest="title", default="IRC logs",
help="title of the index page (default: IRC logs)")
parser.add_option('-p', '--prefix', dest="prefix", default="",
help="prefix for page title (e.g.:"
" 'IRC logs of #channel for ')")
parser.add_option('-f', '--force', action="store_true", dest="force",
default=False,
help="ignore mtime and regenerate all files")
parser.add_option('-S', '--searchbox', action="store_true", dest="searchbox",
default=False,
help="include a search box")
parser.add_option('--dircproxy', action='store_true', default=False,
help="dircproxy log file support (strips leading + or - from messages; off by default)")
parser.add_option('-g', '--glob-pattern', dest="pattern", default="*.log",
help="glob pattern that finds log files to be processed"
" (default: *.log)")
parser.add_option('-o', '--output-dir', dest="output_dir", default=None,
help="destination output directory"
" (default: same as input directory)")
options, args = parser.parse_args(argv[1:])
if len(args) < 1:
parser.error("missing directory name")
if len(args) > 1:
parser.error("too many arguments")
dir = args[0]
try:
process(dir, options)
except Error as e:
sys.exit("%s: %s" % (progname, e))
def process(dir, options):
"""Process log files in a given directory."""
extra_args = []
if options.searchbox:
extra_args += ['-S']
if options.dircproxy:
extra_args += ['--dircproxy']
out_dir = dir
if options.output_dir:
out_dir = options.output_dir
extra_args += ['--output-file', out_dir]
if not os.path.isdir(out_dir):
try:
os.makedirs(out_dir)
except OSError as e:
raise Error("Failed to create directory %s: %s" % (out_dir, e))
logfiles = find_log_files(dir, options.pattern)
logfiles.reverse() # newest first
for n, logfile in enumerate(logfiles):
if n > 0:
next = logfiles[n - 1]
else:
next = None
if n + 1 < len(logfiles):
prev = logfiles[n + 1]
else:
prev = None
if (options.force or not logfile.uptodate()
or prev and prev.newfile() or next and next.newfile()):
logfile.generate(options.style, options.prefix, prev, next,
extra_args)
latest_log_link = None
if logfiles and hasattr(os, "symlink"):
latest_log_link = 'latest.log.html'
move_symlink(logfiles[0].link, os.path.join(out_dir, latest_log_link))
outfilename = os.path.join(out_dir, 'index.html')
try:
outfile = open(outfilename, 'w')
except IOError as e:
raise Error("cannot open %s for writing: %s" % (outfilename, e))
try:
write_index(outfile, options.title, logfiles, options.searchbox,
latest_log_link)
finally:
outfile.close()
css_file = os.path.join(out_dir, 'irclog.css')
if not os.path.exists(css_file) and os.path.exists(CSS_FILE):
shutil.copy(CSS_FILE, css_file)
def move_symlink(src, dst):
"""Create or overwrite a symlink.
``src`` is the link target.
``dst`` is the name of the symlink.
"""
try:
os.unlink(dst)
except OSError:
pass
os.symlink(src, dst)
if __name__ == '__main__':
main()
irclog2html-2.17.2/src/irclog2html/irclogsearch.py 0000775 0001750 0001750 00000021313 13376517171 021135 0 ustar mg mg 0000000 0000000 #!/usr/bin/env python
"""
Search IRC logs (a CGI script and a WSGI app).
Expects to find logs matching the IRCLOG_GLOB pattern (default: *.log)
in the directory specified by the IRCLOG_LOCATION environment variable.
Expects the filenames to contain a ISO 8601 date (YYYY-MM-DD).
Apache configuration example:
ScriptAlias /irclogs/search /path/to/irclogsearch.py
SetEnv IRCLOG_LOCATION /path/to/irclog/files/
# Uncomment the following if your log files use a different format
#SetEnv IRCLOG_GLOB "*.log.????-??-??"
"""
# Copyright (c) 2006-2013, Marius Gedminas and contributors
#
# Released under the terms of the GNU GPL v2 or later
# https://www.gnu.org/copyleft/gpl.html
from __future__ import print_function, unicode_literals
import cgi
import cgitb
import io
import os
import re
import sys
import time
from contextlib import closing
try:
from urllib import quote
except ImportError:
from urllib.parse import quote
from .irclog2html import (LogParser, XHTMLTableStyle, NickColourizer,
escape, open_log_file, VERSION, RELEASE, HOMEPAGE)
from .logs2html import find_log_files
try:
unicode
except NameError:
# Python 3.x
unicode = str
DEFAULT_LOGFILE_PATH = os.path.dirname(__file__)
DEFAULT_LOGFILE_PATTERN = "*.log"
DATE_REGEXP = re.compile(r'^.*(\d\d\d\d)-(\d\d)-(\d\d)')
HEADER = """\
%(title)s
""" % {'VERSION': VERSION, 'RELEASE': RELEASE,
'title': escape("Search IRC logs"), 'charset': 'UTF-8'}
FOOTER = """
" % escape(query), file=stream)
print('', file=stream)
started = time.time()
date = None
prev_result = None
formatter = SearchResultFormatter(stream)
stats = SearchStats()
for result in search_irc_logs(query, stats=stats, where=where,
logfile_pattern=logfile_pattern,
limit=limit):
if date != result.date:
if prev_result:
formatter.print_suffix()
prev_result = None
if date:
print(" ", file=stream)
else:
print('
', file=stream)
print('
%s:' %
(urlescape(result.link),
result.date.strftime('%Y-%m-%d (%A)')),
file=stream)
date = result.date
if not prev_result:
formatter.print_prefix()
formatter.print_html(result)
prev_result = result
if prev_result:
formatter.print_suffix()
if date:
print("
", file=stream)
print("
", file=stream)
total_time = time.time() - started
print("
%d matches in %d log files with %d lines (%.1f seconds).
"
% (stats.matches, stats.files, stats.lines, total_time),
file=stream)
print(FOOTER, file=stream)
def unicode_stdout():
if hasattr(sys.stdout, 'buffer'):
stream = sys.stdout.buffer # Python 3
else:
stream = StdoutWrapper(sys.stdout) # Python 2
return io.TextIOWrapper(stream, 'ascii',
errors='xmlcharrefreplace',
line_buffering=True)
def search_page(stream, form, where, logfile_pattern):
if "q" not in form:
print_search_form(stream)
else:
search_text = form["q"].value
if isinstance(search_text, bytes):
search_text = search_text.decode('UTF-8')
print_search_results(search_text, stream=stream, where=where,
logfile_pattern=logfile_pattern)
def main():
"""CGI script"""
cgitb.enable()
logfile_path = os.getenv('IRCLOG_LOCATION') or DEFAULT_LOGFILE_PATH
logfile_pattern = os.getenv('IRCLOG_GLOB') or DEFAULT_LOGFILE_PATTERN
form = cgi.FieldStorage()
stream = unicode_stdout()
print_cgi_headers(stream)
search_page(stream, form, logfile_path, logfile_pattern)
if __name__ == '__main__':
main()
irclog2html-2.17.2/src/irclog2html/tests/ 0000755 0001750 0001750 00000000000 13457570524 017254 5 ustar mg mg 0000000 0000000 irclog2html-2.17.2/src/irclog2html/tests/test_irclogserver.py 0000644 0001750 0001750 00000033330 13376525145 023374 0 ustar mg mg 0000000 0000000 # -*- coding: utf-8 -*-
import datetime
import gzip
import io
import os
import shutil
import tempfile
import doctest
import unittest
from contextlib import closing
import mock
from irclog2html.irclogserver import dir_listing, parse_path, application
here = os.path.dirname(__file__)
def gzip_copy(src, dst):
with open(src, 'rb') as fi:
with closing(gzip.open(dst, 'wb')) as fo:
shutil.copyfileobj(fi, fo)
def set_up_sample():
tmpdir = tempfile.mkdtemp(prefix='irclog2html-test-')
os.mkdir(os.path.join(tmpdir, '.hidden'))
gzip_copy(os.path.join(here, 'sample.log'),
os.path.join(tmpdir, 'sample-2013-03-17.log.gz'))
shutil.copy(os.path.join(here, 'sample.log'),
os.path.join(tmpdir, 'sample-2013-03-18.log'))
with open(os.path.join(tmpdir, "index.html"), "w") as f:
f.write("This is the index")
with open(os.path.join(tmpdir, "font.css"), "w") as f:
f.write("* { font: comic sans; }")
os.mkdir(os.path.join(tmpdir, "#chan"))
with open(os.path.join(tmpdir, "#chan", "index.html"), "w") as f:
f.write("#chan index")
shutil.copy(os.path.join(here, 'sample.log'),
os.path.join(tmpdir, '#chan', 'sample-2013-03-18.log'))
return tmpdir
def clean_up_sample(tmpdir):
shutil.rmtree(tmpdir)
def doctest_parse_path():
"""Test for parse_path.
This function decides whether to search or to display a file based
on URL path:
>>> parse_path(dict(PATH_INFO='/search'))
(None, 'search')
>>> parse_path(dict(PATH_INFO='/#channel-2015-05-05.log.html'))
(None, '#channel-2015-05-05.log.html')
When there is no file name, we show the index:
>>> parse_path(dict(PATH_INFO='/'))
(None, 'index.html')
Any slashes other than the leading one result in None:
>>> parse_path(dict(PATH_INFO='/../../etc/passwd'))
(None, None)
But there is an option to serve a directory with subdir for each
channel. If IRCLOG_CHAN_DIR is defined, the first traversal step
is the first element of the returned tuple:
>>> parse_path(dict(PATH_INFO='/#random/search',
... IRCLOG_CHAN_DIR='/opt/irclog'))
('#random', 'search')
>>> parse_path(dict(PATH_INFO='/#random/',
... IRCLOG_CHAN_DIR='/opt/irclog'))
('#random', 'index.html')
If the path does not contain the channel name, tough cookies:
>>> parse_path(dict(PATH_INFO='/index.html',
... IRCLOG_CHAN_DIR='/opt/irclog'))
(None, 'index.html')
Hacking verboten:
>>> parse_path(dict(PATH_INFO='/../index.html',
... IRCLOG_CHAN_DIR='/opt/irclog'))
(None, None)
>>> parse_path(dict(PATH_INFO='/#random/../index.html',
... IRCLOG_CHAN_DIR='/opt/irclog'))
(None, None)
"""
class TestDirListing(unittest.TestCase):
def make_channel(self, name, age):
m = mock.Mock(age=age) # can't pass name here :(
m.name = name
return m
@mock.patch('irclog2html.irclogserver.find_channels')
def test_dir_listing_old_an_new(self, mock_find_channels):
mock_find_channels.return_value = [
self.make_channel(name='#cobwebs', age=datetime.timedelta(days=7.5)),
self.make_channel(name='#rainbows', age=datetime.timedelta(minutes=5)),
self.make_channel(name='#puppies', age=datetime.timedelta(days=6.5)),
]
stream = io.StringIO()
dir_listing(stream, '/all/my/logs')
response = stream.getvalue()
self.assertIn('
',
response.body)
@mock.patch("os.environ")
def test_chan_os_environ(self, environ):
os.environ.get = {"IRCLOG_CHAN_DIR": self.tmpdir}.get
response = self.request('/')
self.assertEqual(response.content_type, 'text/html; charset=UTF-8')
self.assertIn(b'IRC logs', response.body)
self.assertIn(b'#chan', response.body)
@mock.patch("os.environ")
def test_chan_search_page_os_environ(self, environ):
os.environ.get = {"IRCLOG_CHAN_DIR": self.tmpdir}.get
response = self.request(
'/#chan/search')
self.assertEqual(response.content_type, 'text/html; charset=UTF-8')
self.assertIn(b'Search IRC logs', response.body)
def test_suite():
return unittest.TestSuite([
unittest.defaultTestLoader.loadTestsFromName(__name__),
doctest.DocTestSuite()
])
irclog2html-2.17.2/src/irclog2html/tests/__init__.py 0000664 0001750 0001750 00000000000 12765062021 021342 0 ustar mg mg 0000000 0000000 irclog2html-2.17.2/src/irclog2html/tests/sample.cfg 0000664 0001750 0001750 00000000247 12765062021 021210 0 ustar mg mg 0000000 0000000 # this is a comment
# this is an option
--title='IRC logs for #mychannel'
# and this is a blank line:
# comments can also be
# indented
# more options
--searchbox
irclog2html-2.17.2/src/irclog2html/tests/test_irclog2html.py 0000644 0001750 0001750 00000075460 13243316000 023103 0 ustar mg mg 0000000 0000000 from __future__ import print_function
import doctest
import io
import os
import shutil
import sys
import tempfile
import unittest
from irclog2html.irclog2html import (
LogParser, ColourChooser, NickColourizer, AbstractStyle,
SimpleTextStyle, TextStyle, SimpleTableStyle, TableStyle,
XHTMLStyle, XHTMLTableStyle, MediaWikiStyle,
COLOURS, parse_args, main)
try:
unicode
except NameError:
# Python 3.x
unicode = str
here = os.path.dirname(__file__)
def myrepr(o):
"""Repr that drops u prefixes on unicode strings."""
if isinstance(o, tuple):
if len(o) == 1:
return '(%s, )' % ', '.join(map(myrepr, o))
else:
return '(%s)' % ', '.join(map(myrepr, o))
elif isinstance(o, unicode):
return repr(o).lstrip('u')
else:
return repr(o)
def doctest_LogParser():
r"""Tests for LogParser
I'll define a helper function to test parsing.
>>> def test(line):
... for time, what, info in LogParser([line]):
... print(myrepr(time), what, myrepr(info))
LogParser ignores empty lines
>>> test('')
>>> test('\n')
>>> test('\r\n')
All other lines result in a tuple (time, what, info)
>>> test('14:18 * mg says Hello')
'14:18' ACTION '* mg says Hello'
Usually `info` is a string, but sometimes it is a tuple
>>> test('14:18 Hello!')
'14:18' COMMENT ('mg', 'Hello!')
Newline characters are stripped from the line, if they are present
>>> test('14:18 * mg says Hello\n')
'14:18' ACTION '* mg says Hello'
>>> test('14:18 * mg says Hello\r\n')
'14:18' ACTION '* mg says Hello'
>>> test('14:18 * mg says Hello\r')
'14:18' ACTION '* mg says Hello'
If there is no timestamp on the line, LogParser returns None
>>> test('* mg says Hello')
None ACTION '* mg says Hello'
Several timestamp formats are recognized
>>> test('14:18 Hello!')
'14:18' COMMENT ('mg', 'Hello!')
>>> test('[14:18] Hello!')
'14:18' COMMENT ('mg', 'Hello!')
>>> test('[14:18:55] Hello!')
'14:18:55' COMMENT ('mg', 'Hello!')
>>> test('[2004-02-04T14:18:55] Hello!')
'2004-02-04T14:18:55' COMMENT ('mg', 'Hello!')
>>> test('[02-Feb-2004 14:18:55] Hello!')
'02-Feb-2004 14:18:55' COMMENT ('mg', 'Hello!')
>>> test('[15 Jan 08:42] +++Hello+++')
'15 Jan 08:42' COMMENT ('mg', '+++Hello+++')
>>> test('1075917300 Hello!')
'2004-02-04T17:55:00' COMMENT ('mg', 'Hello!')
Excessive metainformation is stripped from nicknames
>>> test('[15 Jan 08:42] Hello!')
'15 Jan 08:42' COMMENT ('jsmith', 'Hello!')
Greater-than signs do not confuse the parser (any more)
>>> test('14:18 apples > oranges')
'14:18' COMMENT ('mg', 'apples > oranges')
>>> test('[15 Jan 08:42] Hello > world!')
'15 Jan 08:42' COMMENT ('jsmith', 'Hello > world!')
`what` can be COMMENT...
>>> test(' text')
None COMMENT ('nick', 'text')
...ACTION...
>>> test('* nick text')
None ACTION '* nick text'
>>> test('*\tnick text')
None ACTION '*\tnick text'
...JOIN...
>>> test('*** someone joined #channel')
None JOIN '*** someone joined #channel'
>>> test('--> someone joined')
None JOIN '--> someone joined'
...PART...
>>> test('*** someone quit')
None PART '*** someone quit'
>>> test('<-- someone left #channel')
None PART '<-- someone left #channel'
...NICKCHANGE...
>>> test('*** X is now known as Y')
None NICKCHANGE ('*** X is now known as Y', 'X', 'Y')
>>> test('--- X are now known as Y')
None NICKCHANGE ('--- X are now known as Y', 'X', 'Y')
...SERVER...
>>> test('--- welcome to irc.example.org')
None SERVER '--- welcome to irc.example.org'
>>> test('*** welcome to irc.example.org')
None SERVER '*** welcome to irc.example.org'
All unrecognized lines are reported as OTHER
>>> test('what is this line doing in my IRC log file?')
None OTHER 'what is this line doing in my IRC log file?'
"""
def doctest_LogParser_dircproxy_support():
r"""Tests for LogParser
I'll define a helper function to test parsing.
>>> def test(line):
... for time, what, info in LogParser([line], dircproxy=True):
... print(myrepr(time), what, myrepr(info))
>>> test('[15 Jan 08:42] -hmm')
'15 Jan 08:42' COMMENT ('mg', 'hmm')
>>> test('[15 Jan 08:42] +this')
'15 Jan 08:42' COMMENT ('mg', 'this')
>>> test('[15 Jan 08:42] maybe')
'15 Jan 08:42' COMMENT ('mg', 'maybe')
>>> test('[15 Jan 08:42] --1')
'15 Jan 08:42' COMMENT ('mg', '-1')
>>> test('[15 Jan 08:42] ++2')
'15 Jan 08:42' COMMENT ('mg', '+2')
>>> test('[15 Jan 08:42] +-3')
'15 Jan 08:42' COMMENT ('mg', '-3')
"""
def doctest_LogParser_encodings():
r"""Tests for LogParser
I'll define a helper function to test parsing.
>>> def test(line):
... for time, what, info in LogParser([line]):
... print(myrepr(time), what, myrepr(info))
We accept input that's in UTF-8
>>> test(b'14:18 UTF-8: \xc4\x85')
'14:18' COMMENT ('mg', 'UTF-8: \u0105')
and fall back to Latin-1 (actually, Windows-1252)
>>> test(b'14:18 cp1252: \x9a')
'14:18' COMMENT ('mg', 'cp1252: \u0161')
For convenience, Unicode is also accepted
>>> test(u'14:18 hello, \u2603')
'14:18' COMMENT ('mg', 'hello, \u2603')
"""
def doctest_ColourChooser():
"""Test for ColourChooser
>>> cc = ColourChooser()
>>> print(cc.choose(0, 0))
#763e3e
>>> print(cc.choose(0, 30))
#763e3e
>>> print(cc.choose(1, 30))
#407a40
>>> print(cc.choose(30, 30))
#e47878
>>> print(cc.choose(31, 30))
#79e779
"""
def doctest_NickColourizer():
"""Test for NickColourizer
>>> nc = NickColourizer()
The API provided by NickColourizer is dict-like
>>> print(nc['mgedmin'])
#407a40
Same nick gets the same colour
>>> print(nc['mgedmin'])
#407a40
Different nicks get different colours
>>> print(nc['povbot'])
#42427e
Nick changes keep the old color
>>> nc.change('mgedmin', 'mg_away')
>>> print(nc['mg_away'])
#407a40
Old nick gets a new color
>>> print(nc['mgedmin'])
#818144
We can handle more than 30 nics
>>> for nick in range(100):
... assert nc['nick%d' % nick] != ''
"""
class BytesIOWrapper(object):
charset = 'UTF-8'
closed = False
def __init__(self, stream):
self.stream = stream
def readable(self):
return False
def writable(self):
return True
def seekable(self):
return False
def flush(self):
self.stream.flush()
def write(self, bytestr):
self.stream.write(bytestr.decode(self.charset))
self.stream.flush()
def doctest_AbstractStyle_timestamp_anchor_duplicate_timestamps():
"""Test for AbstractStyle.timestamp_anchor
>>> style = AbstractStyle(BytesIOWrapper(sys.stdout))
>>> print(style.timestamp_anchor('14:51:30'))
t14:51:30
>>> print(style.timestamp_anchor('14:51:31'))
t14:51:31
>>> print(style.timestamp_anchor('14:51:31'))
t14:51:31-2
>>> print(style.timestamp_anchor('14:51:31'))
t14:51:31-3
"""
def doctest_SimpleTextStyle():
"""Test for SimpleTextStyle
>>> style = SimpleTextStyle(BytesIOWrapper(sys.stdout))
>>> style.head('IRC logs of #channel for Monday, 2008-06-10')
IRC logs of #channel for Monday, 2008-06-10
>>> style.nicktext('02:24:17', 'mgedmin', 'Hello, world!', '#77ff77')
<mgedmin> Hello, world!
>>> style.nicktext('02:24', 'mgedmin', 'http://google.com/ has a new favicon', '#77ff77')
<mgedmin> http://google.com/ has a new favicon
>>> style.servermsg('02:25', LogParser.ACTION, '* mgedmin hacks <&>')
* mgedmin hacks <&>
>>> style.servermsg('02:26:01', LogParser.PART, '* mgedmin leaves')
* mgedmin leaves
>>> style.foot()
Generated by irclog2html.py ... by Marius Gedminas
- find it at https://mg.pov.lt/irclog2html/!
"""
def doctest_SimpleTextStyle_colourful():
"""Test for SimpleTextStyle
>>> style = SimpleTextStyle(BytesIOWrapper(sys.stdout),
... colours=dict((what, c) for name, c, what in COLOURS))
>>> style.head('IRC logs of #channel for Monday, 2008-06-10')
IRC logs of #channel for Monday, 2008-06-10
>>> style.nicktext('02:24:17', 'mgedmin', 'Hello, world!', '#77ff77')
<mgedmin> Hello, world!
>>> style.nicktext('02:24', 'mgedmin', 'http://google.com/ has a new favicon', '#77ff77')
<mgedmin> http://google.com/ has a new favicon
>>> style.servermsg('02:25', LogParser.ACTION, '* mgedmin hacks <&>')
* mgedmin hacks <&>
>>> style.servermsg('02:26:01', LogParser.PART, '* mgedmin leaves')
* mgedmin leaves
>>> style.foot()
Generated by irclog2html.py ... by Marius Gedminas
- find it at https://mg.pov.lt/irclog2html/!
"""
def doctest_TextStyle_colourful():
"""Test for TextStyle
>>> style = TextStyle(BytesIOWrapper(sys.stdout),
... colours=dict((what, c) for name, c, what in COLOURS))
>>> style.head('IRC logs of #channel for Monday, 2008-06-10')
IRC logs of #channel for Monday, 2008-06-10
>>> style.nicktext('02:24:17', 'mgedmin', 'Hello, world!', '#77ff77')
<mgedmin> Hello, world!
>>> style.nicktext('02:24', 'mgedmin', 'http://google.com/ has a new favicon', '#77ff77')
<mgedmin> http://google.com/ has a new favicon
>>> style.servermsg('02:25', LogParser.ACTION, '* mgedmin hacks <&>')
* mgedmin hacks <&>
>>> style.servermsg('02:26:01', LogParser.PART, '* mgedmin leaves')
* mgedmin leaves
>>> style.foot()
Generated by irclog2html.py ... by Marius Gedminas
- find it at https://mg.pov.lt/irclog2html/!
"""
def doctest_SimpleTableStyle():
"""Test for SimpleTableStyle
>>> style = SimpleTableStyle(BytesIOWrapper(sys.stdout))
>>> style.head('IRC logs of #channel for Monday, 2008-06-10')
IRC logs of #channel for Monday, 2008-06-10
Generated by irclog2html.py ... by Marius Gedminas
- find it at https://mg.pov.lt/irclog2html/!
"""
def doctest_TableStyle():
"""Test for TableStyle
>>> style = TableStyle(BytesIOWrapper(sys.stdout))
>>> style.head('IRC logs of #channel for Monday, 2008-06-10')
IRC logs of #channel for Monday, 2008-06-10
Generated by irclog2html.py ... by Marius Gedminas
- find it at https://mg.pov.lt/irclog2html/!
"""
def doctest_XHTMLStyle():
"""Test for XHTMLStyle
>>> style = XHTMLStyle(BytesIOWrapper(sys.stdout))
>>> style.head('IRC logs of #channel for Monday, 2008-06-10')
IRC logs of #channel for Monday, 2008-06-10
"""
def doctest_XHTMLTableStyle():
"""Test for XHTMLTableStyle
>>> style = XHTMLTableStyle(BytesIOWrapper(sys.stdout))
>>> style.head('IRC logs of #channel for Monday, 2008-06-10')
IRC logs of #channel for Monday, 2008-06-10
"""
def run(*args):
stderr = sys.stderr
try:
sys.stderr = sys.stdout
main(['logs2html'] + list(args))
except SystemExit as e:
if e.args[0] != 0:
print("SystemExit(%s)" % repr(e.args[0]))
finally:
sys.stderr = stderr
def doctest_main_can_print_help():
"""Test for main
>>> run('--help')
Usage: logs2html [options] directory
Colourises and converts all IRC logs to HTML format for easy web reading.
Options:
--version show program's version number and exit
-h, --help show this help message and exit
...
"""
def doctest_main_missing_dirname():
"""Test for main
>>> run('--style', 'tt')
Usage: logs2html [options] directory
logs2html: error: missing directory name
SystemExit(2)
"""
def doctest_main_extra_args():
"""Test for main
>>> run('dir1', 'dir2')
Usage: logs2html [options] directory
logs2html: error: too many arguments
SystemExit(2)
"""
def test_suite():
return unittest.TestSuite([
doctest.DocTestSuite(optionflags=doctest.ELLIPSIS | doctest.REPORT_NDIFF),
unittest.makeSuite(TestLogFile),
])
irclog2html-2.17.2/src/irclog2html/tests/test_main.py 0000644 0001750 0001750 00000000653 13301516525 021602 0 ustar mg mg 0000000 0000000 import doctest
# Just test that there are no syntax errors and main() can imported; there's
# no actual code in __main__.py.
def doctest_main_can_be_imported():
"""Test for __main__.py
>>> from irclog2html.__main__ import main # noqa
"""
def test_suite():
optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS | doctest.REPORT_NDIFF
return doctest.DocTestSuite(optionflags=optionflags)
irclog2html-2.17.2/src/irclog2html/tests/sample.log 0000664 0001750 0001750 00000001666 12765062021 021240 0 ustar mg mg 0000000 0000000 2005-01-08T23:33:54 *** povbot has joined #pov
2005-01-08T23:34:46 let's see if irc logging works... ąčę
2005-01-08T23:37:22
2005-01-08T23:46:35 *** povbot has joined #pov
2005-01-08T23:47:17 seen mgedmin
2005-01-08T23:47:19 !seen mgedmin
2005-01-08T23:47:19 mgedmin: mgedmin was last seen in #pov 2 seconds ago saying: seen mgedmin
2005-01-08T23:47:50 !dict bot
2005-01-08T23:47:54 mgedmin: web1913, jargon, foldoc, vera, and wn responded: vera: BOT Beginning Of Tape; vera: BOT Broadcast Online TV; web1913: Bot \Bot\, n. (Zo["o]l.) See {Bots}; vera: BOT Build, Operate and Transfer (networke); vera: BOT Back On Topic (telecommunication-slang, Usenet, IRC); wn: bot n : botfly larva; typically develops inside the body of a horse or sheep or human; foldoc: bot