PKpFQZ:mklog/__init__.py# Copyright 2009-2015 Louis Paternault # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """Some meta-information about mklog.""" VERSION = "0.3.3" PKx0Fؑ"mklog/errors.py# Copyright Louis Paternault 2011-2015 # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . 1 """Errors and exceptions""" class MklogError(Exception): """Generic error for mklog""" pass class ExecutionError(MklogError): """Error while running user command""" def __init__(self, message): super().__init__() self.message = message def __str__(self): return "Error when running '{}'.".format(" ".join(self.message)) PK9Hڕ$$ mklog/main.py# Copyright 2009-2015 Louis Paternault # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """Simple way of logging things. * "Logging" means prepending date and time at the beginning of lines. * "Things" may be content of files, standard input, or output of a command. """ from collections import namedtuple import argparse import io import logging import os import subprocess import sys import textwrap import threading import time import mklog from mklog import errors LOGGER = logging.getLogger(mklog.__name__) LOGGER.addHandler(logging.StreamHandler()) TIMEFORMAT = "%Y-%m-%d %H:%M:%S" ################################################################################ ##### Print line preceded by date and time # No verification is done whether argument contains exactly one line or not. def log(line, output_format, error=False): r"""Print argument to standard output, preceded by current time and date Arguments: - error: if True, print it to standard error, in standard output otherwise. - line: a string to print, supposed to end with an EOL character (\n). - output_format: a named tuple of two strings. - output_format.line is the line-format. It can (should?) contain substrings as "{time}" and "{output}" which are replaced by current time and the line to print. - output_format.time is the time-format. It will be passed to "time.strftime()" to print current time. """ if error: out = sys.stderr else: out = sys.stdout out.write(output_format.line.format( time=time.strftime(output_format.time), output=line[:-1], )) out.write("\n") out.flush() def log_fd(file_desc, output_format, error=False): """Print content from `file_desc`, preceding it by current date and time. :param int file_desc: File descriptor to read from. :param str output_format: format to use to print content. See :func:`log` to know its syntax. :param bool error: If `True`, print it to standard error, and in standard output otherwise. """ with os.fdopen(file_desc, errors="replace") as file: log_file(file, output_format, error) def log_file(file, output_format, error=False): """Print content from :class:`file` `file`, preceding it by current date and time. Except from `file`, arguments are the same as arguments of :func:`log_fd`. """ for line in file: log(line, output_format, error) ################################################################################ def safe_open(name): """Safely open a file, and return - None if an error occured - The file object otherwise""" try: return open(name, 'r', errors="replace") except IOError: LOGGER.error("Error while opening '%s'.", name) return None ################################################################################ ### Parsing arguments def commandline_parser(): """Parse command line Return a tuple (options, file), where: - options: a dictionary containing only the command (if any) to be executed (corresponding to option "-c") in the key "command"; - file: the list of files to be processed. """ # Defining parser parser = argparse.ArgumentParser( formatter_class=argparse.RawTextHelpFormatter, description=textwrap.dedent(""" Print the standard input, content of files, or result of a command to standard output, preceded by date and time (in a log-like way). """), epilog=textwrap.dedent(""" `mklog` aims to be a simple way to write text in a log format, i.e. each line being preceded by date and time it was written. Text can be either standard input, content of files, or both standard and error output of a command. If neither files nor a command are given, standard input is processed. Otherwise, the content of each file (if any), and the output of the command (if any) are processed. # Environment When executing command (with `-c` option), environment is preserved, and command should run exactly the same way it should have run if it had been executed directly within the shell. """), ) parser.add_argument( '--version', action='version', version="%(prog)s {version}".format( version=mklog.VERSION, ), ) parser.add_argument( "files", metavar="FILES", nargs='*', help="Files to process.", ) parser.add_argument( "-f", "--format", dest="line_format", default="{time} {output}", help=textwrap.dedent("""\ Format of output. Interpreted sequences are "{time}" for current time, "{output}" for output of the command. Default is "{time} {output}". """), ) parser.add_argument( "-t", "--time-format", dest="time_format", default=TIMEFORMAT, help=textwrap.dedent("""\ Format of time. See the "time" documentation for more information about format (e.g. http://docs.python.org/library/time.html#time.strftime). Default is "{}". """.format(TIMEFORMAT.replace('%', '%%'))), ) parser.add_argument( "-c", "--command", nargs=argparse.REMAINDER, help=textwrap.dedent(""" Run command, processing both its standard and error output. Commands can be written whithout quotes (such as `mklog -c tail -f file1 file2`), or with it, which allows using shell features (such as `mklog -c "(ls; cat file1) & cat file2"`). Destination of output is preserved: standard output of command is written to standard output of `mklog`, and standard error to standard error. Both are processed. This must be the last option on the command line. """), ) # Running parser return parser ################################################################################ ### Main function def main(): "Main function" options = commandline_parser().parse_args() # Now, "options" contains a dictionary containing only the command (if any) # to be executed (corresponding to option "-c") in the key "command", and # "files" contains the list of files to be processed. try: # Handling files # At the end of this block, "files" will contain the list of files to # be read from: either files given in argument, or standard input if no # file is given in the command line. if len(options.files) == 0 and options.command == None: options.files = [io.TextIOWrapper( sys.stdin.buffer, encoding=sys.stdin.encoding, errors="replace" )] else: options.files = [safe_open(f) for f in options.files] # Processing "options.line_format" and "options.time_format". # Quick and dirty parsing. output_format = namedtuple("Format", "line, time")( line=options.line_format, time=options.time_format, ) # Processing files for file_descriptor in options.files: if file_descriptor is None: continue log_file(file_descriptor, output_format) # Handling command if options.command != None: stdout = os.pipe() stderr = os.pipe() try: process = subprocess.Popen( options.command, stdin=sys.stdin, stdout=stdout[1], stderr=stderr[1], shell=(len(options.command) == 1), ) except OSError: raise errors.ExecutionError(options.command) standard = [ threading.Thread( target=log_fd, kwargs={ 'file_desc' : pipe[0], 'output_format': output_format }, daemon=True, ) for pipe in [stdout, stderr] ] for thread in standard: thread.start() process.wait() os.close(stderr[1]) os.close(stdout[1]) for thread in standard: thread.join() except KeyboardInterrupt: sys.exit(1) except errors.MklogError as error: LOGGER.error(error) sys.exit(1) sys.exit(0) if __name__ == "__main__": main() PK۳9H;kk%mklog-0.3.3.dist-info/DESCRIPTION.rstmklog — Convert any output into a log (date and time prepended to each line) ============================================================================ |sources| |documentation| |pypi| |license| `mklog` is a python program that converts standard input, content of files, or output of a command in a log-like format, i.e. current date and time is prepended to each line. Run `mklog --help` for the list of available options; see examples below. Example ------- Download using wget:: $ mklog -c wget https://archive.org/download/Popeye_Nearlyweds/Popeye_Nearlyweds.ogv 2015-02-05 13:13:41 --2015-02-05 13:13:41-- http://t/ 2015-02-05 13:13:41 Résolution de t (t)… échec : Nom ou service inconnu. 2015-02-05 13:13:41 wget : impossible de résoudre l'adresse de l'hôte « t » 2015-02-05 13:13:41 --2015-02-05 13:13:41-- https://archive.org/download/Popeye_Nearlyweds/Popeye_Nearlyweds.ogv 2015-02-05 13:13:41 Résolution de archive.org (archive.org)… 207.241.224.2 2015-02-05 13:13:41 Connexion à archive.org (archive.org)|207.241.224.2|:443… connecté. 2015-02-05 13:13:42 requête HTTP transmise, en attente de la réponse… 302 Moved Temporarily 2015-02-05 13:13:42 Emplacement : https://ia700502.us.archive.org/6/items/Popeye_Nearlyweds/Popeye_Nearlyweds.ogv [suivant] 2015-02-05 13:13:42 --2015-02-05 13:13:42-- https://ia700502.us.archive.org/6/items/Popeye_Nearlyweds/Popeye_Nearlyweds.ogv 2015-02-05 13:13:42 Résolution de ia700502.us.archive.org (ia700502.us.archive.org)… 207.241.237.122 2015-02-05 13:13:42 Connexion à ia700502.us.archive.org (ia700502.us.archive.org)|207.241.237.122|:443… connecté. 2015-02-05 13:13:43 requête HTTP transmise, en attente de la réponse… 200 OK 2015-02-05 13:13:43 Taille : 26698780 (25M) [video/ogg] 2015-02-05 13:13:43 Sauvegarde en : « Popeye_Nearlyweds.ogv » 2015-02-05 13:13:43 2015-02-05 13:13:44 0K .......... .......... .......... .......... .......... 0% 126K 3m26s [...] 2015-02-05 13:14:18 26000K .......... .......... .......... .......... .......... 99% 541K 0s 2015-02-05 13:14:18 26050K .......... .......... ... 100% 5,80M=34s 2015-02-05 13:14:18 2015-02-05 13:14:18 2015-02-05 13:14:18 (762 KB/s) — « Popeye_Nearlyweds.ogv » sauvegardé [26698780/26698780] 2015-02-05 13:14:18 2015-02-05 13:14:18 Terminé — 2015-02-05 13:14:18 — 2015-02-05 13:14:18 Temps total effectif : 37s 2015-02-05 13:14:18 Téléchargés : 1 fichiers, 25M en 34s (762 KB/s) Monitor logs (which are not dated):: $ tail -f /var/log/gdm3/\:0.log | mklog What's new? ----------- See `changelog `_. Download and install -------------------- See the end of list for a (quick and dirty) Debian package. * From sources: * Download: https://pypi.python.org/pypi/mklog * Install (in a `virtualenv`, not to mess with your distribution installation system):: python3 setup.py install * With pip:: pip install mklog * Quick and dirty Debian (and Ubuntu?) package This requires `stdeb `_ to be installed:: python3 setup.py --command-packages=stdeb.command bdist_deb sudo dpkg -i deb_dist/mklog-_all.deb See also -------- See also (other program with the same purpose): * `ts `_ .. |documentation| image:: http://readthedocs.org/projects/mklog/badge :target: http://mklog.readthedocs.org .. |pypi| image:: https://img.shields.io/pypi/v/mklog.svg :target: http://pypi.python.org/pypi/mklog .. |license| image:: https://img.shields.io/pypi/l/mklog.svg :target: http://www.gnu.org/licenses/gpl-3.0.html .. |sources| image:: https://img.shields.io/badge/sources-mklog-brightgreen.svg :target: http://git.framasoft.org/spalax/mklog PKҳ9Hk2J++&mklog-0.3.3.dist-info/entry_points.txt[console_scripts] mklog = mklog.main:main PK۳9HԠ#mklog-0.3.3.dist-info/metadata.json{"classifiers": ["Development Status :: 5 - Production/Stable", "Environment :: Console", "Intended Audience :: System Administrators", "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)", "Operating System :: Unix", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Topic :: System :: Logging"], "extensions": {"python.commands": {"wrap_console": {"mklog": "mklog.main:main"}}, "python.details": {"contacts": [{"email": "spalax@gresille.org", "name": "Louis Paternault", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://git.framasoft.org/spalax/mklog"}}, "python.exports": {"console_scripts": {"mklog": "mklog.main:main"}}}, "generator": "bdist_wheel (0.26.0)", "license": "GPLv3 or any later version", "metadata_version": "2.0", "name": "mklog", "summary": "Append date and time before text", "version": "0.3.3"}PKҳ9H+X#mklog-0.3.3.dist-info/top_level.txtmklog PK+ORF2mklog-0.3.3.dist-info/zip-safe PK۳9H}\\mklog-0.3.3.dist-info/WHEELWheel-Version: 1.0 Generator: bdist_wheel (0.26.0) Root-Is-Purelib: true Tag: py3-none-any PK۳9H!~]]mklog-0.3.3.dist-info/METADATAMetadata-Version: 2.0 Name: mklog Version: 0.3.3 Summary: Append date and time before text Home-page: http://git.framasoft.org/spalax/mklog Author: Louis Paternault Author-email: spalax@gresille.org License: GPLv3 or any later version Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+) Classifier: Operating System :: Unix Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Topic :: System :: Logging mklog — Convert any output into a log (date and time prepended to each line) ============================================================================ |sources| |documentation| |pypi| |license| `mklog` is a python program that converts standard input, content of files, or output of a command in a log-like format, i.e. current date and time is prepended to each line. Run `mklog --help` for the list of available options; see examples below. Example ------- Download using wget:: $ mklog -c wget https://archive.org/download/Popeye_Nearlyweds/Popeye_Nearlyweds.ogv 2015-02-05 13:13:41 --2015-02-05 13:13:41-- http://t/ 2015-02-05 13:13:41 Résolution de t (t)… échec : Nom ou service inconnu. 2015-02-05 13:13:41 wget : impossible de résoudre l'adresse de l'hôte « t » 2015-02-05 13:13:41 --2015-02-05 13:13:41-- https://archive.org/download/Popeye_Nearlyweds/Popeye_Nearlyweds.ogv 2015-02-05 13:13:41 Résolution de archive.org (archive.org)… 207.241.224.2 2015-02-05 13:13:41 Connexion à archive.org (archive.org)|207.241.224.2|:443… connecté. 2015-02-05 13:13:42 requête HTTP transmise, en attente de la réponse… 302 Moved Temporarily 2015-02-05 13:13:42 Emplacement : https://ia700502.us.archive.org/6/items/Popeye_Nearlyweds/Popeye_Nearlyweds.ogv [suivant] 2015-02-05 13:13:42 --2015-02-05 13:13:42-- https://ia700502.us.archive.org/6/items/Popeye_Nearlyweds/Popeye_Nearlyweds.ogv 2015-02-05 13:13:42 Résolution de ia700502.us.archive.org (ia700502.us.archive.org)… 207.241.237.122 2015-02-05 13:13:42 Connexion à ia700502.us.archive.org (ia700502.us.archive.org)|207.241.237.122|:443… connecté. 2015-02-05 13:13:43 requête HTTP transmise, en attente de la réponse… 200 OK 2015-02-05 13:13:43 Taille : 26698780 (25M) [video/ogg] 2015-02-05 13:13:43 Sauvegarde en : « Popeye_Nearlyweds.ogv » 2015-02-05 13:13:43 2015-02-05 13:13:44 0K .......... .......... .......... .......... .......... 0% 126K 3m26s [...] 2015-02-05 13:14:18 26000K .......... .......... .......... .......... .......... 99% 541K 0s 2015-02-05 13:14:18 26050K .......... .......... ... 100% 5,80M=34s 2015-02-05 13:14:18 2015-02-05 13:14:18 2015-02-05 13:14:18 (762 KB/s) — « Popeye_Nearlyweds.ogv » sauvegardé [26698780/26698780] 2015-02-05 13:14:18 2015-02-05 13:14:18 Terminé — 2015-02-05 13:14:18 — 2015-02-05 13:14:18 Temps total effectif : 37s 2015-02-05 13:14:18 Téléchargés : 1 fichiers, 25M en 34s (762 KB/s) Monitor logs (which are not dated):: $ tail -f /var/log/gdm3/\:0.log | mklog What's new? ----------- See `changelog `_. Download and install -------------------- See the end of list for a (quick and dirty) Debian package. * From sources: * Download: https://pypi.python.org/pypi/mklog * Install (in a `virtualenv`, not to mess with your distribution installation system):: python3 setup.py install * With pip:: pip install mklog * Quick and dirty Debian (and Ubuntu?) package This requires `stdeb `_ to be installed:: python3 setup.py --command-packages=stdeb.command bdist_deb sudo dpkg -i deb_dist/mklog-_all.deb See also -------- See also (other program with the same purpose): * `ts `_ .. |documentation| image:: http://readthedocs.org/projects/mklog/badge :target: http://mklog.readthedocs.org .. |pypi| image:: https://img.shields.io/pypi/v/mklog.svg :target: http://pypi.python.org/pypi/mklog .. |license| image:: https://img.shields.io/pypi/l/mklog.svg :target: http://www.gnu.org/licenses/gpl-3.0.html .. |sources| image:: https://img.shields.io/badge/sources-mklog-brightgreen.svg :target: http://git.framasoft.org/spalax/mklog PK۳9Hennmklog-0.3.3.dist-info/RECORDmklog/__init__.py,sha256=YzZ67bOyAdxRm3qTvdmHUrDNeWMPElC3-MS38NfLZ30,735 mklog/errors.py,sha256=igMyOwuPRR_PQD7M9iox60iTGvCwmwHJCad-AUhnAlM,1043 mklog/main.py,sha256=U_LM07TY2Of3MMDPcj0ym6A_s7KrnNEroia6oXg64vk,9469 mklog-0.3.3.dist-info/DESCRIPTION.rst,sha256=qxA9gesxbnNpi8h7aqsZBZ9JkPJHc0VmVbqm-r1mDiw,3947 mklog-0.3.3.dist-info/METADATA,sha256=s1WgzB3g1_b5dexlBPoqKU02hzcoIT_lo9LFzLnxRTY,4701 mklog-0.3.3.dist-info/RECORD,, mklog-0.3.3.dist-info/WHEEL,sha256=zX7PHtH_7K-lEzyK75et0UBa3Bj8egCBMXe1M4gc6SU,92 mklog-0.3.3.dist-info/entry_points.txt,sha256=xKtrDS2U8epapyrOHxBb_hLap_ovA_80TO0sOhaKrTc,43 mklog-0.3.3.dist-info/metadata.json,sha256=HNyx-lwpIvMipIes6pIDE7Vr2FS-Qg367U4DG46uKUM,1003 mklog-0.3.3.dist-info/top_level.txt,sha256=XbTSaY4UAgscBhFjRCQumQhtTuFMSk3KzQyzwRFXWFc,6 mklog-0.3.3.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 PKpFQZ:mklog/__init__.pyPKx0Fؑ"mklog/errors.pyPK9Hڕ$$ Nmklog/main.pyPK۳9H;kk%v,mklog-0.3.3.dist-info/DESCRIPTION.rstPKҳ9Hk2J++&$<mklog-0.3.3.dist-info/entry_points.txtPK۳9HԠ#<mklog-0.3.3.dist-info/metadata.jsonPKҳ9H+X#@mklog-0.3.3.dist-info/top_level.txtPK+ORF2Amklog-0.3.3.dist-info/zip-safePK۳9H}\\CAmklog-0.3.3.dist-info/WHEELPK۳9H!~]]Amklog-0.3.3.dist-info/METADATAPK۳9HennqTmklog-0.3.3.dist-info/RECORDPK +X