pax_global_header00006660000000000000000000000064143622606110014513gustar00rootroot0000000000000052 comment=0e0ae08919b984e3c7cffdb2106e437d0d0891c8 jaraco.context-4.3.0/000077500000000000000000000000001436226061100144415ustar00rootroot00000000000000jaraco.context-4.3.0/.coveragerc000066400000000000000000000001711436226061100165610ustar00rootroot00000000000000[run] omit = # leading `*/` for pytest-dev/pytest-cov#456 */.tox/* */pep517-build-env-* [report] show_missing = True jaraco.context-4.3.0/.editorconfig000066400000000000000000000003661436226061100171230ustar00rootroot00000000000000root = true [*] charset = utf-8 indent_style = tab indent_size = 4 insert_final_newline = true end_of_line = lf [*.py] indent_style = space max_line_length = 88 [*.{yml,yaml}] indent_style = space indent_size = 2 [*.rst] indent_style = space jaraco.context-4.3.0/.flake8000066400000000000000000000002101436226061100156050ustar00rootroot00000000000000[flake8] max-line-length = 88 # jaraco/skeleton#34 max-complexity = 10 extend-ignore = # Black creates whitespace before colon E203 jaraco.context-4.3.0/.github/000077500000000000000000000000001436226061100160015ustar00rootroot00000000000000jaraco.context-4.3.0/.github/FUNDING.yml000066400000000000000000000000361436226061100176150ustar00rootroot00000000000000tidelift: pypi/jaraco.context jaraco.context-4.3.0/.github/dependabot.yml000066400000000000000000000002241436226061100206270ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "pip" directory: "/" schedule: interval: "daily" allow: - dependency-type: "all" jaraco.context-4.3.0/.github/workflows/000077500000000000000000000000001436226061100200365ustar00rootroot00000000000000jaraco.context-4.3.0/.github/workflows/main.yml000066400000000000000000000063361436226061100215150ustar00rootroot00000000000000name: tests on: [push, pull_request] env: # Environment variables to support color support (jaraco/skeleton#66): # Request colored output from CLI tools supporting it. Different tools # interpret the value differently. For some, just being set is sufficient. # For others, it must be a non-zero integer. For yet others, being set # to a non-empty value is sufficient. For tox, it must be one of # , 0, 1, false, no, off, on, true, yes. The only enabling value # in common is "1". FORCE_COLOR: 1 # MyPy's color enforcement (must be a non-zero number) MYPY_FORCE_COLOR: -42 # Recognized by the `py` package, dependency of `pytest` (must be "1") PY_COLORS: 1 # Make tox-wrapped tools see color requests TOX_TESTENV_PASSENV: >- FORCE_COLOR MYPY_FORCE_COLOR NO_COLOR PY_COLORS PYTEST_THEME PYTEST_THEME_MODE # Suppress noisy pip warnings PIP_DISABLE_PIP_VERSION_CHECK: 'true' PIP_NO_PYTHON_VERSION_WARNING: 'true' PIP_NO_WARN_SCRIPT_LOCATION: 'true' # Disable the spinner, noise in GHA; TODO(webknjaz): Fix this upstream # Must be "1". TOX_PARALLEL_NO_SPINNER: 1 jobs: test: strategy: matrix: python: - "3.7" - "3.11" - "3.12" # Workaround for actions/setup-python#508 dev: - -dev platform: - ubuntu-latest - macos-latest - windows-latest include: - python: "3.8" platform: ubuntu-latest - python: "3.9" platform: ubuntu-latest - python: "3.10" platform: ubuntu-latest - python: pypy3.9 platform: ubuntu-latest runs-on: ${{ matrix.platform }} continue-on-error: ${{ matrix.python == '3.12' }} steps: - uses: actions/checkout@v3 - name: Setup Python uses: actions/setup-python@v4 with: python-version: ${{ matrix.python }}${{ matrix.dev }} - name: Install tox run: | python -m pip install tox - name: Run tests run: tox docs: runs-on: ubuntu-latest env: TOXENV: docs steps: - uses: actions/checkout@v3 - name: Setup Python uses: actions/setup-python@v4 with: python-version: ${{ matrix.python }}${{ matrix.dev }} - name: Install tox run: | python -m pip install tox - name: Run tests run: tox check: # This job does nothing and is only used for the branch protection if: always() needs: - test - docs runs-on: ubuntu-latest steps: - name: Decide whether the needed jobs succeeded or failed uses: re-actors/alls-green@release/v1 with: jobs: ${{ toJSON(needs) }} release: needs: - check if: github.event_name == 'push' && contains(github.ref, 'refs/tags/') runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Python uses: actions/setup-python@v4 with: python-version: 3.11-dev - name: Install tox run: | python -m pip install tox - name: Release run: tox -e release env: TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} jaraco.context-4.3.0/.pre-commit-config.yaml000066400000000000000000000001211436226061100207140ustar00rootroot00000000000000repos: - repo: https://github.com/psf/black rev: 22.6.0 hooks: - id: black jaraco.context-4.3.0/.readthedocs.yaml000066400000000000000000000003511436226061100176670ustar00rootroot00000000000000version: 2 python: install: - path: . extra_requirements: - docs # workaround for readthedocs/readthedocs.org#9623 build: # workaround for readthedocs/readthedocs.org#9635 os: ubuntu-22.04 tools: python: "3" jaraco.context-4.3.0/CHANGES.rst000066400000000000000000000025211436226061100162430ustar00rootroot00000000000000v4.3.0 ====== Deprecated ``runner`` parameter to ``tarball_context``. v4.2.1 ====== Added test for ``pushd``. v4.2.0 ====== Added ``on_interrupt`` decorator. v4.1.2 ====== Packaging refresh. Enrolled with Tidelift. v4.1.1 ====== Fixed some docs rendering issues. v4.1.0 ====== To the ``ExceptionTrap``, added ``.raises()`` and ``.passes`` decorators. v4.0.0 ====== Moved ``dependency_context`` and ``run`` to `jaraco.apt `_. v3.0.0 ====== Refreshed package metadata. Require Python 3.6 or later. 2.0 === Switch to `pkgutil namespace technique `_ for the ``jaraco`` namespace. 1.8 === * Dropped support for Python 3.3. * Refreshed project metadata using declarative config. * ``ExceptionTrap`` now presents ``type``, ``value``, and ``tb`` attributes. 1.7 === * Added ``suppress`` context manager as `found in Python 3.4 `_ but with decorator support. 1.6 === * Refresh project skeleton. Moved hosting to Github. 1.5 === * Also allow the ``dest_ctx`` to be overridden in ``repo_context``. 1.4 === * Added ``remover`` parameter to ``context.temp_dir``. 1.2 === * Adopted functionality from jaraco.util.context (10.8). jaraco.context-4.3.0/LICENSE000066400000000000000000000020321436226061100154430ustar00rootroot00000000000000Copyright Jason R. Coombs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. jaraco.context-4.3.0/README.rst000066400000000000000000000030271436226061100161320ustar00rootroot00000000000000.. image:: https://img.shields.io/pypi/v/jaraco.context.svg :target: https://pypi.org/project/jaraco.context .. image:: https://img.shields.io/pypi/pyversions/jaraco.context.svg .. image:: https://github.com/jaraco/jaraco.context/workflows/tests/badge.svg :target: https://github.com/jaraco/jaraco.context/actions?query=workflow%3A%22tests%22 :alt: tests .. image:: https://img.shields.io/badge/code%20style-black-000000.svg :target: https://github.com/psf/black :alt: Code style: Black .. image:: https://readthedocs.org/projects/jaracocontext/badge/?version=latest :target: https://jaracocontext.readthedocs.io/en/latest/?badge=latest .. image:: https://img.shields.io/badge/skeleton-2023-informational :target: https://blog.jaraco.com/skeleton .. image:: https://tidelift.com/badges/package/pypi/jaraco.context :target: https://tidelift.com/subscription/pkg/pypi-jaraco.context?utm_source=pypi-jaraco.context&utm_medium=readme For Enterprise ============== Available as part of the Tidelift Subscription. This project and the maintainers of thousands of other packages are working with Tidelift to deliver one enterprise subscription that covers all of the open source you use. `Learn more `_. Security Contact ================ To report a security vulnerability, please use the `Tidelift security contact `_. Tidelift will coordinate the fix and disclosure. jaraco.context-4.3.0/docs/000077500000000000000000000000001436226061100153715ustar00rootroot00000000000000jaraco.context-4.3.0/docs/conf.py000066400000000000000000000023071436226061100166720ustar00rootroot00000000000000extensions = [ 'sphinx.ext.autodoc', 'jaraco.packaging.sphinx', ] master_doc = "index" html_theme = "furo" # Link dates and other references in the changelog extensions += ['rst.linker'] link_files = { '../CHANGES.rst': dict( using=dict(GH='https://github.com'), replace=[ dict( pattern=r'(Issue #|\B#)(?P\d+)', url='{package_url}/issues/{issue}', ), dict( pattern=r'(?m:^((?Pv?\d+(\.\d+){1,2}))\n[-=]+\n)', with_scm='{text}\n{rev[timestamp]:%d %b %Y}\n', ), dict( pattern=r'PEP[- ](?P\d+)', url='https://peps.python.org/pep-{pep_number:0>4}/', ), ], ) } # Be strict about any broken references nitpicky = True nitpick_ignore = [ ('py:class', 'contextlib.suppress'), ] # Include Python intersphinx mapping to prevent failures # jaraco/skeleton#51 extensions += ['sphinx.ext.intersphinx'] intersphinx_mapping = { 'python': ('https://docs.python.org/3', None), } # Preserve authored syntax for defaults autodoc_preserve_defaults = True extensions += ['jaraco.tidelift'] jaraco.context-4.3.0/docs/history.rst000066400000000000000000000001211436226061100176160ustar00rootroot00000000000000:tocdepth: 2 .. _changes: History ******* .. include:: ../CHANGES (links).rst jaraco.context-4.3.0/docs/index.rst000066400000000000000000000005101436226061100172260ustar00rootroot00000000000000Welcome to |project| documentation! =================================== .. toctree:: :maxdepth: 1 history .. tidelift-referral-banner:: .. automodule:: jaraco.context :members: :undoc-members: :show-inheritance: Indices and tables ================== * :ref:`genindex` * :ref:`modindex` * :ref:`search` jaraco.context-4.3.0/jaraco/000077500000000000000000000000001436226061100157005ustar00rootroot00000000000000jaraco.context-4.3.0/jaraco/context.py000066400000000000000000000164441436226061100177470ustar00rootroot00000000000000import os import subprocess import contextlib import functools import tempfile import shutil import operator import warnings @contextlib.contextmanager def pushd(dir): """ >>> tmp_path = getfixture('tmp_path') >>> with pushd(tmp_path): ... assert os.getcwd() == os.fspath(tmp_path) >>> assert os.getcwd() != os.fspath(tmp_path) """ orig = os.getcwd() os.chdir(dir) try: yield dir finally: os.chdir(orig) @contextlib.contextmanager def tarball_context(url, target_dir=None, runner=None, pushd=pushd): """ Get a tarball, extract it, change to that directory, yield, then clean up. `runner` is the function to invoke commands. `pushd` is a context manager for changing the directory. """ if target_dir is None: target_dir = os.path.basename(url).replace('.tar.gz', '').replace('.tgz', '') if runner is None: runner = functools.partial(subprocess.check_call, shell=True) else: warnings.warn("runner parameter is deprecated", DeprecationWarning) # In the tar command, use --strip-components=1 to strip the first path and # then # use -C to cause the files to be extracted to {target_dir}. This ensures # that we always know where the files were extracted. runner('mkdir {target_dir}'.format(**vars())) try: getter = 'wget {url} -O -' extract = 'tar x{compression} --strip-components=1 -C {target_dir}' cmd = ' | '.join((getter, extract)) runner(cmd.format(compression=infer_compression(url), **vars())) with pushd(target_dir): yield target_dir finally: runner('rm -Rf {target_dir}'.format(**vars())) def infer_compression(url): """ Given a URL or filename, infer the compression code for tar. >>> infer_compression('http://foo/bar.tar.gz') 'z' >>> infer_compression('http://foo/bar.tgz') 'z' >>> infer_compression('file.bz') 'j' >>> infer_compression('file.xz') 'J' """ # cheat and just assume it's the last two characters compression_indicator = url[-2:] mapping = dict(gz='z', bz='j', xz='J') # Assume 'z' (gzip) if no match return mapping.get(compression_indicator, 'z') @contextlib.contextmanager def temp_dir(remover=shutil.rmtree): """ Create a temporary directory context. Pass a custom remover to override the removal behavior. >>> import pathlib >>> with temp_dir() as the_dir: ... assert os.path.isdir(the_dir) ... _ = pathlib.Path(the_dir).joinpath('somefile').write_text('contents') >>> assert not os.path.exists(the_dir) """ temp_dir = tempfile.mkdtemp() try: yield temp_dir finally: remover(temp_dir) @contextlib.contextmanager def repo_context(url, branch=None, quiet=True, dest_ctx=temp_dir): """ Check out the repo indicated by url. If dest_ctx is supplied, it should be a context manager to yield the target directory for the check out. """ exe = 'git' if 'git' in url else 'hg' with dest_ctx() as repo_dir: cmd = [exe, 'clone', url, repo_dir] if branch: cmd.extend(['--branch', branch]) devnull = open(os.path.devnull, 'w') stdout = devnull if quiet else None subprocess.check_call(cmd, stdout=stdout) yield repo_dir @contextlib.contextmanager def null(): """ A null context suitable to stand in for a meaningful context. >>> with null() as value: ... assert value is None """ yield class ExceptionTrap: """ A context manager that will catch certain exceptions and provide an indication they occurred. >>> with ExceptionTrap() as trap: ... raise Exception() >>> bool(trap) True >>> with ExceptionTrap() as trap: ... pass >>> bool(trap) False >>> with ExceptionTrap(ValueError) as trap: ... raise ValueError("1 + 1 is not 3") >>> bool(trap) True >>> trap.value ValueError('1 + 1 is not 3') >>> trap.tb >>> with ExceptionTrap(ValueError) as trap: ... raise Exception() Traceback (most recent call last): ... Exception >>> bool(trap) False """ exc_info = None, None, None def __init__(self, exceptions=(Exception,)): self.exceptions = exceptions def __enter__(self): return self @property def type(self): return self.exc_info[0] @property def value(self): return self.exc_info[1] @property def tb(self): return self.exc_info[2] def __exit__(self, *exc_info): type = exc_info[0] matches = type and issubclass(type, self.exceptions) if matches: self.exc_info = exc_info return matches def __bool__(self): return bool(self.type) def raises(self, func, *, _test=bool): """ Wrap func and replace the result with the truth value of the trap (True if an exception occurred). First, give the decorator an alias to support Python 3.8 Syntax. >>> raises = ExceptionTrap(ValueError).raises Now decorate a function that always fails. >>> @raises ... def fail(): ... raise ValueError('failed') >>> fail() True """ @functools.wraps(func) def wrapper(*args, **kwargs): with ExceptionTrap(self.exceptions) as trap: func(*args, **kwargs) return _test(trap) return wrapper def passes(self, func): """ Wrap func and replace the result with the truth value of the trap (True if no exception). First, give the decorator an alias to support Python 3.8 Syntax. >>> passes = ExceptionTrap(ValueError).passes Now decorate a function that always fails. >>> @passes ... def fail(): ... raise ValueError('failed') >>> fail() False """ return self.raises(func, _test=operator.not_) class suppress(contextlib.suppress, contextlib.ContextDecorator): """ A version of contextlib.suppress with decorator support. >>> @suppress(KeyError) ... def key_error(): ... {}[''] >>> key_error() """ class on_interrupt(contextlib.ContextDecorator): """ Replace a KeyboardInterrupt with SystemExit(1) >>> def do_interrupt(): ... raise KeyboardInterrupt() >>> on_interrupt('error')(do_interrupt)() Traceback (most recent call last): ... SystemExit: 1 >>> on_interrupt('error', code=255)(do_interrupt)() Traceback (most recent call last): ... SystemExit: 255 >>> on_interrupt('suppress')(do_interrupt)() >>> with __import__('pytest').raises(KeyboardInterrupt): ... on_interrupt('ignore')(do_interrupt)() """ def __init__( self, action='error', # py3.7 compat # /, code=1, ): self.action = action self.code = code def __enter__(self): return self def __exit__(self, exctype, excinst, exctb): if exctype is not KeyboardInterrupt or self.action == 'ignore': return elif self.action == 'error': raise SystemExit(self.code) from excinst return self.action == 'suppress' jaraco.context-4.3.0/mypy.ini000066400000000000000000000002321436226061100161350ustar00rootroot00000000000000[mypy] ignore_missing_imports = True # required to support namespace packages # https://github.com/python/mypy/issues/14057 explicit_package_bases = True jaraco.context-4.3.0/pyproject.toml000066400000000000000000000005721436226061100173610ustar00rootroot00000000000000[build-system] requires = ["setuptools>=56", "setuptools_scm[toml]>=3.4.1"] build-backend = "setuptools.build_meta" [tool.black] skip-string-normalization = true [tool.setuptools_scm] [tool.pytest-enabler.black] addopts = "--black" [tool.pytest-enabler.mypy] addopts = "--mypy" [tool.pytest-enabler.flake8] addopts = "--flake8" [tool.pytest-enabler.cov] addopts = "--cov" jaraco.context-4.3.0/pytest.ini000066400000000000000000000017201436226061100164720ustar00rootroot00000000000000[pytest] norecursedirs=dist build .tox .eggs addopts=--doctest-modules doctest_optionflags=ALLOW_UNICODE ELLIPSIS filterwarnings= # Ensure ResourceWarnings are emitted default::ResourceWarning # Suppress deprecation warning in flake8 ignore:SelectableGroups dict interface is deprecated::flake8 # shopkeep/pytest-black#55 ignore: is not using a cooperative constructor:pytest.PytestDeprecationWarning ignore:The \(fspath. py.path.local\) argument to BlackItem is deprecated.:pytest.PytestDeprecationWarning ignore:BlackItem is an Item subclass and should not be a collector:pytest.PytestWarning # tholo/pytest-flake8#83 ignore: is not using a cooperative constructor:pytest.PytestDeprecationWarning ignore:The \(fspath. py.path.local\) argument to Flake8Item is deprecated.:pytest.PytestDeprecationWarning ignore:Flake8Item is an Item subclass and should not be a collector:pytest.PytestWarning jaraco.context-4.3.0/setup.cfg000066400000000000000000000023221436226061100162610ustar00rootroot00000000000000[metadata] name = jaraco.context author = Jason R. Coombs author_email = jaraco@jaraco.com description = Context managers by jaraco long_description = file:README.rst url = https://github.com/jaraco/jaraco.context classifiers = Development Status :: 5 - Production/Stable Intended Audience :: Developers License :: OSI Approved :: MIT License Programming Language :: Python :: 3 Programming Language :: Python :: 3 :: Only [options] packages = find_namespace: include_package_data = true python_requires = >=3.7 install_requires = [options.packages.find] exclude = build* dist* docs* tests* [options.extras_require] testing = # upstream pytest >= 6 pytest-checkdocs >= 2.4 pytest-flake8; \ # workaround for tholo/pytest-flake8#87 python_version < "3.12" # workaround for tholo/pytest-flake8#87 flake8 < 5 pytest-black >= 0.3.7; \ # workaround for jaraco/skeleton#22 python_implementation != "PyPy" pytest-cov pytest-mypy >= 0.9.1; \ # workaround for jaraco/skeleton#22 python_implementation != "PyPy" pytest-enabler >= 1.3 # local docs = # upstream sphinx >= 3.5 jaraco.packaging >= 9 rst.linker >= 1.9 furo sphinx-lint # tidelift jaraco.tidelift >= 1.4 # local [options.entry_points] jaraco.context-4.3.0/tox.ini000066400000000000000000000013621436226061100157560ustar00rootroot00000000000000[tox] envlist = python minversion = 3.2 # https://github.com/jaraco/skeleton/issues/6 tox_pip_extensions_ext_venv_update = true toxworkdir={env:TOX_WORK_DIR:.tox} [testenv] deps = commands = pytest {posargs} usedevelop = True extras = testing [testenv:docs] extras = docs testing changedir = docs commands = python -m sphinx -W --keep-going . {toxinidir}/build/html python -m sphinxlint [testenv:release] skip_install = True deps = build twine>=3 jaraco.develop>=7.1 passenv = TWINE_PASSWORD GITHUB_TOKEN setenv = TWINE_USERNAME = {env:TWINE_USERNAME:__token__} commands = python -c "import shutil; shutil.rmtree('dist', ignore_errors=True)" python -m build python -m twine upload dist/* python -m jaraco.develop.create-github-release