From d6a8bbaad75ae6ffa5eda40dbc5234c8c808a425 Mon Sep 17 00:00:00 2001 From: Jeremy Retailleau Date: Tue, 20 Aug 2024 10:40:05 -0700 Subject: [PATCH] Update documentation and testing logic - Update documentation release scripts to use sphinx-cmake instead of embedded the sphinx CMake module; - Use custom logic instead of 'lowdown' to handle changelog, as it doesn't seem to be maintained; - Update README to indicate support of CMake 3.30; - Use requirements.txt file to track Python dependencies used for testing; - Update documentation. --- .github/workflows/docs-deploy.yml | 16 ++--- .github/workflows/test-linux.yml | 12 ++-- .github/workflows/test-windows.yml | 22 +++---- README.md | 2 +- cmake/modules/FindSphinx.cmake | 64 ------------------- doc/CMakeLists.txt | 4 +- doc/requirements.txt | 8 +-- doc/sphinx/_extensions/changelog.py | 91 ++++++++++++++++++++++++++++ doc/sphinx/_static/style.css | 62 +++++++++++++++++++ doc/sphinx/conf.py | 32 ++++++---- doc/sphinx/doxygen.py | 64 +++++++++---------- doc/sphinx/glossary.rst | 6 -- doc/sphinx/installing.rst | 17 +++--- doc/sphinx/release/release_notes.rst | 20 +++++- test/requirements.txt | 2 + 15 files changed, 262 insertions(+), 160 deletions(-) delete mode 100644 cmake/modules/FindSphinx.cmake create mode 100644 doc/sphinx/_extensions/changelog.py create mode 100644 doc/sphinx/_static/style.css create mode 100644 test/requirements.txt diff --git a/.github/workflows/docs-deploy.yml b/.github/workflows/docs-deploy.yml index 41ae449..d25dbc6 100644 --- a/.github/workflows/docs-deploy.yml +++ b/.github/workflows/docs-deploy.yml @@ -19,9 +19,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: 3.9 @@ -30,21 +30,21 @@ jobs: sudo apt update sudo apt install -y doxygen python -m pip install --upgrade pip - python -m pip install -r ${GITHUB_WORKSPACE}/doc/requirements.txt - mkdir -p ${{runner.workspace}}/build + python -m pip install -r ${{github.workspace}}/doc/requirements.txt + mkdir -p ${{github.workspace}}/build - name: Build documentation run: | export BUILD_DOCS_WITHOUT_CMAKE=1 - export PYTHONPATH="${GITHUB_WORKSPACE}/doc/sphinx" + export PYTHONPATH="${{github.workspace}}/doc/sphinx" sphinx-build -T -E -b html \ - "${GITHUB_WORKSPACE}/doc/sphinx" \ - "${{runner.workspace}}/build" + "${{github.workspace}}/doc/sphinx" \ + "${{github.workspace}}/build" - name: Upload artifact uses: actions/upload-pages-artifact@v1 with: - path: ${{runner.workspace}}/build + path: ${{github.workspace}}/build deploy: environment: diff --git a/.github/workflows/test-linux.yml b/.github/workflows/test-linux.yml index 360cd0c..cd0225f 100644 --- a/.github/workflows/test-linux.yml +++ b/.github/workflows/test-linux.yml @@ -30,10 +30,10 @@ jobs: name: "USD-${{ matrix.usd }}-py${{ matrix.python }}" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} @@ -41,7 +41,7 @@ jobs: run: | sudo apt update sudo apt install -y libgtest-dev ninja-build - pip install pytest pytest-cmake + python -m pip install -r ${{github.workspace}}/test/requirements.txt mkdir -p ${{github.workspace}}/build mkdir -p ${{runner.temp}}/USD @@ -68,17 +68,17 @@ jobs: -D "BUILD_DOCS=OFF" \ -D "CMAKE_INCLUDE_PATH=${{runner.temp}}/USD/include" \ -D "CMAKE_LIBRARY_PATH=${{runner.temp}}/USD/lib" \ - ${GITHUB_WORKSPACE} + .. cmake --build . --config Release - name: Check for formatting errors working-directory: ${{github.workspace}}/build run: | cmake --build . --target format - STATUS_OUTPUT=$(git -C ${GITHUB_WORKSPACE} status --porcelain) + STATUS_OUTPUT=$(git -C .. status --porcelain) if [ -n "$STATUS_OUTPUT" ]; then echo "Code formatting errors found:" - git -C ${GITHUB_WORKSPACE} diff + git -C .. diff exit 1 else echo "No formatting errors found." diff --git a/.github/workflows/test-windows.yml b/.github/workflows/test-windows.yml index 7b2e18b..c93fd30 100644 --- a/.github/workflows/test-windows.yml +++ b/.github/workflows/test-windows.yml @@ -30,19 +30,19 @@ jobs: name: "USD-${{ matrix.usd }}-py${{ matrix.python }}" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} - name: Create Build Environment run: | vcpkg install --triplet=x64-windows gtest - pip install pytest pytest-cmake - cmake -E make_directory ${{runner.workspace}}/build - cmake -E make_directory ${{runner.temp}}/USD + python -m pip install -r ${{github.workspace}}\test\requirements.txt + cmake -E make_directory ${{github.workspace}}\build + cmake -E make_directory ${{runner.temp}}\USD - name: Install USD working-directory: ${{runner.temp}}/USD @@ -66,7 +66,7 @@ jobs: - name: Configure & Build shell: bash - working-directory: ${{runner.workspace}}/build + working-directory: ${{github.workspace}}/build run: | export PATH="${{runner.temp}}/USD/bin;${{runner.temp}}/USD/lib;${PATH}" export PYTHONPATH="${{runner.temp}}/USD/lib/python;${PYTHONPATH}" @@ -77,18 +77,18 @@ jobs: -D "BUILD_DOCS=OFF" \ -D "CMAKE_INCLUDE_PATH=${{runner.temp}}/USD/include" \ -D "CMAKE_LIBRARY_PATH=${{runner.temp}}/USD/lib" \ - '${{github.workspace}}' + .. cmake --build . --config Release - name: Check for formatting errors shell: bash - working-directory: ${{runner.workspace}}/build + working-directory: ${{github.workspace}}/build run: | cmake --build . --target format - STATUS_OUTPUT=$(git -C ${GITHUB_WORKSPACE} status --porcelain) + STATUS_OUTPUT=$(git -C .. status --porcelain) if [ -n "$STATUS_OUTPUT" ]; then echo "Code formatting errors found:" - git -C ${GITHUB_WORKSPACE} diff + git -C .. diff exit 1 else echo "No formatting errors found." @@ -96,7 +96,7 @@ jobs: - name: Run Test shell: bash - working-directory: ${{runner.workspace}}/build + working-directory: ${{github.workspace}}/build run: ctest -VV -C Release env: CTEST_OUTPUT_ON_FAILURE: True diff --git a/README.md b/README.md index 1b4ab76..67bd5e4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # USD Notice Framework -[![CMake](https://img.shields.io/badge/CMake-3.20...3.29-blue.svg?logo=CMake&logoColor=blue)](https://cmake.org) +[![CMake](https://img.shields.io/badge/CMake-3.20...3.30-blue.svg?logo=CMake&logoColor=blue)](https://cmake.org) [![test-linux](https://github.com/wdas/unf/actions/workflows/test-linux.yml/badge.svg?branch=main)](https://github.com/wdas/unf/actions/workflows/test-linux.yml) [![test-windows](https://github.com/wdas/unf/actions/workflows/test-windows.yml/badge.svg?branch=main)](https://github.com/wdas/unf/actions/workflows/test-windows.yml) [![License](https://img.shields.io/badge/License-Modified%20Apache%202.0-yellow.svg)](https://github.com/wdas/unf/blob/main/LICENSE.txt) diff --git a/cmake/modules/FindSphinx.cmake b/cmake/modules/FindSphinx.cmake deleted file mode 100644 index 30da9f4..0000000 --- a/cmake/modules/FindSphinx.cmake +++ /dev/null @@ -1,64 +0,0 @@ -# Discover required Sphinx target. -# -# This module defines the following imported targets: -# Sphinx::Build -# -# It also exposes the 'sphinx_add_docs' function which adds a target -# for generating documentation with Sphinx. -# -# Usage: -# find_package(Sphinx) -# find_package(Sphinx REQUIRED) -# find_package(Sphinx 1.8.6 REQUIRED) -# -# Note: -# The Sphinx_ROOT environment variable or CMake variable can be used to -# prepend a custom search path. -# (https://cmake.org/cmake/help/latest/policy/CMP0074.html) - -include(FindPackageHandleStandardArgs) - -find_program(SPHINX_EXECUTABLE NAMES sphinx-build) - -if(SPHINX_EXECUTABLE) - execute_process( - COMMAND "${SPHINX_EXECUTABLE}" --version - OUTPUT_VARIABLE _version - ERROR_VARIABLE _version - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - if (_version MATCHES " ([0-9]+\\.[0-9]+\\.[0-9]+)$") - set(SPHINX_VERSION "${CMAKE_MATCH_1}") - endif() - - mark_as_advanced(_version) -endif() - -mark_as_advanced(SPHINX_EXECUTABLE SPHINX_VERSION) - -find_package_handle_standard_args( - Sphinx - REQUIRED_VARS - SPHINX_EXECUTABLE - VERSION_VAR - SPHINX_VERSION -) - -if (Sphinx_FOUND AND NOT TARGET Sphinx::Build) - add_executable(Sphinx::Build IMPORTED GLOBAL) - set_target_properties(Sphinx::Build PROPERTIES - IMPORTED_LOCATION "${SPHINX_EXECUTABLE}" - ) - - function(sphinx_add_docs targetName) - cmake_parse_arguments(PARSE_ARGV 1 "" "" "SOURCE;OUTPUT" "DEPENDS") - - add_custom_target(${targetName} VERBATIM - COMMAND ${CMAKE_COMMAND} -E make_directory ${_OUTPUT} - COMMAND Sphinx::Build -b html ${_SOURCE} ${_OUTPUT} - COMMENT "Generate documentation for ${targetName}" - DEPENDS ${_DEPENDS} - ) - endfunction() -endif() diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 6843e30..0f99c46 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -26,8 +26,8 @@ file(COPY sphinx DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) configure_file(sphinx/conf.py sphinx/conf.py @ONLY) sphinx_add_docs(unfDoc - SOURCE "${CMAKE_CURRENT_BINARY_DIR}/sphinx" - OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/doc" + SOURCE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/sphinx" + OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/doc" DEPENDS unfApiRefDoc ) diff --git a/doc/requirements.txt b/doc/requirements.txt index 0643cea..75e27a6 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -1,4 +1,4 @@ -Lowdown==0.2.1 -Sphinx==5.1.1 -sphinx-rtd-theme==1.0.0 -sphinxcontrib-doxylink==1.12.2 +Sphinx==7.* +sphinx-cmake==0.* +sphinx-rtd-theme==2.* +sphinxcontrib-doxylink==1.* \ No newline at end of file diff --git a/doc/sphinx/_extensions/changelog.py b/doc/sphinx/_extensions/changelog.py new file mode 100644 index 0000000..b9f06a6 --- /dev/null +++ b/doc/sphinx/_extensions/changelog.py @@ -0,0 +1,91 @@ +from datetime import datetime + +from docutils import nodes +from docutils.parsers.rst import directives +from sphinx.util.docutils import SphinxDirective + + +class ReleaseDirective(SphinxDirective): + has_content = True + required_arguments = 1 + optional_arguments = 0 + option_spec = { + "date": directives.unchanged_required + } + + def run(self): + """Creates a section for release notes with version and date.""" + version = self.arguments[0] + + # Fetch today's date as default if no date is provided + today_date_str = datetime.now().strftime("%Y-%m-%d") + date_str = self.options.get("date", today_date_str) + + try: + parsed_date = datetime.strptime(date_str, "%Y-%m-%d") + release_date = parsed_date.strftime("%e %B %Y") + except ValueError: + raise ValueError(f"Invalid date format: {date_str}") + + # Create the version title node + version_node = nodes.strong(text=version) + section_title = nodes.title("", "", version_node) + + # Create the section node with a specific ID + section_id = f"release-{version.replace(' ', '-')}" + section = nodes.section( + "", section_title, + ids=[section_id], + classes=["changelog-release"] + ) + + # Append formatted date + section.append( + nodes.emphasis(text=release_date, classes=["release-date"]) + ) + + # Parse content into a list of changes + content_node = nodes.Element() + self.state.nested_parse(self.content, self.content_offset, content_node) + + # Create a bullet list of changes + changes_list = nodes.bullet_list("", classes=["changelog-change-list"]) + for child in content_node: + item = nodes.list_item("") + item.append(child) + changes_list.append(item) + + section.append(changes_list) + + return [section] + + +class ChangeDirective(SphinxDirective): + has_content = True + required_arguments = 1 + optional_arguments = 0 + + def run(self): + """Generates a categorized list item for a changelog entry.""" + category = self.arguments[0] + + # Create a paragraph for the category with specific styling + class_name = f"changelog-category-{category.lower().replace(' ', '-')}" + category_node = nodes.inline( + "", category, + classes=["changelog-category", class_name] + ) + paragraph_node = nodes.paragraph("", "", category_node) + + # Parse the detailed content under the category + content_node = nodes.container() + self.state.nested_parse(self.content, 0, content_node) + paragraph_node += content_node + + return [paragraph_node] + + +def setup(app): + """Register extension with Sphinx.""" + app.add_directive("release", ReleaseDirective) + app.add_directive("change", ChangeDirective) diff --git a/doc/sphinx/_static/style.css b/doc/sphinx/_static/style.css new file mode 100644 index 0000000..8a990df --- /dev/null +++ b/doc/sphinx/_static/style.css @@ -0,0 +1,62 @@ +.changelog-release { + position: relative; +} + +.changelog-release > h1, h2, h3, h4, h5 { + margin-bottom: 5px; +} + +.changelog-release em.release-date { + color: #999; + position: absolute; + line-height: 2.5em; + top: 0; + right: 0; +} + +.changelog-release ul.changelog-change-list { + list-style: outside none none; +} + +.changelog-release ul.changelog-change-list > li { + list-style: outside none none; + position: relative; + margin: 0; + padding: 8px 0 2px 120px; + border-top: 1px solid #D6D6D6; +} + +.rst-content .section .changelog-change-list ul li { + list-style: initial; +} + +.changelog-category { + border-right: 3px solid #CCC; + box-shadow: 0px 1px 1px rgba(0, 0, 0, 0.05), 0px -1px 0px rgba(0, 0, 0, 0.05) inset; + color: #333; + display: inline-block; + font-size: 0.7em; + font-style: normal; + font-weight: bold; + line-height: 14px; + padding: 4px 2px 4px 10px; + text-shadow: 1px 1px 0px #FFF; + text-transform: uppercase; + width: 102px; + position: absolute; + top: 10px; + left: 0px; + background-color: #f8f8f8; +} + +.changelog-category-fixed { + border-color: #7C0; +} + +.changelog-category-new { + border-color: #11B0E9; +} + +.changelog-category-changed { + border-color: #EB3F3F; +} diff --git a/doc/sphinx/conf.py b/doc/sphinx/conf.py index 4723f2d..452d7bc 100644 --- a/doc/sphinx/conf.py +++ b/doc/sphinx/conf.py @@ -1,11 +1,14 @@ -# -*- coding: utf-8 -*- - """Configuration file for the Sphinx documentation builder.""" -import os import re +import pathlib +import os +import sys -extensions = ["sphinxcontrib.doxylink", "lowdown"] +root = pathlib.Path(__file__).parent.resolve() +sys.path.insert(0, str(root / "_extensions")) + +extensions = ["changelog", "sphinxcontrib.doxylink"] # This deployment mode exists so that documentation can be built within a # Github runner without requiring USD/TBB/Boost to be installed. We would be @@ -16,17 +19,20 @@ doxygen.create_cmake_config() build_path = doxygen.build() - source_path = os.path.join(os.path.dirname(__file__), "..", "..") + source_path = root.parent.parent.resolve() + + path = source_path / "CMakeLists.txt" + data = path.read_text() - with open(os.path.join(source_path, "CMakeLists.txt")) as stream: - pattern = r"project\(.* VERSION ([\d\\.]+)" - version = re.search(pattern, stream.read(), re.DOTALL).group(1) + pattern = r"project\(.* VERSION ([\d\\.]+)" + version = re.search(pattern, data, re.DOTALL).group(1) html_extra_path = ["./api"] else: - build_path = "@CMAKE_CURRENT_BINARY_DIR@/doc" - source_path = "@PROJECT_SOURCE_DIR@" + build_path = pathlib.Path("@CMAKE_CURRENT_BINARY_DIR@") / "doc" + source_path = pathlib.Path("@PROJECT_SOURCE_DIR@") + version = "@CMAKE_PROJECT_VERSION@" source_suffix = ".rst" @@ -38,15 +44,17 @@ doxylink = { "usd-cpp": ( - os.path.join(source_path, "doc", "doxygen", "USD.tag"), + str(source_path / "doc" / "doxygen" / "USD.tag"), "https://graphics.pixar.com/usd/release/api" ), "unf-cpp": ( - os.path.join(build_path, "UNF.tag"), + str(build_path / "UNF.tag"), "./doxygen" ) } html_theme = "sphinx_rtd_theme" html_favicon = "favicon.png" +html_static_path = ["_static"] +html_css_files = ["style.css"] diff --git a/doc/sphinx/doxygen.py b/doc/sphinx/doxygen.py index 4a974d8..f50d455 100644 --- a/doc/sphinx/doxygen.py +++ b/doc/sphinx/doxygen.py @@ -1,34 +1,31 @@ -# -*- coding: utf-8 -*- - -import os +import pathlib import re import subprocess import shutil -ROOT = os.path.normpath(os.path.abspath(os.path.curdir)) +ROOT = pathlib.Path().resolve() def build(): """Build API documentation.""" target = "unfApiRefDoc" - build_path = os.path.join(ROOT, "build") - subprocess.call(["cmake", "-S", ROOT, "-B", build_path]) - subprocess.call(["cmake", "--build", build_path, "--target", target]) + build_path = ROOT / "build" + output_path = ROOT / "api" - # Move doxygen API outside the build directory. - output_path = os.path.join(ROOT, "api") - os.makedirs(output_path) + # Run CMake commands + subprocess.call(["cmake", "-S", ROOT, "-B", str(build_path)]) + subprocess.call(["cmake", "--build", str(build_path), "--target", target]) - shutil.move( - os.path.join(build_path, "doxygen"), - os.path.join(output_path, "doxygen") - ) + # Remove output_path if it exists + if output_path.exists() and output_path.is_dir(): + shutil.rmtree(output_path) - shutil.move( - os.path.join(build_path, "UNF.tag"), - os.path.join(output_path, "UNF.tag") - ) + # Move doxygen API outside the build directory + output_path.mkdir() + + shutil.move(build_path / "doxygen", output_path / "doxygen") + shutil.move(build_path / "UNF.tag", output_path / "UNF.tag") return output_path @@ -40,10 +37,8 @@ def create_cmake_config(): fetch_api_doc_content() ]) - path = os.path.join(ROOT, "CMakeLists.txt") - - with open(path, "w") as stream: - stream.write(content) + path = ROOT / "CMakeLists.txt" + path.write_text(content) return path @@ -54,10 +49,8 @@ def fetch_project_content(): # so we hard-code it for now. content = "cmake_minimum_required(VERSION 3.15)\n\n" - path = os.path.join(ROOT, "..", "..", "CMakeLists.txt") - - with open(path, "r") as stream: - data = stream.read() + path = ROOT.parent.parent / "CMakeLists.txt" + data = path.read_text() patterns = [ r"project\(.*?\)", @@ -67,9 +60,9 @@ def fetch_project_content(): for pattern in patterns: match = re.search(pattern, data, re.MULTILINE | re.DOTALL) if not match: - raise ValueError("Pattern not found: {!r}".format(pattern)) + raise ValueError(f"Pattern not found: {pattern!r}") - content += "{}\n\n".format(match.group()) + content += f"{match.group()}\n\n" return content @@ -78,15 +71,12 @@ def fetch_api_doc_content(): """Fetch info from documentation cmake config.""" content = "" - path = os.path.join(ROOT, "..", "CMakeLists.txt") - - with open(path, "r") as stream: - data = stream.read() + path = ROOT.parent / "CMakeLists.txt" + data = path.read_text() - for option in re.findall( - r"set\(\s*DOXYGEN.*?\s*\)", data, re.MULTILINE | re.DOTALL - ): - content += "{}\n".format(option) + # Extract DOXYGEN-related settings + options = re.findall(r"set\(\s*DOXYGEN.*?\s*\)", data, re.MULTILINE | re.DOTALL) + content += "\n".join(options) + "\n" # Update path to tag file. content = re.sub("/doc/", "/../", content) @@ -116,5 +106,5 @@ def fetch_api_doc_content(): command = re.sub("/doc/", "/../", match.group()) command = re.sub("/src/", "/../../src/", command) - content += "\n{}".format(command) + content += f"\n{command}" return content diff --git a/doc/sphinx/glossary.rst b/doc/sphinx/glossary.rst index 72758c4..de7f2af 100644 --- a/doc/sphinx/glossary.rst +++ b/doc/sphinx/glossary.rst @@ -60,12 +60,6 @@ Glossary .. seealso:: https://docs.pytest.org/ - Pytest CMake - Python package providing a convenient way to provide :term:`CMake` configuration - for :term:`Pytest`. - - .. seealso:: https://pytest-cmake.readthedocs.io/en/stable/ - reStructuredText Lightweight markup language. diff --git a/doc/sphinx/installing.rst b/doc/sphinx/installing.rst index fd04912..189b4cf 100644 --- a/doc/sphinx/installing.rst +++ b/doc/sphinx/installing.rst @@ -104,9 +104,10 @@ Then run the program as follows:: Building documentation ====================== -Ensure that :term:`Doxygen` and :term:`Sphinx` with the `lowdown -`_ and `sphinxcontrib-doxylink -`_ extensions are installed. +Ensure that :term:`Doxygen` is installed. The required Python dependencies +must also be installed as follows:: + + pip install -r doc/requirements.txt Then build the documentation as follows:: @@ -122,13 +123,15 @@ Then build the documentation as follows:: Running tests ============= -Ensure that :term:`GTest`, :term:`Pytest` and :term:`Pytest CMake` are -installed. +Ensure that :term:`GTest` is installed. The required Python dependencies +must also be installed as follows:: + + pip install -r test/requirements.txt .. note:: - :term:`Pytest` and :term:`Pytest CMake` are not necessary is you set the - ``BUILD_PYTHON_BINDINGS`` :term:`CMake` option to false. + Python dependencies are not necessary if the ``BUILD_PYTHON_BINDINGS`` + :term:`CMake` option is set to false. Once the library and all tests are built, you can run the tests using :term:`Ctest` within the build folder as follows:: diff --git a/doc/sphinx/release/release_notes.rst b/doc/sphinx/release/release_notes.rst index 4c310b0..8dee668 100644 --- a/doc/sphinx/release/release_notes.rst +++ b/doc/sphinx/release/release_notes.rst @@ -4,6 +4,22 @@ Release Notes ************* +.. release:: Upcoming + + .. change:: changed + + Updated documentation building logic to discover the :term:`Sphinx` + configuration for :term:`CMake` from the `Sphinx CMake + `_ package for simplicity. + + .. change:: changed + + Updated logic to build the :ref:`release/release_notes` page. + + .. change:: changed + + Added compatibility with CMake 3.30. + .. release:: 0.6.4 :date: 2024-08-08 @@ -47,8 +63,8 @@ Release Notes .. change:: changed Updated Python testing logic to discover the :term:`Pytest` - configuration for :term:`CMake` from the :term:`Pytest CMake` package - for simplicity. + configuration for :term:`CMake` from the `Pytest CMake + `_ package for simplicity. .. release:: 0.5.6 :date: 2023-07-13 diff --git a/test/requirements.txt b/test/requirements.txt new file mode 100644 index 0000000..70774ab --- /dev/null +++ b/test/requirements.txt @@ -0,0 +1,2 @@ +pytest>=7 +pytest-cmake==0.*