python -m http.server 9794 | python -m http.server 9794 | ||||
docs-watch: docs | docs-watch: docs | ||||
+sh tools/docs-watch.sh | |||||
+poetry run sh tools/docs-watch.sh | |||||
docs-sync-server: | docs-sync-server: | ||||
mkdir -p _build/docs | mkdir -p _build/docs |
release = '0.1.0-alpha.5' | release = '0.1.0-alpha.5' | ||||
# -- General configuration --------------------------------------------------- | # -- General configuration --------------------------------------------------- | ||||
extensions = [] | |||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx'] | |||||
templates_path = [] | templates_path = [] | ||||
source_suffix = '.rst' | source_suffix = '.rst' | ||||
master_doc = 'index' | master_doc = 'index' | ||||
language = None | language = None | ||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] | ||||
pygments_style = None | pygments_style = None | ||||
intersphinx_mapping = { | |||||
'python': ('https://docs.python.org/3', None), | |||||
'pytest': ('https://docs.pytest.org/en/latest/', None), | |||||
} | |||||
# -- Options for HTML output ------------------------------------------------- | # -- Options for HTML output ------------------------------------------------- | ||||
html_theme = 'nature' | html_theme = 'nature' |
Building ``dds`` from Source | Building ``dds`` from Source | ||||
############################ | ############################ | ||||
While prebuilt ``dds`` executables are `available on the GitHub page | |||||
<releases_>`_, one may wish to build ``dds`` from source. | |||||
.. _releases: https://github.com/vector-of-bool/dds/releases | |||||
The ``dds`` build process is designed to be as turn-key simple as possible. | |||||
Platform Support | |||||
**************** | |||||
``dds`` aims to be as cross-platform as possible. It currently build and | |||||
executes on Windows, macOS, Linux, and FreeBSD. Support for additional | |||||
platforms is possible but will require modifications to ``bootstrap.py`` that | |||||
will allow it to be built on such platforms. | |||||
Build Requirements | |||||
****************** | |||||
Building ``dds`` has a simple set of requirements: | |||||
- **Python 3.6** or newer to run the bootstrap/CI scripts. | |||||
- A C++ compiler that has rudimentary support for C++20 concepts. Newer | |||||
releases of Visual C++ that ship with **VS 2019** will be sufficient on | |||||
Windows, as will **GCC 9** with ``-fconcepts`` on other platforms. | |||||
.. note:: | .. note:: | ||||
On Windows, you will need to execute the build from within a Visual C++ | |||||
enabled environment. This will involve launching the build from a Visual | |||||
Studio Command Prompt. | |||||
.. note:: | |||||
At the time of writing, C++20 Concepts has not yet been released in Clang, | |||||
but should be available in LLVM/Clang 11 and newer. | |||||
Build Scripts and the CI Process | |||||
******************************** | |||||
The main CI process is driven by Python. The root CI script is ``tools/ci.py``, | |||||
and it accepts several command-line parameters. Only a few of are immediate | |||||
interest: | |||||
``--bootstrap-with=<method>`` or ``-B <method>`` | |||||
Tell ``ci.py`` how to obtain the previous ``dds`` executable that can build | |||||
the *current* ``dds`` source tree. This accepts one of three values: | |||||
``skip``, ``download``, or ``build``. Refer to :ref:`bootstrapping`. | |||||
``--build-only`` | |||||
A flag that tells ``ci.py`` to exit after it has successfully built the | |||||
current source tree, and to not execute the phase-2 build nor the automated | |||||
tests. | |||||
``--toolchain=<path>`` or ``-T <path>`` | |||||
Tell ``ci.py`` what toolchain to give to the prior ``dds`` to build the | |||||
current ``dds``. | |||||
The ``ci.py`` script performs the following actions, in order: | |||||
#. Prepare the build output directory | |||||
#. Prepare the prior version of ``dds`` that will build the current version. | |||||
#. Import the embedded ``catalog.json`` into a catalog database stored within | |||||
``_prebuilt/``. This will be used to resolve the third-party packages that | |||||
``dds`` itself uses. | |||||
#. Invoke the build of ``dds`` using the prebuilt ``dds`` from the prior | |||||
bootstrap phase. If ``--build-only`` was specified, the CI script stops | |||||
here. | |||||
#. Use the new ``dds`` executable to rebuild itself *again* (phase-2 self-build | |||||
test). A bit of a "sanity test." | |||||
#. Execute the test suite using ``pytest``. | |||||
.. _bootstrapping: | |||||
This page assumes that you have ready the :doc:`env` page, and that you are | |||||
running all commands from within the Poetry-generated virtual environment. | |||||
Bootstrapping ``dds`` | |||||
********************* | |||||
The main entrypoint for the ``dds`` CI process is the ``dds-ci`` command, which | |||||
will build and test the ``dds`` from the repository sources. ``dds-ci`` accepts | |||||
several optional command-line arguments to tweak its behavior. | |||||
In the beginning, ``dds`` was built by a Python script that globbed the sources | |||||
and invoked the compiler+linker on those sources. Once ``dds`` was able to | |||||
build and link itself, this Python script was replaced instead with ``dds`` | |||||
building itself. ``dds`` has never used another build system. | |||||
The ``ci.py`` script accepts one of three methods for the ``--bootstrap-with`` | |||||
flag: ``skip``, ``download``, or ``build``. | |||||
Running a Build *Only* | |||||
********************** | |||||
Once bootstrapping is complete, a ``dds`` executable will be written to | |||||
``_prebuilt/dds``. This executable refers to a **previous** version of ``dds`` | |||||
that is able to build the newer ``dds`` source tree. | |||||
If you only wish to obtain a built ``dds`` executable, the ``--no-test`` | |||||
parameter can be given:: | |||||
.. note:: | |||||
For all development work on ``dds``, the ``_prebuilt/dds`` executable should | |||||
always be used. This means that newer ``dds`` features are not available | |||||
for use within the ``dds`` repository. | |||||
$ dds-ci --no-test | |||||
This will skip the audit-build and testing phases of CI and build only the final | |||||
``dds`` executable. | |||||
Bootstrap: ``skip`` | |||||
=================== | |||||
If given ``skip``, ``ci.py`` will not perform any bootstrapping steps. It will | |||||
assume that there is an existing ``_prebuilt/dds`` executable. This option | |||||
should be used once bootstrapping has been performed at least once with another | |||||
method, as this is much faster than rebuilding/redownloading every time. | |||||
Rapid Iterations for Development | |||||
******************************** | |||||
If you are making frequent changes to ``dds``'s source code and want a fast | |||||
development process, use ``--rapid``:: | |||||
Bootstrap: ``download`` | |||||
======================= | |||||
$ dds-ci --rapid | |||||
The ``ci.py`` script has a reference to a download URL of the prior version of | |||||
``dds`` that has been designated for the bootstrap. These executables originate | |||||
from `the GitHub releases <releases_>`_ page. | |||||
This will build the build step only, and builds an executable with maximum debug | |||||
and audit information, including AddressSanitizer and | |||||
UndefinedBehaviorSanitizer. This will also execute the unit tests, which should | |||||
run completely in under two seconds (if they are slower, then it may be a bug). | |||||
If given ``download``, then ``ci.py`` will download a predetermined ``dds`` | |||||
executable and use it to perform the remainder of the build. | |||||
Toolchain Control | |||||
***************** | |||||
Bootstrap: ``build`` | |||||
==================== | |||||
``dds-ci`` will automatically select and build with an appropriate | |||||
:doc:`toolchain </guide/toolchains>` based on what it detects of the host | |||||
platform, but you may want to tweak those options. | |||||
Another script, ``tools/bootstrap.py`` is able to build ``dds`` from the ground | |||||
up. It works by progressively cloning previous versions of the ``dds`` | |||||
repository and using them to build the next commit in the chain. | |||||
The ``dds-ci`` script accepts two toolchain options: | |||||
While this is a neat trick, it isn't necessary for most development, as the | |||||
resulting executable will be derived from the same commit as the executable | |||||
that would be obtained using the ``download`` method. This is also more fragile | |||||
as the past commits may make certain assumptions about the system that might | |||||
not be true outside of the CI environment. The build process may be tweaked in | |||||
the future to correct these assumptions. | |||||
``--main-toolchain`` | |||||
This is the toolchain that is used to create a final release-built executable. | |||||
If you build with ``--no-test``, this toolchain will be used. | |||||
``--test-toolchain`` This is the toolchain that is used to create an auditing | |||||
and debuggable executable of ``dds``. This is the toolchain that is used if you | |||||
build with ``--rapid``. | |||||
Selecting a Build Toolchain | |||||
*************************** | |||||
If you build with neither ``--rapid`` nor ``--no-test``, then ``dds-ci`` will | |||||
build *two* ``dds`` executables: One with the ``--test-toolchain`` that is | |||||
passed through the test suite, and another for ``--main-toolchain`` that is | |||||
built for distribution. | |||||
``dds`` includes three toolchains that it uses to build itself in its CI | |||||
environment: ``tools/gcc-9.jsonc`` for Linux and macOS, | |||||
``tools/freebsd-gcc-9.jsonc`` for FreeBSD, and ``tools/msvc.jsonc`` for | |||||
Windows. | |||||
The default toolchains are files contained within the ``tools/`` directory of | |||||
the repository. When ``dds-ci`` builds ``dds``, it will print the path to the | |||||
toolchain file that is selected for that build. | |||||
While these toolchains will work perfectly well in CI, you may need to tweak | |||||
these for your build setup. For example: ``gcc-9.jsonc`` assumes that the GCC 9 | |||||
executables are named ``gcc-9`` and ``g++-9``, which is incorrect on some | |||||
Linux distributions. | |||||
While these provided toolchains will work perfectly well in CI, you may need to | |||||
tweak these for your build setup. For example: ``gcc-9-*.jsonc`` toolchains | |||||
assume that the GCC 9 executables are named ``gcc-9`` and ``g++-9``, which is | |||||
incorrect on some Unix and Linux distributions. | |||||
It is recommended to tweak these files as necessary to get the build working on | It is recommended to tweak these files as necessary to get the build working on | ||||
your system. However, do not include those tweaks in a commit unless they are | |||||
necessary to get the build running in CI. | |||||
your system. However, **do not** include those tweaks in a commit unless they | |||||
are necessary to get the build running in CI. | |||||
Giving a Toolchain to ``ci.py`` | |||||
=============================== | |||||
Just like passing a toolchain to ``dds``, ``ci.py`` also requires a toolchain. | |||||
Simply pass the path to your desired toolchain using the ``--toolchain``/ | |||||
``-T`` argument: | |||||
What's Happening? | |||||
***************** | |||||
.. code-block:: bash | |||||
The ``dds-ci`` script performs the following actions, in order: | |||||
$ python3 tools/ci.py [...] -T tools/gcc-9.jsonc | |||||
#. If given ``--clean``, remove any prior build output and downloaded | |||||
dependencies. | |||||
#. Prepare the prior version of ``dds`` that will build the current version | |||||
(usually, just download it). This is placed in ``_prebuilt/``. | |||||
#. Import the ``old-catalog.json`` into a catalog database stored within | |||||
``_prebuilt/``. This will be used to resolve the third-party packages that | |||||
``dds`` itself uses. | |||||
#. Invoke the build of ``dds`` using the prebuilt ``dds`` obtained from the | |||||
prior bootstrap phase. If ``--no-test`` or ``--rapid`` was specified, the CI | |||||
script stops here. | |||||
#. Launch ``pytest`` with the generated ``dds`` executable and start the final | |||||
release build simultaneously, and wait for both to finish. | |||||
Building for Development | |||||
************************ | |||||
Unit Tests | |||||
********** | |||||
While ``ci.py`` is rigorous in maintaining a clean and reproducible environment, | |||||
we often don't need such rigor for a rapid development iteration cycle. Instead | |||||
we can invoke the build command directly in the same way that ``ci.py`` does | |||||
it: | |||||
Various pieces of ``dds`` contain unit tests. These are stored within the | |||||
``src/`` directory itself in ``*.test.cpp`` files. They are built and executed | |||||
as part of the iteration cycle *unconditionally*. These tests execute in | |||||
milliseconds so as not to burden the development iteration cycle. The more | |||||
rigorous tests are executed separately by PyTest. | |||||
.. code-block:: bash | |||||
$ _prebuilt/dds build -t [toolchain] \ | |||||
--catalog _prebuilt/catalog.db \ | |||||
--repo-dir _prebuilt/ci-repo | |||||
Speeding Up the Build | |||||
********************* | |||||
The ``--catalog`` and ``--repo-dir`` arguments are not strictly necessary, but | |||||
help to isolate the ``dds`` dev environment from the user-local ``dds`` | |||||
environment. This is important if modifications are made to the catalog | |||||
database schema that would conflict with the one of an external ``dds`` | |||||
version. | |||||
``dds``'s build is unfortunately demanding, but can be sped up by additional | |||||
tools: | |||||
.. note:: | |||||
You'll likely want to run ``ci.py`` *at least once* for it to prepare the | |||||
necessary ``catalog.db``. | |||||
.. note:: | |||||
As mentioned previously, if using MSVC, the above command must execute with | |||||
the appropriate VS development environment enabled. | |||||
Use the LLVM ``lld`` Linker | |||||
=========================== | |||||
Installing the LLVM ``lld`` linker will *significantly* improve the time it | |||||
takes for ``dds`` and its unit test executables to link. ``dds-ci`` will | |||||
automatically recognize the presence of ``lld`` if it has been installed | |||||
properly. | |||||
Running the Test Suite | |||||
********************** | |||||
.. note:: | |||||
The ``--build-only`` flag for ``ci.py`` will disable test execution. When this | |||||
flag is omitted, ``ci.py`` will execute a self-build sanity test and then | |||||
execute the main test suite, which is itself written as a set of ``pytest`` | |||||
tests in the ``tests/`` subdirectory. | |||||
``dds-ci`` (and GCC) look for an executable called ``ld.ldd`` on the | |||||
executable PATH (no version suffix!). You may need to symlink the | |||||
version-suffixed executable with ``ld.ldd`` in another location on PATH so | |||||
that ``dds-ci`` (and GCC) can find it. | |||||
Unit Tests | |||||
========== | |||||
Use ``ccache`` | |||||
============== | |||||
Various pieces of ``dds`` contain unit tests. These are stored within the | |||||
``src/`` directory itself in ``*.test.cpp`` files. They are built and executed | |||||
by the bootstrapped ``dds`` executable unconditionally. These tests execute | |||||
in milliseconds and do not burden the development iteration cycle. | |||||
``dds-ci`` will also recognize ``ccache`` and add it as a compiler-launcher if | |||||
it is installed on your PATH. This won't improve initial compilation times, but | |||||
can make subsequent compilations significantly faster when files are unchanged. |
DDS CI Scripts Python API | |||||
######################### | |||||
Types from pytest | |||||
***************** | |||||
These types are defined by pytest, but are used extensively within the testing | |||||
scripts. | |||||
.. class:: _pytest.fixtures.FixtureRequest | |||||
.. seealso:: :class:`pytest.FixtureRequest` | |||||
.. class:: _pytest.tmpdir.TempPathFactory | |||||
.. seealso:: :class:`pytest.TempPathFactory` | |||||
Test Fixtures | |||||
************* | |||||
The following test fixtures are defined: | |||||
- :func:`~dds_ci.testing.fixtures.dds` - :class:`dds_ci.dds.DDSWrapper` - A | |||||
wrapper around the ``dds`` executable under test. | |||||
- :func:`~dds_ci.testing.fixtures.tmp_project` - | |||||
:class:`dds_ci.testing.fixtures.Project` - Create a new empty directory to be | |||||
used as a test project for ``dds`` to execute. | |||||
- :func:`~dds_ci.testing.http.http_repo` - | |||||
:class:`dds_ci.testing.http.RepoServer` - Create a new dds repository and | |||||
spawn an HTTP server to serve it. | |||||
Module: ``dds_ci`` | |||||
****************** | |||||
.. automodule:: dds_ci | |||||
:members: | |||||
Module: ``dds_ci.dds`` | |||||
********************** | |||||
.. automodule:: dds_ci.dds | |||||
:members: | |||||
Module: ``dds_ci.proc`` | |||||
*********************** | |||||
.. automodule:: dds_ci.proc | |||||
:members: | |||||
Module: ``dds_ci.testing`` | |||||
************************** | |||||
.. automodule:: dds_ci.testing | |||||
:members: | |||||
Module: ``dds_ci.testing.http`` | |||||
******************************* | |||||
.. automodule:: dds_ci.testing.http | |||||
:members: | |||||
Module: ``dds_ci.testing.fixtures`` | |||||
*********************************** | |||||
.. automodule:: dds_ci.testing.fixtures | |||||
:members: | |||||
Module: ``dds_ci.testing.error`` | |||||
******************************** | |||||
.. automodule:: dds_ci.testing.error | |||||
:members: |
Setting Up a Build/Development Environment | |||||
########################################## | |||||
While ``dds`` is able to build itself, several aspects of build infrastructure | |||||
are controlled via Python scripts. You will need Python 3.6 or later available | |||||
on your system to get started. | |||||
.. _Poetry: python-poetry.org | |||||
Getting Started with *Poetry* | |||||
***************************** | |||||
``dds`` CI runs atop `Poetry`_, a Python project management tool. While designed | |||||
for Python projects, it serves our purposes well. | |||||
Installing Poetry | |||||
================= | |||||
If you do not have Poetry already installed, it can be obtained easily for most | |||||
any platform. | |||||
`Refer to the Poetry "Installation" documentation to learn how to get Poetry on your platform <https://python-poetry.org/docs/#installation>`_. | |||||
The remainder of this documentation will assume you are able to execute | |||||
``poetry`` on your command-line. | |||||
Setting Up the Environment | |||||
========================== | |||||
To set up the scripts and Python dependencies required for CI and development, | |||||
simply execute the following command from within the root directory of the | |||||
project:: | |||||
$ poetry install | |||||
Poetry will then create a Python virtual environment that contains the Python | |||||
scripts and tools required for building and developing ``dds``. | |||||
The Python virtual environment that Poetry created can be inspected using | |||||
``poetry env info``, and can be deleted from the system using | |||||
``poetry env remove``. Refer to | |||||
`the Poetry documentation <https://python-poetry.org/docs>`_ for more | |||||
information about using Poetry. | |||||
Using the Poetry Environment | |||||
**************************** | |||||
Once the ``poetry install`` command has been executed, you will now be ready to | |||||
run the ``dds`` CI scripts and tools. | |||||
The scripts are installed into the virtual environment, and need not be globally | |||||
installed anywhere else on the system. You can only access these scripts by | |||||
going through Poetry. To run any individual command within the virtual | |||||
environment, use ``poetry run``:: | |||||
$ poetry run <some-command> | |||||
This will load the virtual environment, execute ``<some-command>``, then exit | |||||
the environment. This is useful for running CI scripts from outside of the | |||||
virtualenv. | |||||
**Alternatively**, the environment can be loaded persistently into a shell | |||||
session by using ``poetry shell``:: | |||||
$ poetry shell | |||||
This will spawn a new interactive shell process with the virtual environment | |||||
loaded, and you can now run any CI or development script without needing to | |||||
prefix them with ``poetry run``. | |||||
Going forward, the documentation will assume you have the environment loaded | |||||
as-if by ``poetry shell``, but any ``dds``-CI-specific command can also be | |||||
executed by prefixing the command with ``poetry run``. | |||||
Working With an MSVC Environment in VSCode | |||||
========================================== | |||||
If you use Visual Studio Code as your editor and MSVC as your C++ toolchain, | |||||
you'll need to load the MSVC environment as part of your build task. ``dds`` CI | |||||
has a script designed for this purpose. To use it, first load up a shell within | |||||
the Visual C++ environment, then, from within the previously create Poetry | |||||
environment, run ``gen-msvs-vsc-task``. This program will emit a Visual Studio | |||||
Code JSON build task that builds ``dds`` and also contains the environment | |||||
variables required for the MSVC toolchain to compile and link programs. You can | |||||
save this JSON task into ``.vscode/tasks.json`` to use as your primary build | |||||
task while hacking on ``dds``. | |||||
``dds`` Development | ``dds`` Development | ||||
################### | ################### | ||||
While prebuilt ``dds`` executables are `available on the GitHub page | |||||
<releases>`_, one may wish to build ``dds`` from source. | |||||
.. _releases: https://github.com/vector-of-bool/dds/releases | |||||
The ``dds`` build process is designed to be as turn-key simple as possible. | |||||
This section will discuss how to modify and build ``dds`` itself. | This section will discuss how to modify and build ``dds`` itself. | ||||
.. toctree:: | .. toctree:: | ||||
:maxdepth: 2 | :maxdepth: 2 | ||||
building | |||||
reqs | |||||
env | |||||
building | |||||
testing | |||||
ci-api |
Supported Platforms and Build Requirements | |||||
########################################## | |||||
``dds`` aims to be as cross-platform as possible. It currently build and | |||||
executes on **Windows**, **macOS**, **Linux**, and **FreeBSD**. Support for | |||||
additional platforms is possible but will require modifications to | |||||
``bootstrap.py`` that will allow it to be built on such platforms. | |||||
Build Requirements | |||||
****************** | |||||
Building ``dds`` has a simple set of requirements: | |||||
- **Python 3.6** or newer to run the bootstrap/CI scripts. | |||||
- A C++ compiler that has rudimentary support for several C++20 features, | |||||
including Concepts. Newer releases of Visual C++ that ship with **VS | |||||
2019** will be sufficient on Windows, as will **GCC 9** with ``-fconcepts`` on | |||||
other platforms. | |||||
.. note:: | |||||
On Windows, you will need to execute the build from within a Visual C++ | |||||
enabled environment. This may involve launching the build from a Visual | |||||
Studio Command Prompt. | |||||
.. note:: | |||||
At the time of writing, C++20 Concepts has not yet been released in Clang, | |||||
but should be available in LLVM/Clang 11 and newer. | |||||
Testing with ``pytest`` | |||||
####################### | |||||
For ``dds``'s more rigorous test suite, we use the ``pytest`` testing framework. | |||||
These tests are stored in the ``tests/`` directory and written in ``test_*.py`` | |||||
files. | |||||
The test suite can be run separately without ``dds-ci`` by executing ``pytest`` | |||||
from within the :doc:`Poetry virtual environment <env>`:: | |||||
$ pytest tests/ | |||||
Note that individual tests can take between a few seconds and a few minutes to | |||||
execute, so it may be useful to execute only a subset of the tests based on the | |||||
functionality you want to test. Refer to | |||||
`the pytest documentation <https://docs.pytest.org/en/latest/>` for more | |||||
information about using and executing ``pytest``. If you are running the full | |||||
test suite, you may also want to pass the ``-n`` argument with a number of | |||||
parallel jobs to execute. | |||||
.. highlight:: python | |||||
Writing Tests | |||||
************* | |||||
If a particular aspect of ``dds`` can be tested in isolation and within a few | |||||
dozen milliseconds, you should prefer to test it as a unit test in a | |||||
``*.test.cpp`` file. The ``pytest`` tests are intended to perform full | |||||
end-to-end feature and error handling tests. | |||||
Tests are grouped into individual Python files in the ``tests/`` directory. Any | |||||
Python file containing tests must have a filename beginning with ``test_``. | |||||
Individual test functions should begin with ``test_``. All test functions should | |||||
be properly type-annotated and successfully check via ``mypy``. | |||||
The ``dds`` test suite has access to a set of test fixtures that can be used | |||||
throughout tests to perform complex setup and teardown for complete test-by-test | |||||
isolation. | |||||
Here is a simple test that simple executes ``dds`` with ``--help``:: | |||||
def test_get_help(dds: DDSWrapper) -> None: | |||||
dds.run(['--help']) | |||||
In this test function, :func:`the dds object is a test fixture | |||||
<dds_ci.testing.fixtures.dds>` that wraps the ``dds`` executable under test. | |||||
Testing Error Handling | |||||
********************** | |||||
It is important that ``dds`` handle errors correctly, of course, including user | |||||
error. It is not simply enough to check that a certain operation fails: We must | |||||
be sure that it fails *correctly*. To check that the correct code path is | |||||
executed, ``dds`` can write a file containing a simple constant string | |||||
designating the error handling path that was taken. The file will be written to | |||||
the path indicated by the ``DDS_WRITE_ERROR_MARKER`` environment variable. | |||||
For examples of these error strings, search for usage of ``write_error_marker`` | |||||
in the ``dds`` source code. These should only execute within error-handling | |||||
contexts, should appear near the log messages that issue diagnostics, and should | |||||
be specific to the error at hand. | |||||
To write a test that checks for a given error-handling path, use the | |||||
:func:`~dds_ci.testing.error.expect_error_marker` context manager function:: | |||||
def test_sdist_invalid_project(tmp_project: Project) -> None: | |||||
# Trying to create a package archive from a project without a | |||||
# package.json5 is invalid. Check that it creates the correct | |||||
# error-message string | |||||
with error.expect_error_marker('no-package-json5'): | |||||
tmp_project.pkg_create() | |||||
[[package]] | |||||
name = "alabaster" | |||||
version = "0.7.12" | |||||
description = "A configurable sidebar-enabled Sphinx theme" | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = "*" | |||||
[[package]] | [[package]] | ||||
name = "apipkg" | name = "apipkg" | ||||
version = "1.5" | version = "1.5" | ||||
tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] | tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "zope.interface"] | ||||
tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] | tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six"] | ||||
[[package]] | |||||
name = "babel" | |||||
version = "2.9.0" | |||||
description = "Internationalization utilities" | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" | |||||
[package.dependencies] | |||||
pytz = ">=2015.7" | |||||
[[package]] | |||||
name = "certifi" | |||||
version = "2020.12.5" | |||||
description = "Python package for providing Mozilla's CA Bundle." | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = "*" | |||||
[[package]] | |||||
name = "chardet" | |||||
version = "4.0.0" | |||||
description = "Universal encoding detector for Python 2 and 3" | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" | |||||
[[package]] | [[package]] | ||||
name = "colorama" | name = "colorama" | ||||
version = "0.4.4" | version = "0.4.4" | ||||
optional = false | optional = false | ||||
python-versions = "*" | python-versions = "*" | ||||
[[package]] | |||||
name = "docutils" | |||||
version = "0.16" | |||||
description = "Docutils -- Python Documentation Utilities" | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" | |||||
[[package]] | [[package]] | ||||
name = "execnet" | name = "execnet" | ||||
version = "1.7.1" | version = "1.7.1" | ||||
[package.extras] | [package.extras] | ||||
testing = ["pre-commit"] | testing = ["pre-commit"] | ||||
[[package]] | |||||
name = "idna" | |||||
version = "2.10" | |||||
description = "Internationalized Domain Names in Applications (IDNA)" | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" | |||||
[[package]] | |||||
name = "imagesize" | |||||
version = "1.2.0" | |||||
description = "Getting image size from png/jpeg/jpeg2000/gif file" | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" | |||||
[[package]] | [[package]] | ||||
name = "importlib-metadata" | name = "importlib-metadata" | ||||
version = "3.1.1" | version = "3.1.1" | ||||
requirements_deprecated_finder = ["pipreqs", "pip-api"] | requirements_deprecated_finder = ["pipreqs", "pip-api"] | ||||
colors = ["colorama (>=0.4.3,<0.5.0)"] | colors = ["colorama (>=0.4.3,<0.5.0)"] | ||||
[[package]] | |||||
name = "jinja2" | |||||
version = "2.11.2" | |||||
description = "A very fast and expressive template engine." | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" | |||||
[package.dependencies] | |||||
MarkupSafe = ">=0.23" | |||||
[package.extras] | |||||
i18n = ["Babel (>=0.8)"] | |||||
[[package]] | [[package]] | ||||
name = "json5" | name = "json5" | ||||
version = "0.9.5" | version = "0.9.5" | ||||
optional = false | optional = false | ||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" | ||||
[[package]] | |||||
name = "markupsafe" | |||||
version = "1.1.1" | |||||
description = "Safely add untrusted strings to HTML/XML markup." | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" | |||||
[[package]] | [[package]] | ||||
name = "mccabe" | name = "mccabe" | ||||
version = "0.6.1" | version = "0.6.1" | ||||
optional = false | optional = false | ||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" | ||||
[[package]] | |||||
name = "pygments" | |||||
version = "2.7.3" | |||||
description = "Pygments is a syntax highlighting package written in Python." | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = ">=3.5" | |||||
[[package]] | [[package]] | ||||
name = "pylint" | name = "pylint" | ||||
version = "2.6.0" | version = "2.6.0" | ||||
psutil = ["psutil (>=3.0)"] | psutil = ["psutil (>=3.0)"] | ||||
testing = ["filelock"] | testing = ["filelock"] | ||||
[[package]] | |||||
name = "pytz" | |||||
version = "2020.5" | |||||
description = "World timezone definitions, modern and historical" | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = "*" | |||||
[[package]] | |||||
name = "requests" | |||||
version = "2.25.1" | |||||
description = "Python HTTP for Humans." | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" | |||||
[package.dependencies] | |||||
certifi = ">=2017.4.17" | |||||
chardet = ">=3.0.2,<5" | |||||
idna = ">=2.5,<3" | |||||
urllib3 = ">=1.21.1,<1.27" | |||||
[package.extras] | |||||
security = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)"] | |||||
socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"] | |||||
[[package]] | [[package]] | ||||
name = "rope" | name = "rope" | ||||
version = "0.18.0" | version = "0.18.0" | ||||
optional = false | optional = false | ||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" | ||||
[[package]] | |||||
name = "snowballstemmer" | |||||
version = "2.0.0" | |||||
description = "This package provides 26 stemmers for 25 languages generated from Snowball algorithms." | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = "*" | |||||
[[package]] | |||||
name = "sphinx" | |||||
version = "3.4.1" | |||||
description = "Python documentation generator" | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = ">=3.5" | |||||
[package.dependencies] | |||||
alabaster = ">=0.7,<0.8" | |||||
babel = ">=1.3" | |||||
colorama = {version = ">=0.3.5", markers = "sys_platform == \"win32\""} | |||||
docutils = ">=0.12" | |||||
imagesize = "*" | |||||
Jinja2 = ">=2.3" | |||||
packaging = "*" | |||||
Pygments = ">=2.0" | |||||
requests = ">=2.5.0" | |||||
snowballstemmer = ">=1.1" | |||||
sphinxcontrib-applehelp = "*" | |||||
sphinxcontrib-devhelp = "*" | |||||
sphinxcontrib-htmlhelp = "*" | |||||
sphinxcontrib-jsmath = "*" | |||||
sphinxcontrib-qthelp = "*" | |||||
sphinxcontrib-serializinghtml = "*" | |||||
[package.extras] | |||||
docs = ["sphinxcontrib-websupport"] | |||||
lint = ["flake8 (>=3.5.0)", "isort", "mypy (>=0.790)", "docutils-stubs"] | |||||
test = ["pytest", "pytest-cov", "html5lib", "cython", "typed-ast"] | |||||
[[package]] | |||||
name = "sphinxcontrib-applehelp" | |||||
version = "1.0.2" | |||||
description = "sphinxcontrib-applehelp is a sphinx extension which outputs Apple help books" | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = ">=3.5" | |||||
[package.extras] | |||||
lint = ["flake8", "mypy", "docutils-stubs"] | |||||
test = ["pytest"] | |||||
[[package]] | |||||
name = "sphinxcontrib-devhelp" | |||||
version = "1.0.2" | |||||
description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = ">=3.5" | |||||
[package.extras] | |||||
lint = ["flake8", "mypy", "docutils-stubs"] | |||||
test = ["pytest"] | |||||
[[package]] | |||||
name = "sphinxcontrib-htmlhelp" | |||||
version = "1.0.3" | |||||
description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = ">=3.5" | |||||
[package.extras] | |||||
lint = ["flake8", "mypy", "docutils-stubs"] | |||||
test = ["pytest", "html5lib"] | |||||
[[package]] | |||||
name = "sphinxcontrib-jsmath" | |||||
version = "1.0.1" | |||||
description = "A sphinx extension which renders display math in HTML via JavaScript" | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = ">=3.5" | |||||
[package.extras] | |||||
test = ["pytest", "flake8", "mypy"] | |||||
[[package]] | |||||
name = "sphinxcontrib-qthelp" | |||||
version = "1.0.3" | |||||
description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = ">=3.5" | |||||
[package.extras] | |||||
lint = ["flake8", "mypy", "docutils-stubs"] | |||||
test = ["pytest"] | |||||
[[package]] | |||||
name = "sphinxcontrib-serializinghtml" | |||||
version = "1.1.4" | |||||
description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = ">=3.5" | |||||
[package.extras] | |||||
lint = ["flake8", "mypy", "docutils-stubs"] | |||||
test = ["pytest"] | |||||
[[package]] | [[package]] | ||||
name = "toml" | name = "toml" | ||||
version = "0.10.2" | version = "0.10.2" | ||||
optional = false | optional = false | ||||
python-versions = "*" | python-versions = "*" | ||||
[[package]] | |||||
name = "urllib3" | |||||
version = "1.26.2" | |||||
description = "HTTP library with thread-safe connection pooling, file post, and more." | |||||
category = "dev" | |||||
optional = false | |||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" | |||||
[package.extras] | |||||
brotli = ["brotlipy (>=0.6.0)"] | |||||
secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"] | |||||
socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] | |||||
[[package]] | [[package]] | ||||
name = "wrapt" | name = "wrapt" | ||||
version = "1.12.1" | version = "1.12.1" | ||||
[metadata] | [metadata] | ||||
lock-version = "1.1" | lock-version = "1.1" | ||||
python-versions = "^3.6" | python-versions = "^3.6" | ||||
content-hash = "5c3cefd7d2a4b573928b14dc6291fbb7ef8a8a29306f7982ad64db4cb615e6e5" | |||||
content-hash = "d762128dfce333176ad89e2c60a91113c56efff1539f9ca1c7ab490c7ac05067" | |||||
[metadata.files] | [metadata.files] | ||||
alabaster = [ | |||||
{file = "alabaster-0.7.12-py2.py3-none-any.whl", hash = "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359"}, | |||||
{file = "alabaster-0.7.12.tar.gz", hash = "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"}, | |||||
] | |||||
apipkg = [ | apipkg = [ | ||||
{file = "apipkg-1.5-py2.py3-none-any.whl", hash = "sha256:58587dd4dc3daefad0487f6d9ae32b4542b185e1c36db6993290e7c41ca2b47c"}, | {file = "apipkg-1.5-py2.py3-none-any.whl", hash = "sha256:58587dd4dc3daefad0487f6d9ae32b4542b185e1c36db6993290e7c41ca2b47c"}, | ||||
{file = "apipkg-1.5.tar.gz", hash = "sha256:37228cda29411948b422fae072f57e31d3396d2ee1c9783775980ee9c9990af6"}, | {file = "apipkg-1.5.tar.gz", hash = "sha256:37228cda29411948b422fae072f57e31d3396d2ee1c9783775980ee9c9990af6"}, | ||||
{file = "attrs-20.3.0-py2.py3-none-any.whl", hash = "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6"}, | {file = "attrs-20.3.0-py2.py3-none-any.whl", hash = "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6"}, | ||||
{file = "attrs-20.3.0.tar.gz", hash = "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"}, | {file = "attrs-20.3.0.tar.gz", hash = "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"}, | ||||
] | ] | ||||
babel = [ | |||||
{file = "Babel-2.9.0-py2.py3-none-any.whl", hash = "sha256:9d35c22fcc79893c3ecc85ac4a56cde1ecf3f19c540bba0922308a6c06ca6fa5"}, | |||||
{file = "Babel-2.9.0.tar.gz", hash = "sha256:da031ab54472314f210b0adcff1588ee5d1d1d0ba4dbd07b94dba82bde791e05"}, | |||||
] | |||||
certifi = [ | |||||
{file = "certifi-2020.12.5-py2.py3-none-any.whl", hash = "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830"}, | |||||
{file = "certifi-2020.12.5.tar.gz", hash = "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c"}, | |||||
] | |||||
chardet = [ | |||||
{file = "chardet-4.0.0-py2.py3-none-any.whl", hash = "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5"}, | |||||
{file = "chardet-4.0.0.tar.gz", hash = "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa"}, | |||||
] | |||||
colorama = [ | colorama = [ | ||||
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, | {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, | ||||
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, | {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, | ||||
{file = "distro-1.5.0-py2.py3-none-any.whl", hash = "sha256:df74eed763e18d10d0da624258524ae80486432cd17392d9c3d96f5e83cd2799"}, | {file = "distro-1.5.0-py2.py3-none-any.whl", hash = "sha256:df74eed763e18d10d0da624258524ae80486432cd17392d9c3d96f5e83cd2799"}, | ||||
{file = "distro-1.5.0.tar.gz", hash = "sha256:0e58756ae38fbd8fc3020d54badb8eae17c5b9dcbed388b17bb55b8a5928df92"}, | {file = "distro-1.5.0.tar.gz", hash = "sha256:0e58756ae38fbd8fc3020d54badb8eae17c5b9dcbed388b17bb55b8a5928df92"}, | ||||
] | ] | ||||
docutils = [ | |||||
{file = "docutils-0.16-py2.py3-none-any.whl", hash = "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af"}, | |||||
{file = "docutils-0.16.tar.gz", hash = "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc"}, | |||||
] | |||||
execnet = [ | execnet = [ | ||||
{file = "execnet-1.7.1-py2.py3-none-any.whl", hash = "sha256:d4efd397930c46415f62f8a31388d6be4f27a91d7550eb79bc64a756e0056547"}, | {file = "execnet-1.7.1-py2.py3-none-any.whl", hash = "sha256:d4efd397930c46415f62f8a31388d6be4f27a91d7550eb79bc64a756e0056547"}, | ||||
{file = "execnet-1.7.1.tar.gz", hash = "sha256:cacb9df31c9680ec5f95553976c4da484d407e85e41c83cb812aa014f0eddc50"}, | {file = "execnet-1.7.1.tar.gz", hash = "sha256:cacb9df31c9680ec5f95553976c4da484d407e85e41c83cb812aa014f0eddc50"}, | ||||
] | ] | ||||
idna = [ | |||||
{file = "idna-2.10-py2.py3-none-any.whl", hash = "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0"}, | |||||
{file = "idna-2.10.tar.gz", hash = "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6"}, | |||||
] | |||||
imagesize = [ | |||||
{file = "imagesize-1.2.0-py2.py3-none-any.whl", hash = "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1"}, | |||||
{file = "imagesize-1.2.0.tar.gz", hash = "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1"}, | |||||
] | |||||
importlib-metadata = [ | importlib-metadata = [ | ||||
{file = "importlib_metadata-3.1.1-py3-none-any.whl", hash = "sha256:6112e21359ef8f344e7178aa5b72dc6e62b38b0d008e6d3cb212c5b84df72013"}, | {file = "importlib_metadata-3.1.1-py3-none-any.whl", hash = "sha256:6112e21359ef8f344e7178aa5b72dc6e62b38b0d008e6d3cb212c5b84df72013"}, | ||||
{file = "importlib_metadata-3.1.1.tar.gz", hash = "sha256:b0c2d3b226157ae4517d9625decf63591461c66b3a808c2666d538946519d170"}, | {file = "importlib_metadata-3.1.1.tar.gz", hash = "sha256:b0c2d3b226157ae4517d9625decf63591461c66b3a808c2666d538946519d170"}, | ||||
{file = "isort-5.6.4-py3-none-any.whl", hash = "sha256:dcab1d98b469a12a1a624ead220584391648790275560e1a43e54c5dceae65e7"}, | {file = "isort-5.6.4-py3-none-any.whl", hash = "sha256:dcab1d98b469a12a1a624ead220584391648790275560e1a43e54c5dceae65e7"}, | ||||
{file = "isort-5.6.4.tar.gz", hash = "sha256:dcaeec1b5f0eca77faea2a35ab790b4f3680ff75590bfcb7145986905aab2f58"}, | {file = "isort-5.6.4.tar.gz", hash = "sha256:dcaeec1b5f0eca77faea2a35ab790b4f3680ff75590bfcb7145986905aab2f58"}, | ||||
] | ] | ||||
jinja2 = [ | |||||
{file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"}, | |||||
{file = "Jinja2-2.11.2.tar.gz", hash = "sha256:89aab215427ef59c34ad58735269eb58b1a5808103067f7bb9d5836c651b3bb0"}, | |||||
] | |||||
json5 = [ | json5 = [ | ||||
{file = "json5-0.9.5-py2.py3-none-any.whl", hash = "sha256:af1a1b9a2850c7f62c23fde18be4749b3599fd302f494eebf957e2ada6b9e42c"}, | {file = "json5-0.9.5-py2.py3-none-any.whl", hash = "sha256:af1a1b9a2850c7f62c23fde18be4749b3599fd302f494eebf957e2ada6b9e42c"}, | ||||
{file = "json5-0.9.5.tar.gz", hash = "sha256:703cfee540790576b56a92e1c6aaa6c4b0d98971dc358ead83812aa4d06bdb96"}, | {file = "json5-0.9.5.tar.gz", hash = "sha256:703cfee540790576b56a92e1c6aaa6c4b0d98971dc358ead83812aa4d06bdb96"}, | ||||
{file = "lazy_object_proxy-1.4.3-cp38-cp38-win32.whl", hash = "sha256:5541cada25cd173702dbd99f8e22434105456314462326f06dba3e180f203dfd"}, | {file = "lazy_object_proxy-1.4.3-cp38-cp38-win32.whl", hash = "sha256:5541cada25cd173702dbd99f8e22434105456314462326f06dba3e180f203dfd"}, | ||||
{file = "lazy_object_proxy-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239"}, | {file = "lazy_object_proxy-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:59f79fef100b09564bc2df42ea2d8d21a64fdcda64979c0fa3db7bdaabaf6239"}, | ||||
] | ] | ||||
markupsafe = [ | |||||
{file = "MarkupSafe-1.1.1-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161"}, | |||||
{file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"}, | |||||
{file = "MarkupSafe-1.1.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183"}, | |||||
{file = "MarkupSafe-1.1.1-cp27-cp27m-win32.whl", hash = "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b"}, | |||||
{file = "MarkupSafe-1.1.1-cp27-cp27m-win_amd64.whl", hash = "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e"}, | |||||
{file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f"}, | |||||
{file = "MarkupSafe-1.1.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1"}, | |||||
{file = "MarkupSafe-1.1.1-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5"}, | |||||
{file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1"}, | |||||
{file = "MarkupSafe-1.1.1-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735"}, | |||||
{file = "MarkupSafe-1.1.1-cp34-cp34m-win32.whl", hash = "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21"}, | |||||
{file = "MarkupSafe-1.1.1-cp34-cp34m-win_amd64.whl", hash = "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235"}, | |||||
{file = "MarkupSafe-1.1.1-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b"}, | |||||
{file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f"}, | |||||
{file = "MarkupSafe-1.1.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905"}, | |||||
{file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"}, | |||||
{file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"}, | |||||
{file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"}, | |||||
{file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"}, | |||||
{file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"}, | |||||
{file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"}, | |||||
{file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"}, | |||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"}, | |||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"}, | |||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"}, | |||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"}, | |||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"}, | |||||
{file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"}, | |||||
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"}, | |||||
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"}, | |||||
{file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"}, | |||||
{file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"}, | |||||
{file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"}, | |||||
] | |||||
mccabe = [ | mccabe = [ | ||||
{file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, | {file = "mccabe-0.6.1-py2.py3-none-any.whl", hash = "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42"}, | ||||
{file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, | {file = "mccabe-0.6.1.tar.gz", hash = "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f"}, | ||||
{file = "py-1.9.0-py2.py3-none-any.whl", hash = "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2"}, | {file = "py-1.9.0-py2.py3-none-any.whl", hash = "sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2"}, | ||||
{file = "py-1.9.0.tar.gz", hash = "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342"}, | {file = "py-1.9.0.tar.gz", hash = "sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342"}, | ||||
] | ] | ||||
pygments = [ | |||||
{file = "Pygments-2.7.3-py3-none-any.whl", hash = "sha256:f275b6c0909e5dafd2d6269a656aa90fa58ebf4a74f8fcf9053195d226b24a08"}, | |||||
{file = "Pygments-2.7.3.tar.gz", hash = "sha256:ccf3acacf3782cbed4a989426012f1c535c9a90d3a7fc3f16d231b9372d2b716"}, | |||||
] | |||||
pylint = [ | pylint = [ | ||||
{file = "pylint-2.6.0-py3-none-any.whl", hash = "sha256:bfe68f020f8a0fece830a22dd4d5dddb4ecc6137db04face4c3420a46a52239f"}, | {file = "pylint-2.6.0-py3-none-any.whl", hash = "sha256:bfe68f020f8a0fece830a22dd4d5dddb4ecc6137db04face4c3420a46a52239f"}, | ||||
{file = "pylint-2.6.0.tar.gz", hash = "sha256:bb4a908c9dadbc3aac18860550e870f58e1a02c9f2c204fdf5693d73be061210"}, | {file = "pylint-2.6.0.tar.gz", hash = "sha256:bb4a908c9dadbc3aac18860550e870f58e1a02c9f2c204fdf5693d73be061210"}, | ||||
{file = "pytest-xdist-2.1.0.tar.gz", hash = "sha256:82d938f1a24186520e2d9d3a64ef7d9ac7ecdf1a0659e095d18e596b8cbd0672"}, | {file = "pytest-xdist-2.1.0.tar.gz", hash = "sha256:82d938f1a24186520e2d9d3a64ef7d9ac7ecdf1a0659e095d18e596b8cbd0672"}, | ||||
{file = "pytest_xdist-2.1.0-py3-none-any.whl", hash = "sha256:7c629016b3bb006b88ac68e2b31551e7becf173c76b977768848e2bbed594d90"}, | {file = "pytest_xdist-2.1.0-py3-none-any.whl", hash = "sha256:7c629016b3bb006b88ac68e2b31551e7becf173c76b977768848e2bbed594d90"}, | ||||
] | ] | ||||
pytz = [ | |||||
{file = "pytz-2020.5-py2.py3-none-any.whl", hash = "sha256:16962c5fb8db4a8f63a26646d8886e9d769b6c511543557bc84e9569fb9a9cb4"}, | |||||
{file = "pytz-2020.5.tar.gz", hash = "sha256:180befebb1927b16f6b57101720075a984c019ac16b1b7575673bea42c6c3da5"}, | |||||
] | |||||
requests = [ | |||||
{file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"}, | |||||
{file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"}, | |||||
] | |||||
rope = [ | rope = [ | ||||
{file = "rope-0.18.0.tar.gz", hash = "sha256:786b5c38c530d4846aa68a42604f61b4e69a493390e3ca11b88df0fbfdc3ed04"}, | {file = "rope-0.18.0.tar.gz", hash = "sha256:786b5c38c530d4846aa68a42604f61b4e69a493390e3ca11b88df0fbfdc3ed04"}, | ||||
] | ] | ||||
{file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, | {file = "six-1.15.0-py2.py3-none-any.whl", hash = "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"}, | ||||
{file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, | {file = "six-1.15.0.tar.gz", hash = "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259"}, | ||||
] | ] | ||||
snowballstemmer = [ | |||||
{file = "snowballstemmer-2.0.0-py2.py3-none-any.whl", hash = "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0"}, | |||||
{file = "snowballstemmer-2.0.0.tar.gz", hash = "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"}, | |||||
] | |||||
sphinx = [ | |||||
{file = "Sphinx-3.4.1-py3-none-any.whl", hash = "sha256:aeef652b14629431c82d3fe994ce39ead65b3fe87cf41b9a3714168ff8b83376"}, | |||||
{file = "Sphinx-3.4.1.tar.gz", hash = "sha256:e450cb205ff8924611085183bf1353da26802ae73d9251a8fcdf220a8f8712ef"}, | |||||
] | |||||
sphinxcontrib-applehelp = [ | |||||
{file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, | |||||
{file = "sphinxcontrib_applehelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a"}, | |||||
] | |||||
sphinxcontrib-devhelp = [ | |||||
{file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, | |||||
{file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, | |||||
] | |||||
sphinxcontrib-htmlhelp = [ | |||||
{file = "sphinxcontrib-htmlhelp-1.0.3.tar.gz", hash = "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b"}, | |||||
{file = "sphinxcontrib_htmlhelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f"}, | |||||
] | |||||
sphinxcontrib-jsmath = [ | |||||
{file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, | |||||
{file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, | |||||
] | |||||
sphinxcontrib-qthelp = [ | |||||
{file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, | |||||
{file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, | |||||
] | |||||
sphinxcontrib-serializinghtml = [ | |||||
{file = "sphinxcontrib-serializinghtml-1.1.4.tar.gz", hash = "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc"}, | |||||
{file = "sphinxcontrib_serializinghtml-1.1.4-py2.py3-none-any.whl", hash = "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a"}, | |||||
] | |||||
toml = [ | toml = [ | ||||
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, | {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, | ||||
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, | {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, | ||||
{file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"}, | {file = "typing_extensions-3.7.4.3-py3-none-any.whl", hash = "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918"}, | ||||
{file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"}, | {file = "typing_extensions-3.7.4.3.tar.gz", hash = "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c"}, | ||||
] | ] | ||||
urllib3 = [ | |||||
{file = "urllib3-1.26.2-py2.py3-none-any.whl", hash = "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473"}, | |||||
{file = "urllib3-1.26.2.tar.gz", hash = "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08"}, | |||||
] | |||||
wrapt = [ | wrapt = [ | ||||
{file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"}, | {file = "wrapt-1.12.1.tar.gz", hash = "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"}, | ||||
] | ] |
mypy = "^0.790" | mypy = "^0.790" | ||||
rope = "^0.18.0" | rope = "^0.18.0" | ||||
yapf = "^0.30.0" | yapf = "^0.30.0" | ||||
Sphinx = "^3.4.1" | |||||
[tool.poetry.scripts] | [tool.poetry.scripts] | ||||
dds-ci = "dds_ci.main:start" | dds-ci = "dds_ci.main:start" |
to build the new dds. Returns a DDSWrapper around the generated test executable. | to build the new dds. Returns a DDSWrapper around the generated test executable. | ||||
""" | """ | ||||
test_tc = args.test_toolchain or toolchain.get_default_audit_toolchain() | test_tc = args.test_toolchain or toolchain.get_default_audit_toolchain() | ||||
print(f'Test build is building with toolchain: {test_tc}') | |||||
build_dir = paths.BUILD_DIR | build_dir = paths.BUILD_DIR | ||||
with toolchain.fixup_toolchain(test_tc) as new_tc: | with toolchain.fixup_toolchain(test_tc) as new_tc: | ||||
dds.build(toolchain=new_tc, root=paths.PROJECT_ROOT, build_root=build_dir, jobs=args.jobs, timeout=60 * 15) | dds.build(toolchain=new_tc, root=paths.PROJECT_ROOT, build_root=build_dir, jobs=args.jobs, timeout=60 * 15) | ||||
main_tc = args.toolchain or ( | main_tc = args.toolchain or ( | ||||
# If we are in rapid-dev mode, use the test toolchain, which had audit/debug enabled | # If we are in rapid-dev mode, use the test toolchain, which had audit/debug enabled | ||||
toolchain.get_default_toolchain() if not args.rapid else toolchain.get_default_audit_toolchain()) | toolchain.get_default_toolchain() if not args.rapid else toolchain.get_default_audit_toolchain()) | ||||
print(f'Building with toolchain: {main_tc}') | |||||
with toolchain.fixup_toolchain(main_tc) as new_tc: | with toolchain.fixup_toolchain(main_tc) as new_tc: | ||||
try: | try: | ||||
dds.build(toolchain=new_tc, | dds.build(toolchain=new_tc, |
""" | """ | ||||
Test utility for error checking | |||||
Test utilities for error checking | |||||
""" | """ | ||||
from contextlib import contextmanager | from contextlib import contextmanager | ||||
@contextmanager | @contextmanager | ||||
def expect_error_marker(expect: str) -> Iterator[None]: | def expect_error_marker(expect: str) -> Iterator[None]: | ||||
""" | |||||
A context-manager function that should wrap a scope that causes an error | |||||
from ``dds``. | |||||
:param expect: The error message ID string that is expected to appear. | |||||
The wrapped scope should raise :class:`subprocess.CalledProcessError`. | |||||
After handling the exception, asserts that the subprocess wrote an | |||||
error marker containing the string given in ``expect``. | |||||
""" | |||||
tdir = Path(tempfile.mkdtemp()) | tdir = Path(tempfile.mkdtemp()) | ||||
err_file = tdir / 'error' | err_file = tdir / 'error' | ||||
try: | try: |
class Project: | class Project: | ||||
""" | |||||
Utilities to access a project being used as a test. | |||||
""" | |||||
def __init__(self, dirpath: Path, dds: DDSWrapper) -> None: | def __init__(self, dirpath: Path, dds: DDSWrapper) -> None: | ||||
self.dds = dds | |||||
self.dds = dds.clone() | |||||
self.root = dirpath | self.root = dirpath | ||||
self.build_root = dirpath / '_build' | self.build_root = dirpath / '_build' | ||||
@property | @property | ||||
def package_json(self) -> PackageJSON: | def package_json(self) -> PackageJSON: | ||||
""" | |||||
Get/set the content of the `package.json` file for the project. | |||||
""" | |||||
return cast(PackageJSON, json.loads(self.root.joinpath('package.jsonc').read_text())) | return cast(PackageJSON, json.loads(self.root.joinpath('package.jsonc').read_text())) | ||||
@package_json.setter | @package_json.setter | ||||
@property | @property | ||||
def library_json(self) -> LibraryJSON: | def library_json(self) -> LibraryJSON: | ||||
""" | |||||
Get/set the content of the `library.json` file for the project. | |||||
""" | |||||
return cast(LibraryJSON, json.loads(self.root.joinpath('library.jsonc').read_text())) | return cast(LibraryJSON, json.loads(self.root.joinpath('library.jsonc').read_text())) | ||||
@library_json.setter | @library_json.setter | ||||
self.dds.run(['sdist', 'export', self.dds.cache_dir_arg, self.project_dir_arg]) | self.dds.run(['sdist', 'export', self.dds.cache_dir_arg, self.project_dir_arg]) | ||||
def write(self, path: Pathish, content: str) -> Path: | def write(self, path: Pathish, content: str) -> Path: | ||||
""" | |||||
Write the given `content` to `path`. If `path` is relative, it will | |||||
be resolved relative to the root directory of this project. | |||||
""" | |||||
path = Path(path) | path = Path(path) | ||||
if not path.is_absolute(): | if not path.is_absolute(): | ||||
path = self.root / path | path = self.root / path | ||||
@pytest.fixture() | @pytest.fixture() | ||||
def test_parent_dir(request: FixtureRequest) -> Path: | def test_parent_dir(request: FixtureRequest) -> Path: | ||||
""" | |||||
:class:`pathlib.Path` fixture pointing to the parent directory of the file | |||||
containing the test that is requesting the current fixture | |||||
""" | |||||
return Path(request.fspath).parent | return Path(request.fspath).parent | ||||
class ProjectOpener(): | class ProjectOpener(): | ||||
""" | |||||
A test fixture that opens project directories for testing | |||||
""" | |||||
def __init__(self, dds: DDSWrapper, request: FixtureRequest, worker: str, | def __init__(self, dds: DDSWrapper, request: FixtureRequest, worker: str, | ||||
tmp_path_factory: TempPathFactory) -> None: | tmp_path_factory: TempPathFactory) -> None: | ||||
self.dds = dds | self.dds = dds | ||||
return Path(self._request.fspath).parent | return Path(self._request.fspath).parent | ||||
def open(self, dirpath: Pathish) -> Project: | def open(self, dirpath: Pathish) -> Project: | ||||
""" | |||||
Open a new project testing fixture from the given project directory. | |||||
:param dirpath: The directory that contains the project to use. | |||||
Clones the given directory and then opens a project within that clone. | |||||
The clone directory will be destroyed when the test fixture is torn down. | |||||
""" | |||||
dirpath = Path(dirpath) | dirpath = Path(dirpath) | ||||
if not dirpath.is_absolute(): | if not dirpath.is_absolute(): | ||||
dirpath = self.test_dir / dirpath | dirpath = self.test_dir / dirpath | ||||
@pytest.fixture() | @pytest.fixture() | ||||
def project_opener(request: FixtureRequest, worker_id: str, dds: DDSWrapper, | def project_opener(request: FixtureRequest, worker_id: str, dds: DDSWrapper, | ||||
tmp_path_factory: TempPathFactory) -> ProjectOpener: | tmp_path_factory: TempPathFactory) -> ProjectOpener: | ||||
""" | |||||
A fixture factory that can open directories as Project objects for building | |||||
and testing. Duplicates the project directory into a temporary location so | |||||
that the original test directory remains unchanged. | |||||
""" | |||||
opener = ProjectOpener(dds, request, worker_id, tmp_path_factory) | opener = ProjectOpener(dds, request, worker_id, tmp_path_factory) | ||||
return opener | return opener | ||||
@pytest.fixture() | @pytest.fixture() | ||||
def tmp_project(request: FixtureRequest, worker_id: str, project_opener: ProjectOpener, | def tmp_project(request: FixtureRequest, worker_id: str, project_opener: ProjectOpener, | ||||
tmp_path_factory: TempPathFactory) -> Project: | tmp_path_factory: TempPathFactory) -> Project: | ||||
""" | |||||
A fixture that generates an empty temporary project directory that will be thrown away | |||||
when the test completes. | |||||
""" | |||||
if worker_id != 'master': | if worker_id != 'master': | ||||
proj_dir = tmp_path_factory.mktemp('temp-project') | proj_dir = tmp_path_factory.mktemp('temp-project') | ||||
return project_opener.open(proj_dir) | return project_opener.open(proj_dir) | ||||
@pytest.fixture(scope='session') | @pytest.fixture(scope='session') | ||||
def dds(dds_exe: Path) -> NewDDSWrapper: | def dds(dds_exe: Path) -> NewDDSWrapper: | ||||
""" | |||||
A :class:`~dds_ci.dds.DDSWrapper` around the dds executable under test | |||||
""" | |||||
wr = NewDDSWrapper(dds_exe) | wr = NewDDSWrapper(dds_exe) | ||||
return wr | return wr | ||||
@pytest.fixture(scope='session') | @pytest.fixture(scope='session') | ||||
def dds_exe(pytestconfig: PyTestConfig) -> Path: | def dds_exe(pytestconfig: PyTestConfig) -> Path: | ||||
"""A :class:`pathlib.Path` pointing to the DDS executable under test""" | |||||
opt = pytestconfig.getoption('--dds-exe') or paths.BUILD_DIR / 'dds' | opt = pytestconfig.getoption('--dds-exe') or paths.BUILD_DIR / 'dds' | ||||
return Path(opt) | return Path(opt) |