PK!}4LICENCECopyright © 2017-2019 Scott Stevenson Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. PK!olw nb_clean.py"""Clean Jupyter notebooks of execution counts, metadata, and output.""" import argparse import pathlib import subprocess import sys import nbformat VERSION = "1.3.0" ATTRIBUTE = "*.ipynb filter=nb-clean" def error(message: str, code: int) -> None: """Print error message to stderr and exit with code. Parameters ---------- message : str Error message, printed to stderr. code : int Return code. """ print(f"nb-clean: error: {message}", file=sys.stderr) sys.exit(code) def git(*args: str) -> str: """Call a Git subcommand. Parameters ---------- *args : str Git subcommand and arguments. Returns ------- str stdout from Git. Examples -------- >>> git('rev-parse', '--git-dir') .git """ process = subprocess.run( ["git"] + list(args), stderr=subprocess.PIPE, stdout=subprocess.PIPE ) if process.returncode == 128: error("not in a Git repository", 64) if process.returncode: error(process.stderr, process.returncode) stdout: str = process.stdout.decode().strip() return stdout def attributes_path() -> pathlib.Path: """Get the attributes file path for the current Git repository. Returns ------- pathlib.Path Path to the Git attributes file. Examples -------- >>> attributes_path() PosixPath('.git/info/attributes') """ git_dir = git("rev-parse", "--git-dir") return pathlib.Path(git_dir) / "info" / "attributes" def print_version(_: argparse.Namespace) -> None: """Print the version number. Parameters ---------- args : argparse.Namespace Arguments parsed from the command line. """ print(f"nb-clean {VERSION}") def configure_git(_: argparse.Namespace) -> None: """Configure Git repository to use nb-clean filter. Parameters ---------- args : argparse.Namespace Arguments parsed from the command line. """ git("config", "filter.nb-clean.clean", "nb-clean clean") attributes = attributes_path() if attributes.is_file() and ATTRIBUTE in attributes.read_text(): return with attributes.open("a") as file: file.write(f"\n{ATTRIBUTE}\n") def unconfigure_git(_: argparse.Namespace) -> None: """Remove nb-clean filter from the Git repository. Parameters ---------- args : argparse.Namespace Arguments parsed from the command line. """ attributes = attributes_path() if attributes.is_file(): original_contents = attributes.read_text().split("\n") revised_contents = [ line for line in original_contents if line != ATTRIBUTE ] attributes.write_text("\n".join(revised_contents)) git("config", "--remove-section", "filter.nb-clean") def clean(args: argparse.Namespace) -> None: """Clean notebook of execution counts, metadata, and output. Parameters ---------- args : argparse.Namespace Arguments parsed from the command line. """ notebook = nbformat.read(args.input, as_version=nbformat.NO_CONVERT) for cell in notebook.cells: cell["metadata"] = {} if cell["cell_type"] == "code": cell["execution_count"] = None cell["outputs"] = [] nbformat.write(notebook, args.output) def main() -> None: """Parse command line arguments and call corresponding function.""" parser = argparse.ArgumentParser(allow_abbrev=False, description=__doc__) subparsers = parser.add_subparsers(dest="subcommand") subparsers.required = True version_parser = subparsers.add_parser( "version", help="print version number" ) version_parser.set_defaults(func=print_version) configure_parser = subparsers.add_parser( "configure-git", help="configure Git filter to clean notebooks before staging", ) configure_parser.set_defaults(func=configure_git) unconfigure_parser = subparsers.add_parser( "unconfigure-git", help="remove Git filter that cleans notebooks before staging", ) unconfigure_parser.set_defaults(func=unconfigure_git) clean_parser = subparsers.add_parser( "clean", help="clean notebook of cell execution counts, metadata, and outputs", ) clean_parser.add_argument( "-i", "--input", nargs="?", type=argparse.FileType("r"), default=sys.stdin, help="input file", ) clean_parser.add_argument( "-o", "--output", nargs="?", type=argparse.FileType("w"), default=sys.stdout, help="output file", ) clean_parser.set_defaults(func=clean) args = parser.parse_args() args.func(args) if __name__ == "__main__": main() PK!H}r(*)nb_clean-1.3.0.dist-info/entry_points.txtN+I/N.,()KMIM̳K3r3PK!HڽTUnb_clean-1.3.0.dist-info/WHEEL A н#Z;/"d&F[xzw@Zpy3Fv]\fi4WZ^EgM_-]#0(q7PK!H9E[ !nb_clean-1.3.0.dist-info/METADATAVn7}W q.5u㦂E0 jw$1,/p.ڼ̙3~(e\|-,Z4b;//31Mm+}7+ޅ_"z06ڇKᱏQf%~-Nr ZNm|&XS 'ު,p3X߄1|eRiLqm;䭽V*=?ʊ;3)tI~xQ{E_iZ*$kֵh^`w)V$އn/r_xFv 5j ubxm21iM%6;Nz$̓AY*l1!n"pU$L2EKlZjY$@G>IMNj:Xr) %i@i:OtC4%<&hoCI i֒ 8 3)[fnrs?fN1?/$>9)%`N)j Ɯ&D94;JC;Mϼ43|9(t#N\ʃî)`|@yQ*a+"zO4G\6/b-Lnjm7;&j=Av6j<|QrTOZk U?X6݋a@eUYQ豥0>WI2rG#-'U8mHqz)2>ƞ%7-UVH]*י[\lzC+Iʺ\Qa /QÈ"E0 Qm cF4h~jd #~Ui ? 0W:'QT!?UY>r$CQ6Ic 鯂l(1*B9uB92*6DPK!H7p(nb_clean-1.3.0.dist-info/RECORD}Ir@@}df J@6覑'-W‡t=M Ic=Nt,=ƴ/!?g+D^z#8yB$fؚ ֮ IȪ)lyS-T2IgKTVt ='};Ǐ }GS,ZUnqJ9cS6#mUm suj1`k#yp`$.F)Nifyj Yѕ_Wu/{C\F.=,paS&ZőQVG t޾PK!}4LICENCEPK!olw nb_clean.pyPK!H}r(*))nb_clean-1.3.0.dist-info/entry_points.txtPK!HڽTUnb_clean-1.3.0.dist-info/WHEELPK!H9E[ !(nb_clean-1.3.0.dist-info/METADATAPK!H7p(nb_clean-1.3.0.dist-info/RECORDPK