first commit

This commit is contained in:
Ayxan
2022-05-23 00:16:32 +04:00
commit d660f2a4ca
24786 changed files with 4428337 additions and 0 deletions

View File

@ -0,0 +1,20 @@
"""Backport of Python 3.11's contextlib.chdir."""
import os
from contextlib import AbstractContextManager
class chdir(AbstractContextManager):
"""Non thread-safe context manager to change the current working directory."""
def __init__(self, path):
self.path = path
self._old_cwd = []
def __enter__(self):
self._old_cwd.append(os.getcwd())
os.chdir(self.path)
def __exit__(self, *excinfo):
os.chdir(self._old_cwd.pop())

View File

@ -0,0 +1,40 @@
"""Global configuration class."""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
from traitlets import List, Unicode
from traitlets.config.configurable import LoggingConfigurable
class NbConvertBase(LoggingConfigurable):
"""Global configurable class for shared config
Useful for display data priority that might be used by many transformers
"""
display_data_priority = List(
[
"text/html",
"application/pdf",
"text/latex",
"image/svg+xml",
"image/png",
"image/jpeg",
"text/markdown",
"text/plain",
],
help="""
An ordered list of preferred output type, the first
encountered will usually be used when converting discarding
the others.
""",
).tag(config=True)
default_language = Unicode(
"ipython",
help="Deprecated default highlight language as of 5.0, please use language_info metadata instead",
).tag(config=True)
def __init__(self, **kw):
super().__init__(**kw)

View File

@ -0,0 +1,18 @@
"""NbConvert specific exceptions"""
# -----------------------------------------------------------------------------
# Copyright (c) 2013, the IPython Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Classes and functions
# -----------------------------------------------------------------------------
class ConversionException(Exception):
"""An exception raised by the conversion process."""
pass

View File

@ -0,0 +1,134 @@
"""io-related utilities"""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
import codecs
import errno
import os
import random
import shutil
import sys
def unicode_std_stream(stream="stdout"):
"""Get a wrapper to write unicode to stdout/stderr as UTF-8.
This ignores environment variables and default encodings, to reliably write
unicode to stdout or stderr.
::
unicode_std_stream().write(u'ł@e¶ŧ←')
"""
assert stream in ("stdout", "stderr")
stream = getattr(sys, stream)
try:
stream_b = stream.buffer
except AttributeError:
# sys.stdout has been replaced - use it directly
return stream
return codecs.getwriter("utf-8")(stream_b)
def unicode_stdin_stream():
"""Get a wrapper to read unicode from stdin as UTF-8.
This ignores environment variables and default encodings, to reliably read unicode from stdin.
::
totreat = unicode_stdin_stream().read()
"""
stream = sys.stdin
try:
stream_b = stream.buffer
except AttributeError:
return stream
return codecs.getreader("utf-8")(stream_b)
class FormatSafeDict(dict):
def __missing__(self, key):
return "{" + key + "}"
try:
ENOLINK = errno.ENOLINK
except AttributeError:
ENOLINK = 1998
def link(src, dst):
"""Hard links ``src`` to ``dst``, returning 0 or errno.
Note that the special errno ``ENOLINK`` will be returned if ``os.link`` isn't
supported by the operating system.
"""
if not hasattr(os, "link"):
return ENOLINK
link_errno = 0
try:
os.link(src, dst)
except OSError as e:
link_errno = e.errno
return link_errno
def link_or_copy(src, dst):
"""Attempts to hardlink ``src`` to ``dst``, copying if the link fails.
Attempts to maintain the semantics of ``shutil.copy``.
Because ``os.link`` does not overwrite files, a unique temporary file
will be used if the target already exists, then that file will be moved
into place.
"""
if os.path.isdir(dst):
dst = os.path.join(dst, os.path.basename(src))
link_errno = link(src, dst)
if link_errno == errno.EEXIST:
if os.stat(src).st_ino == os.stat(dst).st_ino:
# dst is already a hard link to the correct file, so we don't need
# to do anything else. If we try to link and rename the file
# anyway, we get duplicate files - see http://bugs.python.org/issue21876
return
new_dst = dst + f"-temp-{random.randint(1, 16**4):04X}"
try:
link_or_copy(src, new_dst)
except BaseException:
try:
os.remove(new_dst)
except OSError:
pass
raise
os.rename(new_dst, dst)
elif link_errno != 0:
# Either link isn't supported, or the filesystem doesn't support
# linking, or 'src' and 'dst' are on different filesystems.
shutil.copy(src, dst)
def ensure_dir_exists(path, mode=0o755):
"""ensure that a directory exists
If it doesn't exist, try to create it and protect against a race condition
if another process is doing the same.
The default permissions are 755, which differ from os.makedirs default of 777.
"""
if not os.path.exists(path):
try:
os.makedirs(path, mode=mode)
except OSError as e:
if e.errno != errno.EEXIST:
raise
elif not os.path.isdir(path):
raise OSError("%r exists but is not a directory" % path)

