├── .gitignore ├── .pep8speaks.yml ├── LICENSE ├── MANIFEST.in ├── README.md ├── appveyor.yml ├── binder └── requirements.txt ├── ci ├── .travis_install.sh └── .travis_test.sh ├── docs ├── images │ ├── ex1.png │ └── ex2.png └── watermark.ipynb ├── requirements.txt ├── setup.cfg ├── setup.py └── watermark ├── __init__.py ├── magic.py ├── tests ├── test_watermark.py └── test_watermark_gpu.py ├── version.py └── watermark.py /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # IDE directories 4 | .ipynb_checkpoints 5 | .vscode 6 | .idea 7 | 8 | # Byte-compiled / optimized / DLL files 9 | __pycache__/ 10 | *.py[cod] 11 | 12 | # C extensions 13 | *.so 14 | 15 | # Distribution / packaging 16 | .Python 17 | env/ 18 | bin/ 19 | build/ 20 | develop-eggs/ 21 | dist/ 22 | eggs/ 23 | lib/ 24 | lib64/ 25 | parts/ 26 | sdist/ 27 | var/ 28 | *.egg-info/ 29 | .installed.cfg 30 | *.egg 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .cache 41 | nosetests.xml 42 | coverage.xml 43 | 44 | # Translations 45 | *.mo 46 | 47 | # Mr Developer 48 | .mr.developer.cfg 49 | .project 50 | .pydevproject 51 | 52 | # Rope 53 | .ropeproject 54 | 55 | # Django stuff: 56 | *.log 57 | *.pot 58 | 59 | # Sphinx documentation 60 | docs/_build/ 61 | 62 | -------------------------------------------------------------------------------- /.pep8speaks.yml: -------------------------------------------------------------------------------- 1 | pycodestyle: 2 | max-line-length: 79 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | New BSD License 2 | 3 | Copyright (c) 2014-2022, Sebastian Raschka. 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of watermark nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | include README.md 3 | include requirements.txt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build status](https://ci.appveyor.com/api/projects/status/2q1iwyc5bbfnqxik?svg=true)](https://ci.appveyor.com/project/rasbt/watermark) 2 | [![PyPI version](https://badge.fury.io/py/watermark.svg)](http://badge.fury.io/py/watermark) 3 | ![Python 3](https://img.shields.io/badge/python-3-blue.svg) 4 | ![License](https://img.shields.io/badge/license-BSD-blue.svg) 5 | 6 | # watermark 7 | 8 | An IPython magic extension for printing date and time stamps, version numbers, and hardware information. 9 |
10 | 11 | #### Sections 12 | 13 | - [Examples](#examples) 14 | - [Installation and updating](#installation-and-updating) 15 | - [Usage](#usage) 16 | - [Development guidelines](#development-guidelines) 17 | - [Changelog](#changelog) 18 | 19 |
20 | 21 | ## Examples 22 | 23 | [[top](#sections)] 24 | 25 | ### Using watermark in Jupyter notebooks and IPython sessions 26 | 27 | 28 | 29 | 30 | 31 | 32 | **More examples can be found in this [Jupyter notebook](docs/watermark.ipynb).** 33 | 34 | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/rasbt/watermark/master?filepath=docs%2Fwatermark.ipynb) 35 | 36 |
37 | 38 | 39 | ### Using watermark as a module 40 | 41 | 42 | ```python 43 | from watermark import watermark 44 | print(watermark()) 45 | ``` 46 | 47 | ``` 48 | Last updated: 2022-09-13T16:28:56.177487-05:00 49 | 50 | Python implementation: CPython 51 | Python version : 3.9.13 52 | IPython version : 8.4.0 53 | 54 | Compiler : Clang 13.0.1 55 | OS : Darwin 56 | Release : 21.6.0 57 | Machine : arm64 58 | Processor : arm 59 | CPU cores : 10 60 | Architecture: 64bit 61 | ``` 62 | 63 | ```python 64 | print(watermark(packages="numpy,scipy")) 65 | ``` 66 | 67 | ``` 68 | numpy: 1.23.2 69 | scipy: 1.9.1 70 | ``` 71 | 72 | 73 | 74 | See `help(watermark)` for more options. 75 | 76 | 77 | 78 | ## Installation and updating 79 | 80 | [[top](#sections)] 81 | 82 | The watermark line magic can be installed by executing 83 | 84 | ```bash 85 | pip install watermark 86 | ``` 87 | 88 | Alternatively, you can install the latest development version directly from GitHub via 89 | 90 | ```bash 91 | pip install -e git+https://github.com/rasbt/watermark#egg=watermark 92 | ``` 93 | 94 |
95 | 96 | Note: 97 | 98 | To remove an old `watermark` installation (installed via the deprecated `%install_ext` magic extension), simply delete it from the ``.ipython/extensions/`` directory, which is typically located in a user's home directory. 99 | 100 | ## Usage 101 | 102 | [[top](#sections)] 103 | 104 | After successful installation, the `watermark` magic extension can be loaded via: 105 | 106 | ```python 107 | %load_ext watermark 108 | ``` 109 | 110 |
111 | 112 | To get an overview of all available commands, type: 113 | 114 | ```python 115 | %watermark? 116 | ``` 117 | 118 |
119 | 120 | ```raw 121 | %watermark [-a AUTHOR] [-gu GITHUB_USERNAME] [-e EMAIL] [-ws WEBSITE] 122 | [-d] [-n] [-t] [-i] [-z] [-u] [-c CUSTOM_TIME] [-v] 123 | [-p PACKAGES] [-co] [-h] [-m] [-g] [-r] [-b] [-w] [-iv] 124 | 125 | IPython magic function to print date/time stamps 126 | and various system information. 127 | 128 | optional arguments: 129 | -a AUTHOR, --author AUTHOR 130 | prints author name 131 | -gu GITHUB_USERNAME, --github_username GITHUB_USERNAME 132 | prints author github username 133 | -e EMAIL, --email EMAIL 134 | prints author email 135 | -ws WEBSITE, --website WEBSITE 136 | prints author or project website 137 | -d, --date prints current date as YYYY-mm-dd 138 | -n, --datename prints date with abbrv. day and month names 139 | -t, --time prints current time as HH-MM-SS 140 | -i, --iso8601 prints the combined date and time including the time 141 | zone in the ISO 8601 standard with UTC offset 142 | -z, --timezone appends the local time zone 143 | -u, --updated appends a string "Last updated: " 144 | -c CUSTOM_TIME, --custom_time CUSTOM_TIME 145 | prints a valid strftime() string 146 | -v, --python prints Python and IPython version 147 | -p PACKAGES, --packages PACKAGES 148 | prints versions of specified Python modules and 149 | packages 150 | -co, --conda prints name of current conda environment 151 | -h, --hostname prints the host name 152 | -m, --machine prints system and machine info 153 | -g, --githash prints current Git commit hash 154 | -r, --gitrepo prints current Git remote address 155 | -b, --gitbranch prints current Git branch 156 | -w, --watermark prints the current version of watermark 157 | -iv, --iversions prints the name/version of all imported modules 158 | ``` 159 | 160 |
161 | 162 | ## Development guidelines 163 | 164 | [[top](#sections)] 165 | 166 | In line with [NEP 29][nep-29], this project supports: 167 | 168 | - All minor versions of Python released 42 months prior to the project, and at minimum the two latest minor versions. 169 | 170 | [nep-29]: https://numpy.org/neps/nep-0029-deprecation_policy.html 171 | 172 |
173 | 174 | ## Changelog 175 | 176 | [[top](#sections)] 177 | 178 | #### v. 2.5.1.dev1 (TBD) 179 | 180 | - Extra args to allow printing `-d` (current date) and `-t` (current time) information without needing to use the `-u` (updated) flag. ([#99](https://github.com/rasbt/watermark/pull/99), via contribution by [Daniel Kleine](https://github.com/d-kleine)) 181 | 182 | #### v. 2.5.0 (Sep 20, 2024) 183 | 184 | - Can now capture imports retrospectively via `-iv` more reliably. ([#94](https://github.com/rasbt/watermark/pull/94), via contribution by [Martin Perier](https://github.com/martinp7)) 185 | 186 | For example, 187 | 188 | ```python 189 | from sympy import solve 190 | ``` 191 | 192 | ``` 193 | %load_ext watermark 194 | ``` 195 | 196 | ``` 197 | %watermark -iv 198 | ``` 199 | 200 | Correctly prints `sympy: 1.11.1` 201 | 202 | 203 | 204 | 205 | #### v. 2.4.3 (May 23, 2023) 206 | 207 | - Make `py3nvml` installation for GPU info optional. ([#92](https://github.com/rasbt/watermark/pull/92), via contribution by [Ben Greiner](https://github.com/bnavigator)) 208 | 209 | #### v. 2.4.1 and v 2.4.2 (May 23, 2023) 210 | 211 | - PyPI and Conda-Forge packaging fixes. 212 | 213 | #### v. 2.4.0 (May 23, 2023) 214 | 215 | - Adds a new `--gpu` flag to print out GPU information (currently limited to NVIDIA devices) ([#90](https://github.com/rasbt/watermark/pull/90), via contribution by [907Resident](https://github.com/907Resident)) 216 | 217 | 218 | #### v. 2.3.1 (May 27, 2022) 219 | 220 | - Upper limit on importlib-metadata caused trouble installing on Python 3.7. 221 | Instead pin to minimum version with Python 3.8 functionality according to https://github.com/python/importlib_metadata#compatibility ([#86](https://github.com/rasbt/watermark/pull/86), via contribution by [James Myatt](https://github.com/jamesmyatt)) 222 | 223 | #### v. 2.3.0 (January 3, 2022) 224 | 225 | - Added the following arguments: `--github_username` - for prints author github username, `--email` - for prints author email, `--website` - for prints author or project website. ([#82](https://github.com/rasbt/watermark/pull/82), via contribution by [joschkazj](https://github.com/joschkazj)) 226 | - Added a `--conda` option to print the name of the current conda environment. ([#79](https://github.com/rasbt/watermark/pull/79), via contribution by [Alexander Krasnikov](https://github.com/askras)) 227 | - It is now possible to inject globals when used outside IPython ([#80](https://github.com/rasbt/watermark/pull/80), via contribution by [ 228 | Hugo Lapré](https://github.com/Hugovdberg)). For example, version numbers of imported packages can now be obtained as follows: 229 | 230 | ```python 231 | import numpy 232 | import watermark.watermark as watermark 233 | 234 | 235 | watermark(iversions=True, globals_=globals()) 236 | ``` 237 | 238 | #### v. 2.2.0 (February 17, 2021) 239 | 240 | - Refactoring such that a `watermark()` function now also works outside IPython and Jupyter. Now, the magic `%watermark` calls `watermark()`. Calling `%watermark` via IPython and Juypter still works as usual. However, in addition the `watermark()` function can be used within regular Python for unit testing purposes etc. ([#46](https://github.com/rasbt/watermark/pull/46), via contribution by [Tymoteusz Wołodźko](https://github.com/twolodzko)) 241 | 242 | #### v. 2.1.0 (November 23, 2020) 243 | 244 | - Adopt [NEP 29][nep-29] and require Python version 3.7 or newer. ([#63](https://github.com/rasbt/watermark/pull/63), via contribution by [James Myatt](https://github.com/jamesmyatt)) 245 | - Add Python 3.8 and 3.9 to Travis CI builds. ([#63](https://github.com/rasbt/watermark/pull/63), via contribution by [James Myatt](https://github.com/jamesmyatt)) 246 | - Fix: Allow setup.py to run without install_requires already installed ([#67](https://github.com/rasbt/watermark/pull/67), via contribution by [James Myatt](https://github.com/jamesmyatt)) 247 | - Major refactoring to improve code readability ([#64](https://github.com/rasbt/watermark/pull/64) and [65](https://github.com/rasbt/watermark/pull/65), via contribution by [Bahram Aghaei](https://github.com/GreatBahram)) 248 | - Use importlib and importlib.metadata to determine package version numbers. ([#66](https://github.com/rasbt/watermark/pull/66), via contribution by [James Myatt](https://github.com/jamesmyatt)) 249 | 250 | #### v. 2.0.2 (November 19, 2019) 251 | 252 | - Support `VERSION` attributes, in addition to `__version__` attributes. 253 | 254 | #### v. 2.0.1 (October 04, 2019) 255 | 256 | - Fix `'sklearn'` vs. `'scikit-learn'` import compatibility. 257 | 258 | #### v. 2.0.0 (October 04, 2019) 259 | 260 | - Now uses `pkg_resources` as the default method for getting version numbers. 261 | - Fixes a whitespace bug when printing the timezone. 262 | 263 | #### v. 1.8.2 (July 28, 2019) 264 | 265 | - When no Python library was imported and the `--iversion` is used, print an empty string instead of raising an error. 266 | 267 | #### v. 1.8.1 (January 26, 2019) 268 | 269 | - Fixes string alignment issues when the `-iv`/`--iversion` flag is used. 270 | 271 | #### v. 1.8.0 (January 02, 2019) 272 | 273 | - The `-iv`/`--iversion` flag now also shows package versions that were imported as `from X import Y` 274 | and `import X.Y as Y`. For example, 275 | 276 | ```python 277 | import scipy as sp 278 | from sklearn import metrics 279 | import numpy.linalg as linalg 280 | ``` 281 | 282 | ``` 283 | %watermark --iversions 284 | ``` 285 | 286 | will return 287 | 288 | ``` 289 | scipy 1.1.0 290 | sklearn 0.20.1 291 | numpy 1.15.4 292 | ``` 293 | 294 | #### v. 1.7.0 (October 13, 2018) 295 | 296 | (Via contribution by [James Myatt](https://github.com/jamesmyatt)) 297 | 298 | - Shows "not installed" for version of packages/modules that cannot be imported. 299 | - Shows "unknown" for version of packages/modules when version attribute cannot be found. 300 | - Add Python 3.6 and 3.7 to Travis CI builds. 301 | - Add classifiers to setuptools configuration. 302 | 303 | #### v. 1.6.1 (June 10, 2018) 304 | 305 | - Now also includes the LICENSE file in the Python Wheels distribution 306 | 307 | #### v. 1.6.0 (Jan uary18, 2018) 308 | 309 | - Adds a new `-b`/`--gitbranch` parameter that prints the current Git branch. 310 | 311 | #### v. 1.5.0 (August 27, 2017) 312 | 313 | - Adds a new `-iv`/ `--iversions` parameter that prints the package names and version numbers of all packages that were previously imported in the current Python session. (Via contribution by [Aziz Alto](https://github.com/iamaziz)) 314 | 315 | #### v. 1.4.0 (April 18, 2017) 316 | 317 | - Adds a new `-r`/ `--gitrepo` parameter that returns the URL of Git remote name "origin". (Via contribution by [Lucy Park](https://github.com/e9t)) 318 | 319 | #### v. 1.3.4 (October 15, 2016) 320 | 321 | - Allow fetching scikit-learn's version number via `-p scikit-learn` in addition of `-p sklearn` (the former is deprecated and will not be supported in watermark > 1.7). 322 | 323 | #### v. 1.3.3 (September 1, 2016) 324 | 325 | - Includes LICENSE in MANIFEST.in for packaging 326 | 327 | #### v. 1.3.2 (August 16, 2016) 328 | 329 | - Fixes an issue where the wrong package info was obtained when using the system level Jupyter within a virtualenv environment. (Via contribrution by [Michael Bell](https://github.com/mrbell)) 330 | - Adds a new `-i`/ `--iso8601` parameter that returns the current date-time string in ISO 8601 format with offset to UTC. For instance: `2016-08-16T18:03:42-04:00`. Current caveat: Python < 3.2 requires external libraries for for computing the timezone offset, thus, Python < 3.2 will currently only print `2016-08-16T18:03:42` 331 | - Adds offsets to UTC to the default date-time string for Python >= 3.2 332 | 333 | #### v. 1.3.1 (June 6, 2016) 334 | 335 | - Fixes an issue that caused problems importing watermark using Python 2.x 336 | 337 | #### v. 1.3.0 (May 21, 2016) 338 | 339 | - Removed the deprecated the %install_ext magic so that watermark can now be installed as a regular python package via `pip` (Via contribution by [Peter Bull](https://github.com/pjbull)) 340 | 341 | #### v. 1.2.3 (January 29, 2016) 342 | 343 | - Changed date format to the unambiguous ISO-8601 format 344 | - Ditched the deprecated %install_ext function and made watermark a proper Python package 345 | - Released the new version under a more permissive newBSD [license](./LICENSE) 346 | 347 | #### v. 1.2.2 (June 17, 2015) 348 | 349 | - Changed the default date-format of `-d`, `--date` to MM/DD/YYYY, the format DD/MM/YYYY can be used via the shortcut `-e`, `--eurodate`. 350 | 351 | #### v. 1.2.1 (March 3, 2015) 352 | 353 | - Small bugfix to allow custom time string formatting. 354 | 355 | #### v. 1.2.0 (October 1, 2014) 356 | 357 | - `--watermark` command added to print the current version of watermark. 358 | - Print author name on a separate line 359 | - Fixed bug that day takes the same value as the minute if the `-n` flag is used. 360 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | build: false 2 | 3 | environment: 4 | matrix: 5 | - PYTHON_VERSION: 3.8 6 | MINICONDA: C:/Miniconda37-x64 7 | init: 8 | - ECHO %PYTHON_VERSION% %MINICONDA% 9 | - ECHO conda --version 10 | 11 | install: 12 | - set PATH=%MINICONDA%;%MINICONDA%\\Scripts;%PATH% 13 | - conda config --set always_yes yes --set changeps1 no 14 | - conda update -q conda 15 | - conda info -a 16 | - conda create -q -n test-environment python=%PYTHON_VERSION% ipython pytest 17 | - activate test-environment 18 | 19 | test_script: 20 | - set PYTHONPATH=%PYTHONPATH%;%CD% 21 | - pip install -e . 22 | - pytest -sv 23 | 24 | notifications: 25 | 26 | # Email 27 | - provider: Email 28 | to: 29 | - mail@sebastianraschka.com 30 | on_build_success: true 31 | on_build_failure: true 32 | on_build_status_changed: true 33 | -------------------------------------------------------------------------------- /binder/requirements.txt: -------------------------------------------------------------------------------- 1 | ipython 2 | numpy 3 | scipy 4 | scikit-learn 5 | jupyter 6 | py3nvml -------------------------------------------------------------------------------- /ci/.travis_install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; 6 | bash miniconda.sh -b -p $HOME/miniconda 7 | source "$HOME/miniconda/etc/profile.d/conda.sh" 8 | hash -r 9 | conda config --set always_yes yes --set changeps1 no 10 | conda update -q conda 11 | conda info -a 12 | 13 | conda create -n testenv python=$PYTHON_VERSION -c conda-forge; 14 | conda activate testenv; 15 | 16 | python --version; 17 | 18 | if [[ "$PYTHON_VERSION" == "2.7" ]]; then 19 | python -m pip install ipython; 20 | python -m pip install . --ignore-requires-python; 21 | else 22 | python -m pip install .; 23 | fi 24 | -------------------------------------------------------------------------------- /ci/.travis_test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | python -c "import IPython; print('IPython %s' % IPython.__version__)"; 6 | python -c "import watermark; print('watermark %s' % watermark.__version__)"; 7 | ipython -c "%load_ext watermark"; 8 | 9 | PYTHONPATH='.' pytest -sv -------------------------------------------------------------------------------- /docs/images/ex1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rasbt/watermark/eb56c6aa5835a0ef63105e687650f90b0dd588d6/docs/images/ex1.png -------------------------------------------------------------------------------- /docs/images/ex2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rasbt/watermark/eb56c6aa5835a0ef63105e687650f90b0dd588d6/docs/images/ex2.png -------------------------------------------------------------------------------- /docs/watermark.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# IPython magic function documentation - `%watermark`" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "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" 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "## Installation" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "The watermark line magic can be installed by executing\n", 29 | "\n", 30 | "```bash\n", 31 | "pip install watermark\n", 32 | "```\n", 33 | "\n", 34 | "Alternatively, you can install the latest development version directly from GitHub via\n", 35 | "\n", 36 | "```bash\n", 37 | "pip install -e git+https://github.com/rasbt/watermark#egg=watermark\n", 38 | "```" 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "## Loading the `%watermark` magic" 46 | ] 47 | }, 48 | { 49 | "cell_type": "markdown", 50 | "metadata": {}, 51 | "source": [ 52 | "To load the `watermark` magic, execute the following line in your IPython notebook or current IPython shell" 53 | ] 54 | }, 55 | { 56 | "cell_type": "code", 57 | "execution_count": 1, 58 | "metadata": {}, 59 | "outputs": [], 60 | "source": [ 61 | "%load_ext watermark" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "metadata": {}, 67 | "source": [ 68 | "The version of `watermark` itself can be retrieved as follows:" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": 2, 74 | "metadata": {}, 75 | "outputs": [ 76 | { 77 | "name": "stdout", 78 | "output_type": "stream", 79 | "text": [ 80 | "Watermark: 2.3.0\n", 81 | "\n" 82 | ] 83 | } 84 | ], 85 | "source": [ 86 | "%watermark --watermark" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "## Usage" 94 | ] 95 | }, 96 | { 97 | "cell_type": "markdown", 98 | "metadata": {}, 99 | "source": [ 100 | "In order to display the optional `watermark` arguments, type" 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": 3, 106 | "metadata": {}, 107 | "outputs": [ 108 | { 109 | "data": { 110 | "text/plain": [ 111 | "\u001b[0;31mDocstring:\u001b[0m\n", 112 | "::\n", 113 | "\n", 114 | " %watermark [-a AUTHOR] [-gu GITHUB_USERNAME] [-e EMAIL] [-ws WEBSITE]\n", 115 | " [-d] [-n] [-t] [-i] [-z] [-u] [-c CUSTOM_TIME] [-v]\n", 116 | " [-p PACKAGES] [-co] [-h] [-m] [-g] [-r] [-b] [-w] [-iv]\n", 117 | "\n", 118 | "IPython magic function to print date/time stamps\n", 119 | "and various system information.\n", 120 | "\n", 121 | "optional arguments:\n", 122 | " -a AUTHOR, --author AUTHOR\n", 123 | " prints author name\n", 124 | " -gu GITHUB_USERNAME, --github_username GITHUB_USERNAME\n", 125 | " prints author github username\n", 126 | " -e EMAIL, --email EMAIL\n", 127 | " prints author email\n", 128 | " -ws WEBSITE, --website WEBSITE\n", 129 | " prints author or project website\n", 130 | " -d, --date prints current date as YYYY-mm-dd\n", 131 | " -n, --datename prints date with abbrv. day and month names\n", 132 | " -t, --time prints current time as HH-MM-SS\n", 133 | " -i, --iso8601 prints the combined date and time including the time\n", 134 | " zone in the ISO 8601 standard with UTC offset\n", 135 | " -z, --timezone appends the local time zone\n", 136 | " -u, --updated appends a string \"Last updated: \"\n", 137 | " -c CUSTOM_TIME, --custom_time CUSTOM_TIME\n", 138 | " prints a valid strftime() string\n", 139 | " -v, --python prints Python and IPython version\n", 140 | " -p PACKAGES, --packages PACKAGES\n", 141 | " prints versions of specified Python modules and\n", 142 | " packages\n", 143 | " -co, --conda prints name of current conda environment\n", 144 | " -h, --hostname prints the host name\n", 145 | " -m, --machine prints system and machine info\n", 146 | " -g, --githash prints current Git commit hash\n", 147 | " -r, --gitrepo prints current Git remote address\n", 148 | " -b, --gitbranch prints current Git branch\n", 149 | " -w, --watermark prints the current version of watermark\n", 150 | " -iv, --iversions prints the name/version of all imported modules\n", 151 | "\u001b[0;31mFile:\u001b[0m ~/code/github_rasbt/watermark/watermark/magic.py\n" 152 | ] 153 | }, 154 | "metadata": {}, 155 | "output_type": "display_data" 156 | } 157 | ], 158 | "source": [ 159 | "%watermark?" 160 | ] 161 | }, 162 | { 163 | "cell_type": "markdown", 164 | "metadata": {}, 165 | "source": [ 166 | "
\n",
167 |     "%watermark [-a AUTHOR] [-gu GITHUB_USERNAME] [-e EMAIL] [-ws WEBSITE]\n",
168 |     "                 [-d] [-n] [-t] [-i] [-z] [-u] [-c CUSTOM_TIME] [-v]\n",
169 |     "                 [-p PACKAGES] [-h] [-m] [-g] [-r] [-b] [-w] [-iv]\n",
170 |     "\n",
171 |     "IPython magic function to print date/time stamps\n",
172 |     "and various system information.\n",
173 |     "\n",
174 |     "options:\n",
175 |     "  -a AUTHOR, --author AUTHOR\n",
176 |     "                        prints author name\n",
177 |     "  -gu GITHUB_USERNAME, --github_username GITHUB_USERNAME\n",
178 |     "                        prints author github username\n",
179 |     "  -e EMAIL, --email EMAIL\n",
180 |     "                        prints author email\n",
181 |     "  -ws WEBSITE, --website WEBSITE\n",
182 |     "                        prints author or project website\n",
183 |     "  -d, --date            prints current date as YYYY-mm-dd\n",
184 |     "  -n, --datename        prints date with abbrv. day and month names\n",
185 |     "  -t, --time            prints current time as HH-MM-SS\n",
186 |     "  -i, --iso8601         prints the combined date and time including the time\n",
187 |     "                        zone in the ISO 8601 standard with UTC offset\n",
188 |     "  -z, --timezone        appends the local time zone\n",
189 |     "  -u, --updated         appends a string \"Last updated: \"\n",
190 |     "  -c CUSTOM_TIME, --custom_time CUSTOM_TIME\n",
191 |     "                        prints a valid strftime() string\n",
192 |     "  -v, --python          prints Python and IPython version\n",
193 |     "  -p PACKAGES, --packages PACKAGES\n",
194 |     "                        prints versions of specified Python modules and\n",
195 |     "                        packages\n",
196 |     "  -h, --hostname        prints the host name\n",
197 |     "  -m, --machine         prints system and machine info\n",
198 |     "  -g, --githash         prints current Git commit hash\n",
199 |     "  -r, --gitrepo         prints current Git remote address\n",
200 |     "  -b, --gitbranch       prints current Git branch\n",
201 |     "  -w, --watermark       prints the current version of watermark\n",
202 |     "  -iv, --iversions      prints the name/version of all imported modules\n",
203 |     "
" 204 | ] 205 | }, 206 | { 207 | "cell_type": "markdown", 208 | "metadata": {}, 209 | "source": [ 210 | "## Examples" 211 | ] 212 | }, 213 | { 214 | "cell_type": "markdown", 215 | "metadata": {}, 216 | "source": [ 217 | "### Defaults" 218 | ] 219 | }, 220 | { 221 | "cell_type": "code", 222 | "execution_count": 4, 223 | "metadata": {}, 224 | "outputs": [ 225 | { 226 | "name": "stdout", 227 | "output_type": "stream", 228 | "text": [ 229 | "Last updated: 2022-01-03T19:44:42.841436-06:00\n", 230 | "\n", 231 | "Python implementation: CPython\n", 232 | "Python version : 3.9.6\n", 233 | "IPython version : 7.30.1\n", 234 | "\n", 235 | "Compiler : Clang 11.1.0 \n", 236 | "OS : Darwin\n", 237 | "Release : 21.1.0\n", 238 | "Machine : arm64\n", 239 | "Processor : arm\n", 240 | "CPU cores : 8\n", 241 | "Architecture: 64bit\n", 242 | "\n" 243 | ] 244 | } 245 | ], 246 | "source": [ 247 | "%watermark" 248 | ] 249 | }, 250 | { 251 | "cell_type": "markdown", 252 | "metadata": {}, 253 | "source": [ 254 | "### Last updated date and time" 255 | ] 256 | }, 257 | { 258 | "cell_type": "code", 259 | "execution_count": 5, 260 | "metadata": {}, 261 | "outputs": [ 262 | { 263 | "name": "stdout", 264 | "output_type": "stream", 265 | "text": [ 266 | "Last updated: 2022-01-03 19:44:42\n", 267 | "\n" 268 | ] 269 | } 270 | ], 271 | "source": [ 272 | "%watermark -u -t -d" 273 | ] 274 | }, 275 | { 276 | "cell_type": "code", 277 | "execution_count": 6, 278 | "metadata": {}, 279 | "outputs": [ 280 | { 281 | "name": "stdout", 282 | "output_type": "stream", 283 | "text": [ 284 | "Last updated: 2022-01-03T19:44:42.855544-06:00\n", 285 | "\n" 286 | ] 287 | } 288 | ], 289 | "source": [ 290 | "%watermark -u --iso8601" 291 | ] 292 | }, 293 | { 294 | "cell_type": "code", 295 | "execution_count": 7, 296 | "metadata": {}, 297 | "outputs": [ 298 | { 299 | "name": "stdout", 300 | "output_type": "stream", 301 | "text": [ 302 | "Last updated: Mon Jan 03 2022 19:44:42CST\n", 303 | "\n" 304 | ] 305 | } 306 | ], 307 | "source": [ 308 | "%watermark -u -n -t -z" 309 | ] 310 | }, 311 | { 312 | "cell_type": "markdown", 313 | "metadata": {}, 314 | "source": [ 315 | "### Python version information" 316 | ] 317 | }, 318 | { 319 | "cell_type": "code", 320 | "execution_count": 8, 321 | "metadata": {}, 322 | "outputs": [ 323 | { 324 | "name": "stdout", 325 | "output_type": "stream", 326 | "text": [ 327 | "Python implementation: CPython\n", 328 | "Python version : 3.9.6\n", 329 | "IPython version : 7.30.1\n", 330 | "\n" 331 | ] 332 | } 333 | ], 334 | "source": [ 335 | "%watermark -v" 336 | ] 337 | }, 338 | { 339 | "cell_type": "markdown", 340 | "metadata": {}, 341 | "source": [ 342 | "### Machine information" 343 | ] 344 | }, 345 | { 346 | "cell_type": "code", 347 | "execution_count": 9, 348 | "metadata": {}, 349 | "outputs": [ 350 | { 351 | "name": "stdout", 352 | "output_type": "stream", 353 | "text": [ 354 | "Compiler : Clang 11.1.0 \n", 355 | "OS : Darwin\n", 356 | "Release : 21.1.0\n", 357 | "Machine : arm64\n", 358 | "Processor : arm\n", 359 | "CPU cores : 8\n", 360 | "Architecture: 64bit\n", 361 | "\n" 362 | ] 363 | } 364 | ], 365 | "source": [ 366 | "%watermark -m" 367 | ] 368 | }, 369 | { 370 | "cell_type": "markdown", 371 | "metadata": {}, 372 | "source": [ 373 | "### Combination of information" 374 | ] 375 | }, 376 | { 377 | "cell_type": "code", 378 | "execution_count": 10, 379 | "metadata": {}, 380 | "outputs": [ 381 | { 382 | "name": "stdout", 383 | "output_type": "stream", 384 | "text": [ 385 | "Python implementation: CPython\n", 386 | "Python version : 3.9.6\n", 387 | "IPython version : 7.30.1\n", 388 | "\n", 389 | "numpy : 1.22.0\n", 390 | "scipy : 1.7.3\n", 391 | "sklearn: 1.0.2\n", 392 | "\n", 393 | "Compiler : Clang 11.1.0 \n", 394 | "OS : Darwin\n", 395 | "Release : 21.1.0\n", 396 | "Machine : arm64\n", 397 | "Processor : arm\n", 398 | "CPU cores : 8\n", 399 | "Architecture: 64bit\n", 400 | "\n" 401 | ] 402 | } 403 | ], 404 | "source": [ 405 | "%watermark -v -m -p numpy,scipy,sklearn " 406 | ] 407 | }, 408 | { 409 | "cell_type": "markdown", 410 | "metadata": {}, 411 | "source": [ 412 | "### With author" 413 | ] 414 | }, 415 | { 416 | "cell_type": "code", 417 | "execution_count": 11, 418 | "metadata": {}, 419 | "outputs": [ 420 | { 421 | "name": "stdout", 422 | "output_type": "stream", 423 | "text": [ 424 | "Author: John Doe\n", 425 | "\n", 426 | "Last updated: 2022-01-03\n", 427 | "\n", 428 | "Python implementation: CPython\n", 429 | "Python version : 3.9.6\n", 430 | "IPython version : 7.30.1\n", 431 | "\n", 432 | "Compiler : Clang 11.1.0 \n", 433 | "OS : Darwin\n", 434 | "Release : 21.1.0\n", 435 | "Machine : arm64\n", 436 | "Processor : arm\n", 437 | "CPU cores : 8\n", 438 | "Architecture: 64bit\n", 439 | "\n" 440 | ] 441 | } 442 | ], 443 | "source": [ 444 | "%watermark -a \"John Doe\" -u -d -v -m" 445 | ] 446 | }, 447 | { 448 | "cell_type": "markdown", 449 | "metadata": {}, 450 | "source": [ 451 | "### Imported modules information" 452 | ] 453 | }, 454 | { 455 | "cell_type": "code", 456 | "execution_count": 12, 457 | "metadata": {}, 458 | "outputs": [], 459 | "source": [ 460 | "import scipy as sp\n", 461 | "from sklearn import metrics\n", 462 | "import numpy.linalg as linalg" 463 | ] 464 | }, 465 | { 466 | "cell_type": "code", 467 | "execution_count": 13, 468 | "metadata": {}, 469 | "outputs": [ 470 | { 471 | "name": "stdout", 472 | "output_type": "stream", 473 | "text": [ 474 | "scipy : 1.7.3\n", 475 | "numpy : 1.22.0\n", 476 | "sklearn: 1.0.2\n", 477 | "\n" 478 | ] 479 | } 480 | ], 481 | "source": [ 482 | "%watermark --iversions" 483 | ] 484 | } 485 | ], 486 | "metadata": { 487 | "kernelspec": { 488 | "display_name": "Python 3 (ipykernel)", 489 | "language": "python", 490 | "name": "python3" 491 | }, 492 | "language_info": { 493 | "codemirror_mode": { 494 | "name": "ipython", 495 | "version": 3 496 | }, 497 | "file_extension": ".py", 498 | "mimetype": "text/x-python", 499 | "name": "python", 500 | "nbconvert_exporter": "python", 501 | "pygments_lexer": "ipython3", 502 | "version": "3.9.6" 503 | }, 504 | "toc": { 505 | "base_numbering": 1, 506 | "nav_menu": {}, 507 | "number_sections": true, 508 | "sideBar": true, 509 | "skip_h1_title": false, 510 | "title_cell": "Table of Contents", 511 | "title_sidebar": "Contents", 512 | "toc_cell": false, 513 | "toc_position": {}, 514 | "toc_section_display": true, 515 | "toc_window_display": false 516 | } 517 | }, 518 | "nbformat": 4, 519 | "nbformat_minor": 4 520 | } 521 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | ipython >= 6.0 2 | importlib-metadata >= 1.4 3 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | version = 2.5.1.dev1 3 | license_file = LICENSE 4 | classifiers = 5 | Development Status :: 5 - Production/Stable 6 | Framework :: IPython 7 | Intended Audience :: Developers 8 | Intended Audience :: Science/Research 9 | License :: OSI Approved :: BSD License 10 | Programming Language :: Python :: 3 11 | Programming Language :: Python :: 3.7 12 | Programming Language :: Python :: 3.8 13 | Programming Language :: Python :: 3.9 14 | Programming Language :: Python :: 3.10 15 | 16 | [options] 17 | python_requires = >=3.7 18 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Sebastian Raschka 2014-2022 2 | # IPython magic function to print date/time stamps and 3 | # various system information. 4 | # Author: Sebastian Raschka 5 | # 6 | # License: BSD 3 clause 7 | 8 | from os.path import dirname, join, realpath 9 | from textwrap import dedent 10 | 11 | from setuptools import find_packages, setup 12 | 13 | 14 | PROJECT_ROOT = dirname(realpath(__file__)) 15 | REQUIREMENTS_FILE = join(PROJECT_ROOT, "requirements.txt") 16 | 17 | with open(REQUIREMENTS_FILE) as f: 18 | install_reqs = f.read().splitlines() 19 | 20 | install_reqs.append("setuptools") 21 | 22 | # Also see settings in setup.cfg 23 | setup( 24 | name="watermark", 25 | license="newBSD", 26 | description=( 27 | "IPython magic function to print date/time stamps and " 28 | "various system information." 29 | ), 30 | author="Sebastian Raschka", 31 | author_email="mail@sebastianraschka.com", 32 | url="https://github.com/rasbt/watermark", 33 | packages=find_packages(exclude=[]), 34 | install_requires=install_reqs, 35 | extras_require={'gpu': ['py3nvml>=0.2']}, 36 | long_description=dedent( 37 | """\ 38 | An IPython magic extension for printing date and time stamps, version 39 | numbers, and hardware information. 40 | 41 | Contact 42 | ============= 43 | If you have any questions or comments about watermark, 44 | please feel free to contact me via 45 | email: mail@sebastianraschka.com 46 | 47 | This project is hosted at https://github.com/rasbt/watermark 48 | 49 | The documentation can be found at 50 | https://github.com/rasbt/watermark/blob/master/README.md""" 51 | ), 52 | ) 53 | -------------------------------------------------------------------------------- /watermark/__init__.py: -------------------------------------------------------------------------------- 1 | # Sebastian Raschka 2014-2018 2 | # IPython magic function to print date/time stamps and 3 | # various system information. 4 | # Author: Sebastian Raschka 5 | # 6 | # License: BSD 3 clause 7 | 8 | from __future__ import absolute_import 9 | 10 | from .version import __version__ 11 | 12 | from watermark.magic import * 13 | from watermark.watermark import watermark 14 | 15 | __all__ = ["watermark", "magic"] 16 | -------------------------------------------------------------------------------- /watermark/magic.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | IPython magic function to print date/time stamps and 4 | various system information. 5 | Author: Sebastian Raschka 6 | License: BSD 3 clause 7 | """ 8 | 9 | from IPython.core.magic import Magics 10 | from IPython.core.magic import magics_class 11 | from IPython.core.magic import line_magic 12 | from IPython.core.magic_arguments import argument 13 | from IPython.core.magic_arguments import magic_arguments 14 | from IPython.core.magic_arguments import parse_argstring 15 | 16 | from watermark import watermark 17 | 18 | 19 | class PackageNotFoundError(Exception): 20 | pass 21 | 22 | 23 | @magics_class 24 | class WaterMark(Magics): 25 | """ 26 | IPython magic function to print date/time stamps 27 | and various system information. 28 | """ 29 | @magic_arguments() 30 | @argument('-a', '--author', type=str, 31 | help='prints author name') 32 | @argument('-gu', '--github_username', type=str, 33 | help='prints author github username') 34 | @argument('-e', '--email', type=str, 35 | help='prints author email') 36 | @argument('-ws', '--website', type=str, 37 | help='prints author or project website') 38 | @argument('-d', '--date', action='store_true', 39 | help='prints current date as YYYY-mm-dd') 40 | @argument('-n', '--datename', action='store_true', 41 | help='prints date with abbrv. day and month names') 42 | @argument('-t', '--time', action='store_true', 43 | help='prints current time as HH-MM-SS') 44 | @argument('-i', '--iso8601', action='store_true', 45 | help='prints the combined date and time including the time zone' 46 | ' in the ISO 8601 standard with UTC offset') 47 | @argument('-z', '--timezone', action='store_true', 48 | help='appends the local time zone') 49 | @argument('-u', '--updated', action='store_true', 50 | help='appends a string "Last updated: "') 51 | @argument('-c', '--custom_time', type=str, 52 | help='prints a valid strftime() string') 53 | @argument('-v', '--python', action='store_true', 54 | help='prints Python and IPython version') 55 | @argument('-p', '--packages', type=str, 56 | help='prints versions of specified Python modules and packages') 57 | @argument('-co', '--conda', action='store_true', 58 | help='prints name of current conda environment') 59 | @argument('-h', '--hostname', action='store_true', 60 | help='prints the host name') 61 | @argument('-m', '--machine', action='store_true', 62 | help='prints system and machine info') 63 | @argument('-g', '--githash', action='store_true', 64 | help='prints current Git commit hash') 65 | @argument('-r', '--gitrepo', action='store_true', 66 | help='prints current Git remote address') 67 | @argument('-b', '--gitbranch', action='store_true', 68 | help='prints current Git branch') 69 | @argument('-w', '--watermark', action='store_true', 70 | help='prints the current version of watermark') 71 | @argument('-iv', '--iversions', action='store_true', 72 | help='prints the name/version of all imported modules') 73 | @argument('--gpu', action='store_true', 74 | help='prints GPU information (currently limited to NVIDIA GPUs),' 75 | ' if available') 76 | @line_magic 77 | def watermark(self, line): 78 | """ 79 | IPython magic function to print date/time stamps 80 | and various system information. 81 | """ 82 | args = vars(parse_argstring(self.watermark, line)) 83 | 84 | # renaming not to pollute the namespace 85 | # while preserving backward compatibility 86 | args['current_date'] = args.pop('date') 87 | args['current_time'] = args.pop('time') 88 | args['watermark_self'] = self 89 | 90 | formatted_text = watermark.watermark(**args) 91 | print(formatted_text) 92 | 93 | 94 | def load_ipython_extension(ipython): 95 | ipython.register_magics(WaterMark) 96 | -------------------------------------------------------------------------------- /watermark/tests/test_watermark.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import sys 4 | import os 5 | 6 | sys.path.append(os.path.join("../watermark")) 7 | 8 | import watermark 9 | 10 | 11 | def test_defaults(): 12 | a = watermark.watermark() 13 | txt = a.split('\n') 14 | clean_txt = [] 15 | for t in txt: 16 | t = t.strip() 17 | if t: 18 | t = t.split(':')[0] 19 | clean_txt.append(t.strip()) 20 | clean_txt = set(clean_txt) 21 | 22 | expected = [ 23 | 'Last updated', 24 | 'Python implementation', 25 | 'Python version', 26 | 'IPython version', 27 | 'Compiler', 28 | 'OS', 29 | 'Release', 30 | 'Machine', 31 | 'Processor', 32 | 'CPU cores', 33 | 'Architecture'] 34 | 35 | for i in expected: 36 | assert i in clean_txt, print(f'{i} not in {clean_txt}') 37 | -------------------------------------------------------------------------------- /watermark/tests/test_watermark_gpu.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import sys 3 | import os 4 | 5 | sys.path.append(os.path.join("../watermark")) 6 | 7 | import watermark 8 | 9 | def test_gpu_info(): 10 | a = watermark.watermark(gpu=True) 11 | txt = a.split('\n') 12 | clean_txt = [] 13 | for t in txt: 14 | t = t.strip() 15 | if t: 16 | t = t.split(':')[0] 17 | clean_txt.append(t.strip()) 18 | clean_txt = set(clean_txt) 19 | 20 | expected = [ 21 | 'GPU Info', 22 | ] 23 | 24 | for i in expected: 25 | assert i in clean_txt, print(f'{i} not in {clean_txt}') -------------------------------------------------------------------------------- /watermark/version.py: -------------------------------------------------------------------------------- 1 | try: 2 | import importlib.metadata as importlib_metadata 3 | except ImportError: 4 | # Running on pre-3.8 Python; use importlib-metadata package 5 | import importlib_metadata 6 | 7 | try: 8 | __version__ = importlib_metadata.version("watermark") 9 | except Exception: 10 | __version__ = "unknown" 11 | -------------------------------------------------------------------------------- /watermark/watermark.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Function to print date/time stamps and 4 | various system information. 5 | 6 | Authors: Sebastian Raschka , Tymoteusz Wołodźko 7 | License: BSD 3 clause 8 | """ 9 | 10 | from __future__ import absolute_import 11 | 12 | import datetime 13 | import importlib 14 | import inspect 15 | import os 16 | import platform 17 | import subprocess 18 | import time 19 | import types 20 | from multiprocessing import cpu_count 21 | from socket import gethostname 22 | 23 | 24 | try: 25 | from py3nvml import py3nvml 26 | except ImportError: 27 | py3nvml = None 28 | 29 | try: 30 | import importlib.metadata as importlib_metadata 31 | except ImportError: 32 | # Running on pre-3.8 Python; use importlib-metadata package 33 | import importlib_metadata 34 | 35 | import IPython 36 | 37 | from .version import __version__ 38 | 39 | 40 | def watermark( 41 | author=None, 42 | email=None, 43 | github_username=None, 44 | website=None, 45 | current_date=False, 46 | datename=False, 47 | current_time=False, 48 | iso8601=False, 49 | timezone=False, 50 | updated=False, 51 | custom_time=None, 52 | python=False, 53 | packages=None, 54 | conda=False, 55 | hostname=False, 56 | machine=False, 57 | githash=False, 58 | gitrepo=False, 59 | gitbranch=False, 60 | watermark=False, 61 | iversions=False, 62 | gpu=False, 63 | watermark_self=None, 64 | globals_=None 65 | ): 66 | 67 | '''Function to print date/time stamps and various system information. 68 | 69 | Parameters: 70 | =========== 71 | 72 | author : 73 | prints author name 74 | 75 | github_username : 76 | prints author github username 77 | 78 | email : 79 | prints author email 80 | 81 | website : 82 | prints author or project website 83 | 84 | current_date : 85 | prints current date as YYYY-mm-dd 86 | 87 | datename : 88 | prints date with abbrv. day and month names 89 | 90 | current_time : 91 | prints current time as HH-MM-SS 92 | 93 | iso8601 : 94 | prints the combined date and time including the time zone 95 | in the ISO 8601 standard with UTC offset 96 | 97 | timezone : 98 | appends the local time zone 99 | 100 | updated : 101 | appends a string "Last updated: " 102 | 103 | custom_time : 104 | prints a valid strftime() string 105 | 106 | python : 107 | prints Python and IPython version (if running from Jupyter) 108 | 109 | packages : 110 | prints versions of specified Python modules and packages 111 | 112 | conda : 113 | prints name of current conda environment 114 | 115 | hostname : 116 | prints the host name 117 | 118 | machine : 119 | prints system and machine info 120 | 121 | githash : 122 | prints current Git commit hash 123 | 124 | gitrepo : 125 | prints current Git remote address 126 | 127 | gitbranch : 128 | prints current Git branch 129 | 130 | watermark : 131 | prints the current version of watermark 132 | 133 | iversions : 134 | prints the name/version of all imported modules 135 | 136 | gpu : 137 | prints GPU information (currently limited to NVIDIA GPUs), if available 138 | 139 | watermark_self : 140 | instance of the watermark magics class, which is required 141 | for iversions. 142 | 143 | ''' 144 | output = [] 145 | args = locals() 146 | watermark_self = args['watermark_self'] 147 | del args['watermark_self'] 148 | 149 | if not any(args.values()) or args['iso8601']: 150 | iso_dt = _get_datetime() 151 | 152 | if not any(args.values()): 153 | args['updated'] = True 154 | output.append({"Last updated": iso_dt}) 155 | output.append(_get_pyversions()) 156 | output.append(_get_sysinfo()) 157 | else: 158 | if args['author']: 159 | output.append({"Author": args['author'].strip("'\"")}) 160 | if args['github_username']: 161 | output.append({"Github username": \ 162 | args['github_username'].strip("'\"")}) 163 | if args['email']: 164 | output.append({"Email": args['email'].strip("'\"")}) 165 | if args['website']: 166 | output.append({"Website": args['website'].strip("'\"")}) 167 | if args['updated']: 168 | value = "" 169 | if args['custom_time']: 170 | value = time.strftime(args['custom_time']) 171 | elif args['iso8601']: 172 | value = iso_dt 173 | else: 174 | values = [] 175 | if args['current_date'] or args['datename']: 176 | if args['datename']: 177 | values.append(time.strftime("%a %b %d %Y")) 178 | else: 179 | values.append(time.strftime("%Y-%m-%d")) 180 | if args['current_time']: 181 | time_str = time.strftime("%H:%M:%S") 182 | if args['timezone']: 183 | time_str += time.strftime("%Z") 184 | values.append(time_str) 185 | value = " ".join(values) 186 | output.append({"Last updated": value}) 187 | elif args['current_date'] or args['current_time']: 188 | if args['current_date'] and args['current_time']: 189 | date_str = time.strftime("%Y-%m-%d") 190 | time_str = time.strftime("%H:%M:%S") 191 | output.append({"Date/Time": f"{date_str} {time_str}"}) 192 | elif args['current_date']: 193 | output.append({"Date": time.strftime("%Y-%m-%d")}) 194 | elif args['current_time']: 195 | output.append({"Time": time.strftime("%H:%M:%S")}) 196 | if args['python']: 197 | output.append(_get_pyversions()) 198 | if args['packages']: 199 | output.append(_get_packages(args['packages'])) 200 | if args['conda']: 201 | output.append(_get_conda_env()) 202 | if args['machine']: 203 | output.append(_get_sysinfo()) 204 | if args['hostname']: 205 | output.append({"Hostname": gethostname()}) 206 | if args['githash']: 207 | output.append(_get_commit_hash(bool(args['machine']))) 208 | if args['gitrepo']: 209 | output.append(_get_git_remote_origin(bool(args['machine']))) 210 | if args['gitbranch']: 211 | output.append(_get_git_branch(bool(args['machine']))) 212 | if args['iversions']: 213 | if watermark_self: 214 | ns = watermark_self.shell.user_ns 215 | elif globals_: 216 | ns = globals_ 217 | else: 218 | raise RuntimeError( 219 | "Either `watermark_self` or `globals_` must be provided " 220 | "to show imported package versions." 221 | ) 222 | output.append(_get_all_import_versions(ns)) 223 | if args['gpu']: 224 | output.append(_get_gpu_info()) 225 | if args['watermark']: 226 | output.append({"Watermark": __version__}) 227 | 228 | return _generate_formatted_text(output) 229 | 230 | 231 | def _generate_formatted_text(list_of_dicts): 232 | result = [] 233 | for section in list_of_dicts: 234 | if section: 235 | text = "" 236 | longest = max(len(key) for key in section) 237 | for key, value in section.items(): 238 | text += f"{key.ljust(longest)}: {value}\n" 239 | result.append(text) 240 | return "\n".join(result) 241 | 242 | 243 | def _get_datetime(pattern="%Y-%m-%dT%H:%M:%S"): 244 | try: 245 | dt = datetime.datetime.now(tz=datetime.timezone.utc) 246 | iso_dt = dt.astimezone().isoformat() 247 | except AttributeError: # timezone only supported by Py >=3.2: 248 | iso_dt = time.strftime(pattern) 249 | return iso_dt 250 | 251 | 252 | def _get_packages(pkgs): 253 | packages = pkgs.split(",") 254 | return {package: _get_package_version(package) 255 | for package in packages} 256 | 257 | 258 | def _get_package_version(pkg_name): 259 | """Return the version of a given package""" 260 | if pkg_name == "scikit-learn": 261 | pkg_name = "sklearn" 262 | try: 263 | imported = importlib.import_module(pkg_name) 264 | except ImportError: 265 | version = "not installed" 266 | else: 267 | try: 268 | version = importlib_metadata.version(pkg_name) 269 | except importlib_metadata.PackageNotFoundError: 270 | try: 271 | version = imported.__version__ 272 | except AttributeError: 273 | try: 274 | version = imported.version 275 | except AttributeError: 276 | try: 277 | version = imported.version_info 278 | except AttributeError: 279 | version = "unknown" 280 | return version 281 | 282 | 283 | def _get_pyversions(): 284 | return { 285 | "Python implementation": platform.python_implementation(), 286 | "Python version": platform.python_version(), 287 | "IPython version": IPython.__version__, 288 | } 289 | 290 | 291 | def _get_sysinfo(): 292 | return { 293 | "Compiler": platform.python_compiler(), 294 | "OS": platform.system(), 295 | "Release": platform.release(), 296 | "Machine": platform.machine(), 297 | "Processor": platform.processor(), 298 | "CPU cores": cpu_count(), 299 | "Architecture": platform.architecture()[0], 300 | } 301 | 302 | 303 | def _get_commit_hash(machine): 304 | process = subprocess.Popen( 305 | ["git", "rev-parse", "HEAD"], shell=False, stdout=subprocess.PIPE 306 | ) 307 | git_head_hash = process.communicate()[0].strip() 308 | return {"Git hash": git_head_hash.decode("utf-8")} 309 | 310 | 311 | def _get_git_remote_origin(machine): 312 | process = subprocess.Popen( 313 | ["git", "config", "--get", "remote.origin.url"], 314 | shell=False, 315 | stdout=subprocess.PIPE, 316 | ) 317 | git_remote_origin = process.communicate()[0].strip() 318 | return {"Git repo": git_remote_origin.decode("utf-8")} 319 | 320 | 321 | def _get_git_branch(machine): 322 | process = subprocess.Popen( 323 | ["git", "rev-parse", "--abbrev-ref", "HEAD"], 324 | shell=False, 325 | stdout=subprocess.PIPE, 326 | ) 327 | git_branch = process.communicate()[0].strip() 328 | return {"Git branch": git_branch.decode("utf-8")} 329 | 330 | 331 | def _get_all_import_versions(vars): 332 | to_print = {} 333 | 334 | imported_modules = { 335 | val 336 | for val in list(vars.values()) 337 | if isinstance(val, types.ModuleType) 338 | } 339 | 340 | imported_modules.update( 341 | { 342 | inspect.getmodule(val) for val in list(vars.values()) 343 | if inspect.isclass(val) or inspect.isfunction(val) 344 | } 345 | ) 346 | 347 | imported_pkgs = {module.__name__.split(".")[0] for module in imported_modules} 348 | 349 | imported_pkgs.discard("builtins") 350 | for pkg_name in imported_pkgs: 351 | pkg_version = _get_package_version(pkg_name) 352 | if pkg_version not in ("not installed", "unknown"): 353 | to_print[pkg_name] = pkg_version 354 | return to_print 355 | 356 | 357 | def _get_conda_env(): 358 | name = os.getenv('CONDA_DEFAULT_ENV', 'n/a') 359 | return {"conda environment": name} 360 | 361 | 362 | def _get_gpu_info(): 363 | if py3nvml is None: 364 | return {"GPU Info": 'Install the gpu extra ' 365 | '(pip install "watermark[gpu]") ' 366 | 'to display GPU information for NVIDIA chipsets'} 367 | try: 368 | gpu_info = [""] 369 | py3nvml.nvmlInit() 370 | num_gpus = py3nvml.nvmlDeviceGetCount() 371 | for i in range(num_gpus): 372 | handle = py3nvml.nvmlDeviceGetHandleByIndex(i) 373 | gpu_name = py3nvml.nvmlDeviceGetName(handle) 374 | gpu_info.append(f"GPU {i}: {gpu_name}") 375 | py3nvml.nvmlShutdown() 376 | return {"GPU Info": "\n ".join(gpu_info)} 377 | 378 | except py3nvml.NVMLError_LibraryNotFound: 379 | return {"GPU Info": "NVIDIA drivers do not appear " 380 | "to be installed on this machine."} 381 | except: 382 | return {"GPU Info": "GPU information is not " 383 | "available for this machine."} 384 | --------------------------------------------------------------------------------