From a1d1ab5d0ed4e8dde13a6b40c3f2a4eb980b70c0 Mon Sep 17 00:00:00 2001 From: Nicholas Bollweg Date: Thu, 10 Sep 2015 02:06:39 -0400 Subject: [PATCH] initial crack at storing in metadata --- .gitignore | 1 + .../watermark-checkpoint.ipynb | 434 ------------------ setup.py | 27 ++ watermark.py | 219 +++++---- 4 files changed, 164 insertions(+), 517 deletions(-) delete mode 100644 docs/.ipynb_checkpoints/watermark-checkpoint.ipynb create mode 100644 setup.py diff --git a/.gitignore b/.gitignore index 5810e5f..65bc5d2 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,4 @@ coverage.xml # Sphinx documentation docs/_build/ +*_checkpoints* diff --git a/docs/.ipynb_checkpoints/watermark-checkpoint.ipynb b/docs/.ipynb_checkpoints/watermark-checkpoint.ipynb deleted file mode 100644 index 91f51eb..0000000 --- a/docs/.ipynb_checkpoints/watermark-checkpoint.ipynb +++ /dev/null @@ -1,434 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "[Sebastian Raschka](http://sebastianraschka.com) \n", - "\n", - "
\n", - "I would be happy to hear your comments and suggestions. \n", - "Please feel free to drop me a note via\n", - "[twitter](https://twitter.com/rasbt), [email](mailto:bluewoodtree@gmail.com), or [google+](https://plus.google.com/+SebastianRaschka).\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# IPython magic function documentation - `%watermark`" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "I wrote this simple `watermark` IPython magic function to conveniently add date- and time-stamps to my IPython notebooks. Also, I often want to document various system information, e.g., for my [Python benchmarks](https://github.com/rasbt/One-Python-benchmark-per-day) series.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Installation" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The `watermark` line magic can be directly installed from my GitHub repository via" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Installed watermark.py. To use it, type:\n", - " %load_ext watermark\n" - ] - } - ], - "source": [ - "%install_ext https://raw.githubusercontent.com/rasbt/watermark/master/watermark.py" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Loading the `%watermark` magic" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To load the `date` magic, execute the following line in your IPython notebook or current IPython shell" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "%load_ext watermark" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Usage" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "In order to display the optional `watermark` arguments, type" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "%watermark?" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
  %watermark [-a AUTHOR] [-d] [-e] [-n] [-t] [-z] [-u] [-c CUSTOM_TIME]\n",
-    "                 [-v] [-p PACKAGES] [-h] [-m] [-g] [-w]\n",
-    "\n",
-    " \n",
-    "IPython magic function to print date/time stamps \n",
-    "and various system information.\n",
-    "\n",
-    "watermark version 1.2.1\n",
-    "\n",
-    "optional arguments:\n",
-    "  -a AUTHOR, --author AUTHOR\n",
-    "                        prints author name\n",
-    "  -d, --date            prints current date as MM/DD/YYYY\n",
-    "  -e, --eurodate        prints current date as DD/MM/YYYY\n",
-    "  -n, --datename        prints date with abbrv. day and month names\n",
-    "  -t, --time            prints current time\n",
-    "  -z, --timezone        appends the local time zone\n",
-    "  -u, --updated         appends a string \"Last updated: \"\n",
-    "  -c CUSTOM_TIME, --custom_time CUSTOM_TIME\n",
-    "                        prints a valid strftime() string\n",
-    "  -v, --python          prints Python and IPython version\n",
-    "  -p PACKAGES, --packages PACKAGES\n",
-    "                        prints versions of specified Python modules and\n",
-    "                        packages\n",
-    "  -h, --hostname        prints the host name\n",
-    "  -m, --machine         prints system and machine info\n",
-    "  -g, --githash         prints current Git commit hash\n",
-    "  -w, --watermark       prints the current version of watermark\n",
-    "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
\n", - "
" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Examples" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "06/17/2015 15:04:35\n", - "\n", - "CPython 3.4.3\n", - "IPython 3.1.0\n", - "\n", - "compiler : GCC 4.2.1 (Apple Inc. build 5577)\n", - "system : Darwin\n", - "release : 14.3.0\n", - "machine : x86_64\n", - "processor : i386\n", - "CPU cores : 4\n", - "interpreter: 64bit\n" - ] - } - ], - "source": [ - "%watermark" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "06/17/2015 15:04:36 \n" - ] - } - ], - "source": [ - "%watermark -d -t" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Last updated: Wed Jun 17 2015 15:04:36 EDT\n" - ] - } - ], - "source": [ - "%watermark -u -n -t -z" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CPython 3.4.3\n", - "IPython 3.1.0\n" - ] - } - ], - "source": [ - "%watermark -v" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "compiler : GCC 4.2.1 (Apple Inc. build 5577)\n", - "system : Darwin\n", - "release : 14.3.0\n", - "machine : x86_64\n", - "processor : i386\n", - "CPU cores : 4\n", - "interpreter: 64bit\n" - ] - } - ], - "source": [ - "%watermark -m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CPython 3.4.3\n", - "IPython 3.1.0\n", - "\n", - "numpy 1.9.2\n", - "scipy 0.15.1\n", - "\n", - "compiler : GCC 4.2.1 (Apple Inc. build 5577)\n", - "system : Darwin\n", - "release : 14.3.0\n", - "machine : x86_64\n", - "processor : i386\n", - "CPU cores : 4\n", - "interpreter: 64bit\n", - "Git hash : fde9b4a1c1c0cd706a09a1c37e210755c59bffae\n" - ] - } - ], - "source": [ - "%watermark -v -m -p numpy,scipy -g" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": { - "collapsed": false - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "John Doe 06/17/2015 \n", - "\n", - "CPython 3.4.3\n", - "IPython 3.1.0\n", - "\n", - "compiler : GCC 4.2.1 (Apple Inc. build 5577)\n", - "system : Darwin\n", - "release : 14.3.0\n", - "machine : x86_64\n", - "processor : i386\n", - "CPU cores : 4\n", - "interpreter: 64bit\n" - ] - } - ], - "source": [ - "%watermark -a \"John Doe\" -d -v -m" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "
" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.4.3" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..c8ac626 --- /dev/null +++ b/setup.py @@ -0,0 +1,27 @@ +import os +from setuptools import setup + + +def read(fname): + with open(os.path.join(os.path.dirname(__file__), fname)) as f: + return f.read() + + +setup( + name="watermark", + version="1.2.2", + author="Sebastian Raschka", + author_email="mail@sebastianraschka.com", + description=("An IPython magic extension for printing date and time" + " stamps, version numbers, and hardware information"), + license="GPL3", + keywords="ipython jupyter watermark benchmark", + url="https://github.com/rasbt/watermark", + modules=['watermark'], + long_description=read('README.md'), + classifiers=[ + "Development Status :: 3 - Alpha", + "Topic :: Utilities", + "License :: OSI Approved :: GPL3 License", + ], +) diff --git a/watermark.py b/watermark.py index e5ff443..1ee062a 100644 --- a/watermark.py +++ b/watermark.py @@ -37,6 +37,9 @@ -m, --machine prints system and machine info -g, --githash prints current Git commit hash -w, --watermark prints the current version of watermark + -o, --output [output, metadata, both] + where to store watermark data + default: output Examples: @@ -45,41 +48,69 @@ """ import platform import subprocess -from time import strftime +from datetime import datetime from socket import gethostname from pkg_resources import get_distribution from multiprocessing import cpu_count +import json import IPython from IPython.core.magic import Magics, magics_class, line_magic from IPython.core.magic_arguments import argument, magic_arguments, parse_argstring +from IPython.display import display, Javascript __version__ = '1.2.2' + +class ISODateEncoder(json.JSONEncoder): + # JSON encoder that serializes datetimes to ISO 8601 strings + def default(self, obj, *args, **kwargs): + if isinstance(obj, datetime): + return obj.isoformat() + return json.JSONEncoder.default(self, obj, *args, **kwargs) + + @magics_class class WaterMark(Magics): """ IPython magic function to print date/time stamps and various system information. - """ - @magic_arguments() - @argument('-a', '--author', type=str, help='prints author name') - @argument('-d', '--date', action='store_true', help='prints current date as MM/DD/YYYY') - @argument('-e', '--eurodate', action='store_true', help='prints current date as DD/MM/YYYY') - @argument('-n', '--datename', action='store_true', help='prints date with abbrv. day and month names') - @argument('-t', '--time', action='store_true', help='prints current time') - @argument('-z', '--timezone', action='store_true', help='appends the local time zone') - @argument('-u', '--updated', action='store_true', help='appends a string "Last updated: "') - @argument('-c', '--custom_time', type=str, help='prints a valid strftime() string') - @argument('-v', '--python', action='store_true', help='prints Python and IPython version') - @argument('-p', '--packages', type=str, help='prints versions of specified Python modules and packages') - @argument('-h', '--hostname', action='store_true', help='prints the host name') - @argument('-m', '--machine', action='store_true', help='prints system and machine info') - @argument('-g', '--githash', action='store_true', help='prints current Git commit hash') - @argument('-w', '--watermark', action='store_true', help='prints the current version of watermark') @line_magic + @magic_arguments() + @argument('-a', '--author', type=str, + help='prints author name') + @argument('-d', '--date', action='store_true', + help='prints current date as MM/DD/YYYY') + @argument('-e', '--eurodate', action='store_true', + help='prints current date as DD/MM/YYYY') + @argument('-n', '--datename', action='store_true', + help='prints date with abbrv. day and month names') + @argument('-t', '--time', action='store_true', + help='prints current time') + @argument('-z', '--timezone', action='store_true', + help='appends the local time zone') + @argument('-u', '--updated', action='store_true', + help='appends a string "Last updated: "') + @argument('-c', '--custom_time', type=str, + help='prints a valid strftime() string') + @argument('-v', '--python', action='store_true', + help='prints Python and IPython version') + @argument('-p', '--packages', type=str, + help='prints versions of specified Python modules and packages') + @argument('-h', '--hostname', action='store_true', + help='prints the host name') + @argument('-m', '--machine', action='store_true', + help='prints system and machine info') + @argument('-g', '--githash', action='store_true', + help='prints current Git commit hash') + @argument('-w', '--watermark', action='store_true', + help='prints the current version of watermark') + @argument('--output', action='store', + choices=['output', 'metadata', 'both'], + default='output', + help='where to store the watermark (meta)data') def watermark(self, line): """ IPython magic function to print date/time stamps @@ -88,90 +119,112 @@ def watermark(self, line): watermark version 1.2.2 """ - self.out = '' - args = parse_argstring(self.watermark, line) - - if not any(vars(args).values()): - self.out += strftime('%m/%d/%Y %H:%M:%S') - self._get_pyversions() - self._get_sysinfo() + self.args = args = parse_argstring(self.watermark, line) + + out = list(self._get_marks(args)) + + if args.output in ['both', 'output']: + max_len = max([len(m[0]) for m in out]) + tmpl = '{:%d} : {}' % max_len + for key, value in out: + if isinstance(value, datetime): + value = value.strftime(self._date_format) + print(tmpl.format(key, value)) + + if args.output in ['both', 'metadata']: + display(Javascript('IPython.notebook.metadata.watermark = {};' + .format(json.dumps(dict(out), cls=ISODateEncoder)))) + + @property + def _date_format(self): + fmt = '' + args = self.args + + if args.date: + fmt += '%m/%d/%Y' + elif args.eurodate: + fmt += '%d/%m/%Y' + elif args.datename: + fmt += '%a %b %d %Y' + + if args.custom_time: + fmt += ' ' + args.custom_time + elif args.time: + fmt += ' %H:%M:%S' + + if (args.custom_time or args.time) and args.timezone: + fmt += '%Z' + + # if nothing else specified, apply default + return fmt or '%m/%d/%Y %H:%M:%S' + + def _get_marks(self, args): + if not any([ + value for key, value in vars(args).items() + if key not in ['output'] + ]): + for mark in self._get_updated(): + yield mark + for mark in self._get_pyversions(): + yield mark + for mark in self._get_sysinfo(): + yield mark else: if args.author: - self.out += '% s ' %args.author.strip('\'"') - if args.updated and args.author: - self.out += '\n' + yield ['Authored by', args.author.strip('\'"')] + if args.updated: - self.out += 'Last updated: ' - if args.custom_time: - self.out += '%s ' %strftime(args.custom_time) - if args.date: - self.out += '%s ' %strftime('%m/%d/%Y') - if args.eurodate: - self.out += '%s ' %strftime('%d/%m/%Y') - elif args.datename: - self.out += '%s ' %strftime('%a %b %d %Y') - if args.time: - self.out += '%s ' %strftime('%H:%M:%S') - if args.timezone: - self.out += strftime('%Z') + for mark in self._get_updated(): + yield mark + if args.python: - self._get_pyversions() + for mark in self._get_pyversions(): + yield mark + if args.packages: - self._get_packages(args.packages) + for mark in self._get_packages(args.packages): + yield mark + + if args.watermark: + yield ['watermark', __version__] + if args.machine: - self._get_sysinfo() + for mark in self._get_sysinfo(): + yield mark + if args.hostname: - space = '' - if args.machine: - space = ' ' - self.out += '\nhost name%s: %s' %(space, gethostname()) + yield ['host name', gethostname()] + if args.githash: - self._get_commit_hash(bool(args.machine)) - if args.watermark: - if self.out: - self.out += '\n' - self.out += 'watermark v. %s' %__version__ - print(self.out) + for mark in self._get_commit_hash(bool(args.machine)): + yield mark + + def _get_updated(self): + yield ['Last updated', datetime.now()] def _get_packages(self, pkgs): - if self.out: - self.out += '\n' - packages = pkgs.split(',') - for p in packages: - self.out += '\n%s %s' %(p, get_distribution(p).version) + for p in pkgs.split(','): + yield [p, get_distribution(p).version] def _get_pyversions(self): - if self.out: - self.out += '\n\n' - self.out += '%s %s\nIPython %s' %( - platform.python_implementation(), - platform.python_version(), - IPython.__version__ - ) + yield [platform.python_implementation(), platform.python_version()] + yield ['IPython', IPython.__version__] def _get_sysinfo(self): - if self.out: - self.out += '\n\n' - self.out += 'compiler : %s\nsystem : %s\n'\ - 'release : %s\nmachine : %s\n'\ - 'processor : %s\nCPU cores : %s\ninterpreter: %s'%( - platform.python_compiler(), - platform.system(), - platform.release(), - platform.machine(), - platform.processor(), - cpu_count(), - platform.architecture()[0] - ) + yield ['compiler', platform.python_compiler()] + yield ['system', platform.system()] + yield ['release', platform.release()] + yield ['machine', platform.machine()] + yield ['processor', platform.processor()] + yield ['CPU cores', cpu_count()] + yield ['interpreter', platform.architecture()[0]] def _get_commit_hash(self, machine): - process = subprocess.Popen(['git', 'rev-parse', 'HEAD'], shell=False, stdout=subprocess.PIPE) + process = subprocess.Popen(['git', 'rev-parse', 'HEAD'], + shell=False, stdout=subprocess.PIPE) git_head_hash = process.communicate()[0].strip() - space = '' - if machine: - space = ' ' - self.out += '\nGit hash%s: %s' %(space, git_head_hash.decode("utf-8")) + yield ['git hash', git_head_hash.decode('utf-8')] def load_ipython_extension(ipython):