View File

@ -0,0 +1,6 @@
"""Deprecated as of 5.0; import from IPython.lib.lexers instead."""
from warnings import warn
warn("nbconvert.utils.lexers is deprecated as of 5.0. Use IPython.lib.lexers")
from IPython.lib.lexers import * # noqa

View File

@ -0,0 +1,149 @@
"""Utility for calling pandoc"""
# Copyright (c) IPython Development Team.
# Distributed under the terms of the Modified BSD License.
import re
import shutil
import subprocess
import warnings
from io import BytesIO, TextIOWrapper
from nbconvert.utils.version import check_version
from .exceptions import ConversionException
_minimal_version = "1.12.1"
_maximal_version = "3.0.0"
def pandoc(source, fmt, to, extra_args=None, encoding="utf-8"):
"""Convert an input string using pandoc.
Pandoc converts an input string `from` a format `to` a target format.
Parameters
----------
source : string
Input string, assumed to be valid format `from`.
fmt : string
The name of the input format (markdown, etc.)
to : string
The name of the output format (html, etc.)
Returns
-------
out : unicode
Output as returned by pandoc.
Raises
------
PandocMissing
If pandoc is not installed.
Any error messages generated by pandoc are printed to stderr.
"""
cmd = ["pandoc", "-f", fmt, "-t", to]
if extra_args:
cmd.extend(extra_args)
# this will raise an exception that will pop us out of here
check_pandoc_version()
# we can safely continue
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
out, _ = p.communicate(source.encode())
out = TextIOWrapper(BytesIO(out), encoding, "replace").read()
return out.rstrip("\n")
def get_pandoc_version():
"""Gets the Pandoc version if Pandoc is installed.
If the minimal version is not met, it will probe Pandoc for its version, cache it and return that value.
If the minimal version is met, it will return the cached version and stop probing Pandoc
(unless `clean_cache()` is called).
Raises
------
PandocMissing
If pandoc is unavailable.
"""
global __version
if __version is None:
if not shutil.which("pandoc"):
raise PandocMissing()
out = subprocess.check_output(["pandoc", "-v"])
out_lines = out.splitlines()
version_pattern = re.compile(r"^\d+(\.\d+){1,}$")
for tok in out_lines[0].decode("ascii", "replace").split():
if version_pattern.match(tok):
__version = tok
break
return __version
def check_pandoc_version():
"""Returns True if pandoc's version meets at least minimal version.
Raises
------
PandocMissing
If pandoc is unavailable.
"""
if check_pandoc_version._cached is not None:
return check_pandoc_version._cached
v = get_pandoc_version()
if v is None:
warnings.warn(
"Sorry, we cannot determine the version of pandoc.\n"
"Please consider reporting this issue and include the"
"output of pandoc --version.\nContinuing...",
RuntimeWarning,
stacklevel=2,
)
return False
ok = check_version(v, _minimal_version, max_v=_maximal_version)
check_pandoc_version._cached = ok
if not ok:
warnings.warn(
"You are using an unsupported version of pandoc (%s).\n" % v
+ "Your version must be at least (%s) " % _minimal_version
+ "but less than (%s).\n" % _maximal_version
+ "Refer to https://pandoc.org/installing.html.\nContinuing with doubts...",
RuntimeWarning,
stacklevel=2,
)
return ok
check_pandoc_version._cached = None
# -----------------------------------------------------------------------------
# Exception handling
# -----------------------------------------------------------------------------
class PandocMissing(ConversionException):
"""Exception raised when Pandoc is missing."""
def __init__(self, *args, **kwargs):
super().__init__(
"Pandoc wasn't found.\n" # noqa
+ "Please check that pandoc is installed:\n"
+ "https://pandoc.org/installing.html"
)
# -----------------------------------------------------------------------------
# Internal state management
# -----------------------------------------------------------------------------
def clean_cache():
global __version
__version = None
__version = None

View File

@ -0,0 +1,39 @@
"""Tests for utils.io"""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
import io as stdlib_io
import sys
from io import StringIO
from ..io import unicode_std_stream
def test_UnicodeStdStream():
# Test wrapping a bytes-level stdout
stdoutb = stdlib_io.BytesIO()
stdout = stdlib_io.TextIOWrapper(stdoutb, encoding="ascii")
orig_stdout = sys.stdout
sys.stdout = stdout
try:
sample = "@łe¶ŧ←"
unicode_std_stream().write(sample)
output = stdoutb.getvalue().decode("utf-8")
assert output == sample
assert not stdout.closed
finally:
sys.stdout = orig_stdout
def test_UnicodeStdStream_nowrap():
# If we replace stdout with a StringIO, it shouldn't get wrapped.
orig_stdout = sys.stdout
sys.stdout = StringIO()
try:
assert unicode_std_stream() is sys.stdout
assert not sys.stdout.closed
finally:
sys.stdout = orig_stdout

