Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide a way to capture or wrap streams #50

Merged
merged 15 commits into from
Dec 10, 2018
Merged
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ install:
- "pipenv install --dev"
- "pipenv run pip install --upgrade -e .[spinner,tests]"
script:
- "pipenv run pytest -v -n auto tests/"
- "pipenv run pytest -v tests/"

jobs:
include:
Expand All @@ -33,7 +33,7 @@ jobs:
- stage: coverage
python: "3.6"
install:
- "pip install --upgrade pip pipenv pytest-cov pytest-xdist pytest-timeout pytest"
- "pip install --upgrade pip pipenv pytest-cov pytest-timeout pytest"
- "pipenv install --dev"
script:
- "pipenv run pytest -n auto --timeout 300 --cov=vistir --cov-report=term-missing --cov-report=xml --cov-report=html tests"
- "pipenv run pytest --timeout 300 --cov=vistir --cov-report=term-missing --cov-report=xml --cov-report=html tests"
121 changes: 120 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ default encoding:
* ``vistir.contextmanagers.atomic_open_for_write``
* ``vistir.contextmanagers.cd``
* ``vistir.contextmanagers.open_file``
* ``vistir.contextmanagers.replaced_stream``
* ``vistir.contextmanagers.spinner``
* ``vistir.contextmanagers.temp_environ``
* ``vistir.contextmanagers.temp_path``
Expand Down Expand Up @@ -203,6 +204,23 @@ to pair this with an iterator which employs a sensible chunk size.
shutil.copyfileobj(fp, filecontents)


.. _`replaced_stream`:

A context manager to temporarily swap out *stream_name* with a stream wrapper. This will
capture the stream output and prevent it from being written as normal.

.. code-block:: python

>>> orig_stdout = sys.stdout
>>> with replaced_stream("stdout") as stdout:
... sys.stdout.write("hello")
... assert stdout.getvalue() == "hello"
... assert orig_stdout.getvalue() != "hello"

>>> sys.stdout.write("hello")
'hello'


.. _`spinner`:

**spinner**
Expand Down Expand Up @@ -286,8 +304,13 @@ The following Miscellaneous utilities are available as helper methods:
* ``vistir.misc.partialclass``
* ``vistir.misc.to_text``
* ``vistir.misc.to_bytes``
* ``vistir.misc.divide``
* ``vistir.misc.take``
* ``vistir.misc.chunked``
* ``vistir.misc.decode_for_output``

* ``vistir.misc.get_canonical_encoding_name``
* ``vistir.misc.get_wrapped_stream``
* ``vistir.misc.StreamWrapper``

.. _`shell_escape`:

Expand Down Expand Up @@ -401,6 +424,62 @@ Converts arbitrary byte-convertable input to bytes while handling errors.
b'this is some text'


.. _`chunked`:

**chunked**
////////////

Splits an iterable up into groups *of the specified length*, per `more itertools`_. Returns an iterable.

This example will create groups of chunk size **5**, which means there will be *6 groups*.

.. code-block:: python

>>> chunked_iterable = vistir.misc.chunked(5, range(30))
>>> for chunk in chunked_iterable:
... add_to_some_queue(chunk)

.. _more itertools: https://more-itertools.readthedocs.io/en/latest/api.html#grouping


.. _`take`:

**take**
/////////

Take elements from the supplied iterable without consuming it.

.. code-block:: python

>>> iterable = range(30)
>>> first_10 = take(10, iterable)
>>> [i for i in first_10]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> [i for i in iterable]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]


.. _`divide`:

**divide**
////////////

Splits an iterable up into the *specified number of groups*, per `more itertools`_. Returns an iterable.

.. code-block:: python

>>> iterable = range(30)
>>> groups = []
>>> for grp in vistir.misc.divide(3, iterable):
... groups.append(grp)
>>> groups
[<tuple_iterator object at 0x7fb7966006a0>, <tuple_iterator object at 0x7fb796652780>, <tuple_iterator object at 0x7fb79650a2b0>]


