Source code for pyensae.filehelper.magic_file

# -*- coding: utf-8 -*-
"""
Magic command to handle files


:githublink:`%|py|6`
"""
import sys
import os
import pandas

from IPython.core.magic import magics_class, line_magic, cell_magic
from IPython.core.display import HTML

from pyquickhelper.filehelper.synchelper import explore_folder_iterfile, explore_folder_iterfile_repo
from pyquickhelper.loghelper import run_cmd
from pyquickhelper.ipythonhelper import MagicCommandParser, MagicClassWithHelpers
from pyquickhelper.helpgen import docstring2html
from .format_helper import format_file_size, format_file_mtime
from .content_helper import file_head, file_tail, enumerate_grep, file_encoding


[docs]@magics_class class MagicFile(MagicClassWithHelpers): """ Defines magic commands to help with files .. faqref:: :title: Magic command not found Magic commands are automatically added when importing the module:: import pyensae This instruction does not raise any exception. To understand what went wrong, the following instruction must be run:: %load_ext pyensae Usually, one necessary module is missing. .. versionadded:: 1.1 :githublink:`%|py|43` """
[docs] @staticmethod def head_parser(): """ defines the way to parse the magic command ``%head`` :githublink:`%|py|49` """ parser = MagicCommandParser(prog="head", description='display the first lines of a text file') parser.add_argument('f', type=str, help='filename') parser.add_argument( '-n', '--n', type=int, default=10, help='number of lines to display') parser.add_argument( '-r', '--raw', default=False, action='store_true', help='display raw text instead of HTML') parser.add_argument( '-e', '--encoding', default="utf8", help='file encoding') parser.add_argument( '-s', '--errors', default="", help='What about errors: "", strict, replace, surrogateescape, ' 'xmlcharrefreplace, backslashreplace, namereplace') return parser
[docs] @line_magic def head(self, line): """ Defines ``%head`` which displays the first lines of a file. .. nbref:: :tag: file :title: head The magic command ``%head`` is equivalent to:: from pyensae.file_helper import file_head file_head(<filename>, <n>, <encoding>) :githublink:`%|py|92` """ parser = self.get_parser(MagicFile.head_parser, "head") args = self.get_args(line, parser) if args is not None: errors = args.errors if errors is not None and len(errors) < 2: errors = None encoding = args.encoding if encoding is not None and len(encoding) < 2: encoding = None rows = file_head(args.f, args.n, encoding, errors=errors) if args.raw: return "".join(rows) else: return HTML("<pre>\n{0}\n</pre>".format("".join(rows))) return None
[docs] @staticmethod def encoding_parser(): """ Defines the way to parse the magic command ``%encoding``. :githublink:`%|py|114` """ parser = MagicCommandParser(prog="encoding", description='guess the encoding of a file') parser.add_argument('f', type=str, help='filename') parser.add_argument( '-n', '--n', type=int, default=2**20, help='maximum number of lines to use to guess the encoding') return parser
[docs] @line_magic def encoding(self, line): """ Defines ``%encoding`` which guesses the encoding. .. nbref:: :tag: file :title: encoding The magic command ``%encoding`` is equivalent to:: from pyensae.file_helper import file_head file_head(<filename>, <n>, <encoding>) :githublink:`%|py|140` """ parser = self.get_parser(MagicFile.encoding_parser, "encoding") args = self.get_args(line, parser) if args is not None: res = file_encoding(args.f, args.n) return str(res) return None
[docs] @staticmethod def grep_parser(): """ defines the way to parse the magic command ``%grep`` :githublink:`%|py|153` """ parser = MagicCommandParser(prog="grep", description='display the first lines of a text file') parser.add_argument('f', type=str, help='filename') parser.add_argument('regex', type=str, help='regular expression') parser.add_argument( '-n', '--n', type=int, default=-1, help='number of lines to display, -1 for all') parser.add_argument( '-r', '--raw', default=False, action='store_true', help='display raw text instead of HTML') parser.add_argument( '-e', '--encoding', default="utf8", help='file encoding') parser.add_argument( '-s', '--errors', default="", help='What about errors: "", strict, replace, surrogateescape, ' 'xmlcharrefreplace, backslashreplace, namereplace') return parser
[docs] @line_magic def grep(self, line): """ defines ``%grep`` which displays the first lines of a file .. nbref:: :tag: file :title: grep The magic command ``%grep`` is equivalent to:: from pyensae.file_helper import enumerate_grep list(enumerate_grep(<filename>, <regex>, <encoding>)) :githublink:`%|py|197` """ parser = self.get_parser(MagicFile.grep_parser, "grep") args = self.get_args(line, parser) if args is not None: errors = args.errors if errors is not None and len(errors) < 2: errors = None encoding = args.encoding if encoding is not None and len(encoding) < 2: encoding = None iter = enumerate_grep(args.f, args.regex, encoding, errors=errors) if args.n != -1: rows = [] for r in iter: if len(rows) >= args.n: break rows.append(r) else: rows = list(iter) if args.raw: return "".join(rows) else: return HTML("<pre>\n{0}\n</pre>".format("".join(rows))) return None
[docs] @staticmethod def tail_parser(): """ defines the way to parse the magic command ``%tail`` :githublink:`%|py|229` """ parser = MagicCommandParser(prog="tail", description='display the last lines of a text file') parser.add_argument('f', type=str, help='filename') parser.add_argument( '-n', '--n', type=int, default=10, help='number of lines to display') parser.add_argument( '-r', '--raw', default=False, action='store_true', help='display raw text instead of HTML') parser.add_argument( '-e', '--encoding', default="utf8", help='file encoding') parser.add_argument( '-s', '--errors', default="", help='What about errors: "", strict, replace, surrogateescape, ' 'xmlcharrefreplace, backslashreplace, namereplace') return parser
[docs] @line_magic def tail(self, line): """ defines ``%tail`` which displays the last lines of a file .. nbref:: :tag: file :title: tail The magic command ``%tail`` is equivalent to:: from pyensae.file_helper import file_tail file_tail(<filename>, <n>, <encoding>) :githublink:`%|py|272` """ parser = self.get_parser(MagicFile.tail_parser, "tail") args = self.get_args(line, parser) if args is not None: errors = args.errors if errors is not None and len(errors) < 2: errors = None encoding = args.encoding if encoding is not None and len(encoding) < 2: encoding = None rows = file_tail(args.f, args.n, encoding, errors=errors) if args.raw: return "".join(rows) else: return HTML("<pre>\n{0}\n</pre>".format("".join(rows))) return None
[docs] @staticmethod def lsr_parser(): """ defines the way to parse the magic command ``%lsr`` :githublink:`%|py|294` """ parser = MagicCommandParser(prog="lsr", description='display the content of a folder as a dataframe') parser.add_argument( 'path', type=str, nargs="?", help='path', default=".") parser.add_argument( '-f', '--filter', type=str, default=".*", help='filter, same syntax as a regular expression') return parser
[docs] @line_magic def lsr(self, line): """ Defines ``%lsr`` which returns the content of a folder, the method stops after around 10000 files --> you should precise the filter. .. nbref:: :tag: file :title: lsr The magic command ``%lsr`` is almost equivalent to:: from pyquickhelper.file_helper import explore_folder_iterfile res = explore_folder_iterfile(<filename>, <pattern>) for f in res: print(f) :githublink:`%|py|328` """ parser = self.get_parser(MagicFile.lsr_parser, "lsr") args = self.get_args(line, parser) if args is not None: if args.path is None or len(args.path) == 0: filename = "." else: filename = args.path pattern = args.filter if "*" in filename: pattern = filename filename = "." iter = explore_folder_iterfile(filename, pattern) rows = [] for r in iter: d = os.path.isfile(r) if d: st = os.stat(r) r = {"name": r, "size": format_file_size(st.st_size), "last_modified": format_file_mtime(st.st_mtime), "directory": False} else: r = {"name": r, "directory": True} rows.append(r) return pandas.DataFrame(rows) return None
[docs] @staticmethod def PYTHON_parser(): """ Defines the way to parse the magic command ``%%PYTHON``. :githublink:`%|py|363` """ parser = MagicCommandParser(prog="PYTHON", description='the command stores the content of the cell as a local file.') parser.add_argument( 'file', type=str, help='filename') return parser
[docs] @cell_magic def PYTHON(self, line, cell=None): """ Defines command ``%%PYTHON``. .. nbref:: :title: PYTHON The magic command ``%%PYTHON`` is almost to: :: with open(<filename>, "w", encoding="utf8") as f: f.write("# -*- coding: utf8 -*-\\n") f.write(cell.replace("\\r", "")) :githublink:`%|py|387` """ parser = self.get_parser(MagicFile.PYTHON_parser, "PYTHON") args = self.get_args(line, parser) if args is not None: filename = args.file with open(filename, "w", encoding="utf8") as f: f.write("# -*- coding: utf8 -*-\n") f.write(cell.replace("\r", ""))
[docs] @staticmethod def runpy_parser(): """ Defines the way to parse the magic command ``%%runpy``. :githublink:`%|py|401` """ parser = MagicCommandParser(prog="runpy", description='run a python script which accepts standards input and ' + 'produces standard outputs, a timeout is set up at 10s') parser.add_argument( 'file', type=str, help='python file') parser.add_argument( 'args', type=str, nargs="*", help='arguments for the scripts', default=".") return parser
[docs] @cell_magic def runpy(self, line, cell=None): """ Defines command ``%%runpy``. .. nbref:: :title: runpy ``%%runpy`` runs a python script which accepts standards input and produces standard outputs, a timeout is set up at 10s. It is almost equivalent to:: from pyquickhelper.loghelper import run_cmd import sys cmd = sys.executable.replace( "pythonw", "python") + " " + filename + " " + args out, err = run_cmd( cmd, wait=True, sin=cell, communicate=True, timeout=10, shell=False) .. versionadded:: 1.1 :githublink:`%|py|438` """ parser = self.get_parser(MagicFile.runpy_parser, "runpy") args = self.get_args(line, parser) if args is not None: filename = args.file if len(filename) == 0: self.runpy("") else: args = args.args cmd = sys.executable.replace("pythonw", "python") cmd += " " + filename + " " cmd += " ".join('"{0}"'.format(_) for _ in args) if isinstance(args, list) else args tosend = cell out, err = run_cmd( cmd, wait=True, sin=tosend, communicate=True, timeout=10, shell=False) if len(err) > 0: return HTML( '<font color="#DD0000">Error</font><br /><pre>\n%s\n</pre>' % err) else: return HTML('<pre>\n%s\n</pre>' % out) return None
[docs] @staticmethod def lsrepo_parser(): """ Defines the way to parse the magic command ``%lsrepo``. :githublink:`%|py|466` """ parser = MagicCommandParser(prog="lsrepo", description='display the content of a repository (GIT or SVN)') parser.add_argument('path', type=str, nargs="?", help='path', default=".") return parser
[docs] @line_magic def lsrepo(self, line): """ Defines ``%lsrepo``. .. nbref:: :tag: file :title: lsrepo The method returns the files present in a repository (:epkg:`GIT` or :pkg:`SVN`). The code is equivalent to:: from pyquickhelper.filehelper import explore_folder_iterfile_repo res = explore_folder_iterfile_repo(<filename>, <pattern>) for f in res: print(f) .. versionadded:: 1.1 :githublink:`%|py|491` """ parser = self.get_parser(MagicFile.lsrepo_parser, "lsrepo") args = self.get_args(line, parser) if args is not None: if args.path is None or len(args.path) == 0: filename = "." else: filename = args.path iter = explore_folder_iterfile_repo(filename) rows = [] for r in iter: d = os.path.isfile(r) if d: st = os.stat(r) r = {"name": r, "size": format_file_size(st.st_size), "last_modified": format_file_mtime(st.st_mtime), "directory": False} else: r = {"name": r, "directory": True} rows.append(r) return pandas.DataFrame(rows) return None
[docs] @staticmethod def hhelp_parser(): """ Defines the way to parse the magic command ``%hhelp``. .. versionadded:: 1.1 :githublink:`%|py|523` """ parser = MagicCommandParser(prog="hhelp", description='display help for an object in HTML format') parser.add_argument( 'obj', type=str, help='a python object') parser.add_argument( '-f', '--format', type=str, default="html", help='format', choices=['text', 'html', 'rst', 'rawhtml']) parser.add_argument( '-np', '--no-print', action='store_true', help='by default, the magic command outputs everything on the standard output, ' 'if specified, it returns a string') return parser
[docs] @line_magic def hhelp(self, line): """ Define ``%hhelp``, it displays the help for an object in :epkg:`HTML`. .. nbref:: :title: hhelp The magic command is equivalent to:: from pyquickhelper import docstring2html docstring2html(obj, format=format) .. versionadded:: 1.1 :githublink:`%|py|559` """ parser = self.get_parser(MagicFile.hhelp_parser, "hhelp") args = self.get_args(line, parser) if args is not None: obj = args.obj format = args.format nop = args.no_print if nop or format == "html": return docstring2html(obj, format=format) else: print(docstring2html(obj, format=format)) return None
[docs]def register_file_magics(ip=None): """ register magics function, can be called from a notebook :param ip: from ``get_ipython()`` :githublink:`%|py|579` """ if ip is None: from IPython import get_ipython ip = get_ipython() ip.register_magics(MagicFile)