View File

@ -0,0 +1,81 @@
"""Test Pandoc module"""
# -----------------------------------------------------------------------------
# Copyright (C) 2014 The IPython Development Team
#
# Distributed under the terms of the BSD License. The full license is in
# the file COPYING, distributed as part of this software.
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Imports
# -----------------------------------------------------------------------------
import os
import warnings
from nbconvert.tests.base import TestsBase
from ...tests.utils import onlyif_cmds_exist
from .. import pandoc
# -----------------------------------------------------------------------------
# Classes and functions
# -----------------------------------------------------------------------------
class TestPandoc(TestsBase):
"""Collection of Pandoc tests"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.original_env = os.environ.copy()
def setUp(self):
super().setUp()
pandoc.check_pandoc_version._cached = None
@onlyif_cmds_exist("pandoc")
def test_pandoc_available(self):
"""Test behaviour that pandoc functions raise PandocMissing as documented"""
pandoc.clean_cache()
os.environ["PATH"] = ""
with self.assertRaises(pandoc.PandocMissing):
pandoc.get_pandoc_version()
with self.assertRaises(pandoc.PandocMissing):
pandoc.check_pandoc_version()
with self.assertRaises(pandoc.PandocMissing):
pandoc.pandoc("", "markdown", "html")
# original_env["PATH"] should contain pandoc
os.environ["PATH"] = self.original_env["PATH"]
with warnings.catch_warnings(record=True) as w:
pandoc.get_pandoc_version()
pandoc.check_pandoc_version()
pandoc.pandoc("", "markdown", "html")
self.assertEqual(w, [])
@onlyif_cmds_exist("pandoc")
def test_minimal_version(self):
original_minversion = pandoc._minimal_version
pandoc._minimal_version = "120.0"
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
# call it twice to verify the cached value is used
assert not pandoc.check_pandoc_version()
assert not pandoc.check_pandoc_version()
# only one warning after two calls, due to cache
self.assertEqual(len(w), 1)
# clear cache
pandoc.check_pandoc_version._cached = None
pandoc._minimal_version = pandoc.get_pandoc_version()
assert pandoc.check_pandoc_version()
def pandoc_function_raised_missing(f, *args, **kwargs):
try:
f(*args, **kwargs)
except pandoc.PandocMissing:
return True
else:
return False

View File

@ -0,0 +1,13 @@
from ..version import check_version
def test_check_version():
"""Test the behaviour of check_versionself.
This is mostly used to make sure the pandoc version is appropriate for the library.
"""
assert check_version("1.19.2.4", "1.12.1")
assert check_version("2.2.3.2", "1.12.1")
assert check_version("1.19.2.4", "1.12.1", max_v="2.0")
assert not check_version("2.2.3.2", "1.12.1", max_v="2.0")

View File

@ -0,0 +1,41 @@
import os
import re
def indent(instr, nspaces=4, ntabs=0, flatten=False):
"""Indent a string a given number of spaces or tabstops.
indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
Parameters
----------
instr : basestring
The string to be indented.
nspaces : int (default: 4)
The number of spaces to be indented.
ntabs : int (default: 0)
The number of tabs to be indented.
flatten : bool (default: False)
Whether to scrub existing indentation. If True, all lines will be
aligned to the same indentation. If False, existing indentation will
be strictly increased.
Returns
-------
str|unicode : string indented by ntabs and nspaces.
"""
if instr is None:
return
ind = "\t" * ntabs + " " * nspaces
if flatten:
pat = re.compile(r"^\s*", re.MULTILINE)
else:
pat = re.compile(r"^", re.MULTILINE)
outstr = re.sub(pat, ind, instr)
if outstr.endswith(os.linesep + ind):
return outstr[: -len(ind)]
else:
return outstr

View File

@ -0,0 +1,34 @@
"""
Utilities for version comparison
It is a bit ridiculous that we need these.
"""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
from packaging.version import Version
def check_version(v, min_v, max_v=None):
"""check version string v >= min_v and v < max_v
Parameters
----------
v : str
version of the package
min_v : str
minimal version supported
max_v : str
earliest version not supported
Note: If dev/prerelease tags result in TypeError for string-number
comparison, it is assumed that the check passes and the version dependency
is satisfied. Users on dev branches are responsible for keeping their own
packages up to date.
"""
try:
below_max = Version(v) < Version(max_v) if max_v is not None else True
return Version(v) >= Version(min_v) and below_max
except TypeError:
return True