.. _more itertools: https://more-itertools.readthedocs.io/en/latest/api.html#grouping


.. _`decode_for_output`:

**decode_for_output**
Expand All @@ -411,6 +490,46 @@ outputs using the system preferred locale using ``locale.getpreferredencoding(Fa
with some additional hackery on linux systems.


.. _`get_canonical_encoding_name`:

**get_canonical_encoding_name**
////////////////////////////////

Given an encoding name, get the canonical name from a codec lookup.

.. code-block:: python

>>> vistir.misc.get_canonical_encoding_name("utf8")
"utf-8"


.. _`get_wrapped_stream`:

**get_wrapped_stream**
//////////////////////

Given a stream, wrap it in a `StreamWrapper` instance and return the wrapped stream.

.. code-block:: python

>>> stream = sys.stdout
>>> wrapped_stream = vistir.misc.get_wrapped_stream(sys.stdout)


.. _`StreamWrapper`:

**StreamWrapper**
//////////////////

A stream wrapper and compatibility class for handling wrapping file-like stream objects
which may be used in place of ``sys.stdout`` and other streams.

.. code-block:: python

>>> wrapped_stream = vistir.misc.StreamWrapper(sys.stdout, encoding="utf-8", errors="replace", line_buffering=True)
>>> wrapped_stream = vistir.misc.StreamWrapper(io.StringIO(), encoding="utf-8", errors="replace", line_buffering=True)


🐉 Path Utilities
------------------

Expand Down
6 changes: 3 additions & 3 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ environment:
install:
- "SET PATH=%PYTHON%\\;%PYTHON%\\Scripts;%PATH%"
- "python --version"
- "python -m pip install --upgrade pip pipenv"
- "python -m pip install --upgrade pip pipenv pytest pytest-timeout pytest-cov"
- "python -m pipenv install --dev"
- "python -m pipenv run pip install -e .[tests,spinner]"
- "python -m pipenv run pip install --upgrade -e .[tests,spinner]"

build: off

Expand All @@ -24,4 +24,4 @@ test_script:
- "subst T: %TEMP%"
- "set TEMP=T:\\"
- "set TMP=T:\\"
- "python -m pipenv run pytest -n auto -v tests"
- "python -m pipenv run pytest -ra tests"
31 changes: 26 additions & 5 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,30 @@
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
import codecs
import os
import re
import sys
docs_dir = os.path.abspath(os.path.dirname(__file__))
src_dir = os.path.join(os.path.dirname(docs_dir), "src", "vistir")
sys.path.insert(0, src_dir)
version_file = os.path.join(src_dir, "__init__.py")


def read_file(path):
# intentionally *not* adding an encoding option to open, See:
# https://github.com/pypa/virtualenv/issues/201#issuecomment-3145690
with codecs.open(path, 'r') as fp:
return fp.read()


def find_version(file_path):
version_file = read_file(file_path)
version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
version_file, re.M)
if version_match:
return version_match.group(1)
return '0.0.0'


# -- Project information -----------------------------------------------------
Expand All @@ -25,10 +44,12 @@
copyright = '2018, Dan Ryan <dan@danryan.co>'
author = 'Dan Ryan <dan@danryan.co>'

release = find_version(version_file)
version = '.'.join(release.split('.')[:2])
# The short X.Y version
version = '0.0'
# version = '0.0'
# The full version, including alpha/beta/rc tags
release = '0.0.0.dev0'
# release = '0.0.0.dev0'


# -- General configuration ---------------------------------------------------
Expand Down Expand Up @@ -132,11 +153,11 @@
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
'papersize': 'letterpaper',

# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
'pointsize': '10pt',

# Additional stuff for the LaTeX preamble.
#
Expand Down Expand Up @@ -173,7 +194,7 @@
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'vistir', 'vistir Documentation',
author, 'vistir', 'One line description of project.',
author, 'vistir', 'Miscellaneous utilities for dealing with filesystems, paths, projects, subprocesses, and more.',
'Miscellaneous'),
]

Expand Down