diff --git a/.gitattributes b/.gitattributes index d6e0c6a82..f1cf0f50e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,7 +4,7 @@ CHANGELOG.md merge=union *.xlsx binary *.min.js binary *.min.css binary -doorstop/core/files/templates/html/output/*.js binary +doorstop/core/files/templates/html/output/**/*.js binary doorstop/core/files/templates/html/tex-mml-chtml.js binary doorstop/core/tests/files/published*.html binary diff --git a/Makefile b/Makefile index e09db7e4e..e1f84f122 100644 --- a/Makefile +++ b/Makefile @@ -81,7 +81,7 @@ endif RANDOM_SEED ?= $(shell date +%s) -PYTEST_OPTIONS := --doctest-modules +PYTEST_OPTIONS := --doctest-modules -n auto ifndef DISABLE_COVERAGE PYTEST_OPTIONS += --cov=$(PACKAGE) --cov-report=html --cov-report=term-missing endif diff --git a/doorstop/cli/commands.py b/doorstop/cli/commands.py index 1df175318..59f49790f 100644 --- a/doorstop/cli/commands.py +++ b/doorstop/cli/commands.py @@ -611,6 +611,7 @@ def _get_tree(args, cwd, request_next_number=None, load=False): """ utilities.show("building tree...", flush=True) + log.debug(f"Building tree at {cwd}, project root {args.project}, request_next_number={request_next_number}") tree = build(cwd=cwd, root=args.project, request_next_number=request_next_number) if load: diff --git a/doorstop/cli/main.py b/doorstop/cli/main.py index 5b92b7c1a..6f3f321f7 100644 --- a/doorstop/cli/main.py +++ b/doorstop/cli/main.py @@ -166,6 +166,7 @@ def main(args=None): # pylint: disable=R0915 args = parser.parse_args(args=args) # Configure logging + print(f"verbose: {args.verbose}") utilities.configure_logging(args.verbose) # Configure settings diff --git a/doorstop/cli/tests/test_all.py b/doorstop/cli/tests/test_all.py index 62f265712..ec9b0aac8 100644 --- a/doorstop/cli/tests/test_all.py +++ b/doorstop/cli/tests/test_all.py @@ -6,6 +6,7 @@ import shutil import tempfile import unittest +from shutil import copytree from unittest.mock import Mock, patch from doorstop import common, settings @@ -45,6 +46,7 @@ class MockTestCase(TempTestCase): def setUp(self): super().setUp() + copytree(os.path.join("reqs"), os.path.join(self.temp, "reqs")) os.chdir(self.temp) common.touch(".mockvcs") _clear_tree() @@ -133,7 +135,7 @@ def get_next_number(): @unittest.skipUnless(os.getenv(ENV), REASON) @patch("doorstop.settings.SERVER_HOST", None) @patch("doorstop.settings.ADDREMOVE_FILES", False) -class TestAdd(unittest.TestCase): +class TestAdd(MockTestCase): """Integration tests for the 'doorstop add' command.""" @classmethod @@ -183,7 +185,7 @@ def test_add_error(self): @unittest.skipUnless(os.getenv(ENV), REASON) @patch("doorstop.settings.ADDREMOVE_FILES", False) -class TestAddServer(unittest.TestCase): +class TestAddServer(MockTestCase): """Integration tests for the 'doorstop add' command using a server.""" @classmethod @@ -221,7 +223,7 @@ def test_add_force(self): @unittest.skipUnless(os.getenv(ENV), REASON) @patch("doorstop.settings.ADDREMOVE_FILES", False) -class TestRemove(unittest.TestCase): +class TestRemove(MockTestCase): """Integration tests for the 'doorstop remove' command.""" ITEM = os.path.join(TUTORIAL, "TUT003.yml") @@ -244,7 +246,7 @@ def test_remove_error(self): @unittest.skipUnless(os.getenv(ENV), REASON) @patch("doorstop.settings.ADDREMOVE_FILES", False) -class TestReorder(unittest.TestCase): +class TestReorder(MockTestCase): """Integration tests for the 'doorstop reorder' command.""" @classmethod @@ -322,7 +324,7 @@ def test_reorder_with_backslashes_in_text(self): @unittest.skipUnless(os.getenv(ENV), REASON) @patch("doorstop.settings.SERVER_HOST", None) @patch("doorstop.settings.ADDREMOVE_FILES", False) -class TestEdit(unittest.TestCase): +class TestEdit(MockTestCase): """Integration tests for the 'doorstop edit' command.""" @patch("subprocess.call", Mock()) @@ -376,7 +378,7 @@ def test_edit_error(self): @unittest.skipUnless(os.getenv(ENV), REASON) @patch("doorstop.settings.ADDREMOVE_FILES", False) -class TestLink(unittest.TestCase): +class TestLink(MockTestCase): """Integration tests for the 'doorstop link' command.""" ITEM = os.path.join(TUTORIAL, "TUT003.yml") @@ -404,7 +406,7 @@ def test_link_unknown_parent(self): @unittest.skipUnless(os.getenv(ENV), REASON) @patch("doorstop.settings.ADDREMOVE_FILES", False) -class TestUnlink(unittest.TestCase): +class TestUnlink(MockTestCase): """Integration tests for the 'doorstop unlink' command.""" ITEM = os.path.join(TUTORIAL, "TUT003.yml") @@ -433,7 +435,7 @@ def test_unlink_unknown_parent(self): @unittest.skipUnless(os.getenv(ENV), REASON) -class TestClear(unittest.TestCase): +class TestClear(MockTestCase): """Integration tests for the 'doorstop clear' command.""" @patch("doorstop.core.item.Item.clear") @@ -482,7 +484,7 @@ def test_clear_error(self): @unittest.skipUnless(os.getenv(ENV), REASON) -class TestReview(unittest.TestCase): +class TestReview(MockTestCase): """Integration tests for the 'doorstop review' command.""" @patch("doorstop.core.item.Item.review") @@ -527,7 +529,7 @@ def test_review_error(self): @unittest.skipUnless(os.getenv(ENV), REASON) @patch("doorstop.settings.SERVER_HOST", None) @patch("doorstop.settings.ADDREMOVE_FILES", False) -class TestImport(unittest.TestCase): +class TestImport(MockTestCase): """Integration tests for the 'doorstop import' command.""" def tearDown(self): @@ -646,7 +648,7 @@ def test_import_xlsx_to_document_existing(self): @unittest.skipUnless(os.getenv(ENV), REASON) @patch("doorstop.settings.ADDREMOVE_FILES", False) -class TestImportServer(unittest.TestCase): +class TestImportServer(MockTestCase): """Integration tests for the 'doorstop import' command using a server.""" def tearDown(self): diff --git a/doorstop/core/document.py b/doorstop/core/document.py index 356842ab2..31a0c5cc6 100644 --- a/doorstop/core/document.py +++ b/doorstop/core/document.py @@ -134,12 +134,13 @@ def new( :return: new :class:`~doorstop.core.document.Document` """ + log.debug(f"Adding document: prefix={prefix}, digits={digits}, seperator={sep}, auto={auto}, root={root}, tree={tree}, path={path}") # Check separator if sep and sep not in settings.SEP_CHARS: raise DoorstopError("invalid UID separator '{}'".format(sep)) config = os.path.join(path, Document.CONFIG) - + log.debug(f"Checking for document {config}") # Check for an existing document if os.path.exists(config): raise DoorstopError("document already exists: {}".format(path)) diff --git a/doorstop/core/publishers/tests/test_publisher_html.py b/doorstop/core/publishers/tests/test_publisher_html.py index 9f83c5923..f361ddee4 100644 --- a/doorstop/core/publishers/tests/test_publisher_html.py +++ b/doorstop/core/publishers/tests/test_publisher_html.py @@ -52,8 +52,10 @@ def test_publish_document(self, mock_open, mock_makedirs): path2 = publisher.publish(self.document, path) # Assert self.assertIs(path, path2) - mock_makedirs.assert_called_once_with(self.dirpath) - mock_open.assert_called_once_with(path, "wb") + mock_makedirs.assert_called_with(os.sep.join([self.dirpath, "documents"])) + mock_open.assert_called_once_with( + os.sep.join([os.path.dirname(path), "documents", "published.html"]), "wb" + ) @patch("os.path.isdir", Mock(return_value=False)) @patch("os.makedirs") diff --git a/doorstop/core/tree.py b/doorstop/core/tree.py index 06b95be97..72b328005 100644 --- a/doorstop/core/tree.py +++ b/doorstop/core/tree.py @@ -138,6 +138,7 @@ def _place(self, document): """ log.debug("trying to add {}...".format(document)) + print(f"_place: {self.document}") if not self.document: # tree is empty if document.parent: msg = "unknown parent for {}: {}".format(document, document.parent) diff --git a/poetry.lock b/poetry.lock index 9688c3dbc..014616cab 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "altgraph" @@ -30,35 +30,6 @@ wrapt = [ {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}, ] -[[package]] -name = "atomicwrites" -version = "1.4.1" -description = "Atomic file writes." -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" -files = [ - {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"}, -] - -[[package]] -name = "attrs" -version = "23.2.0" -description = "Classes Without Boilerplate" -optional = false -python-versions = ">=3.7" -files = [ - {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, - {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, -] - -[package.extras] -cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[tests]", "pre-commit"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] -tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] -tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] - [[package]] name = "beautifulsoup4" version = "4.12.3" @@ -128,13 +99,13 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "bottle" -version = "0.12.25" +version = "0.13.1" description = "Fast and simple WSGI-framework for small web-applications." optional = false python-versions = "*" files = [ - {file = "bottle-0.12.25-py3-none-any.whl", hash = "sha256:d6f15f9d422670b7c073d63bd8d287b135388da187a0f3e3c19293626ce034ea"}, - {file = "bottle-0.12.25.tar.gz", hash = "sha256:e1a9c94970ae6d710b3fb4526294dfeb86f2cb4a81eff3a4b98dc40fb0e5e021"}, + {file = "bottle-0.13.1-py2.py3-none-any.whl", hash = "sha256:d5e068ad0b4ed3422231ad59bd9ea646a141f57a9c90587212d63477ec04fe96"}, + {file = "bottle-0.13.1.tar.gz", hash = "sha256:a48852dc7a051353d3e4de3dd5590cd25de370bcfd94a72237561e314ceb0c88"}, ] [[package]] @@ -424,6 +395,34 @@ files = [ {file = "et_xmlfile-1.1.0.tar.gz", hash = "sha256:8eb9e2bc2f8c97e37a2dc85a09ecdcdec9d8a396530a6d5a33b30b9a92da0c5c"}, ] +[[package]] +name = "exceptiongroup" +version = "1.2.2" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "execnet" +version = "2.1.1" +description = "execnet: rapid multi-Python deployment" +optional = false +python-versions = ">=3.8" +files = [ + {file = "execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc"}, + {file = "execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3"}, +] + +[package.extras] +testing = ["hatch", "pre-commit", "pytest", "tox"] + [[package]] name = "ghp-import" version = "2.1.0" @@ -806,13 +805,13 @@ files = [ [[package]] name = "openpyxl" -version = "3.1.2" +version = "3.1.5" description = "A Python library to read/write Excel 2010 xlsx/xlsm files" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "openpyxl-3.1.2-py2.py3-none-any.whl", hash = "sha256:f91456ead12ab3c6c2e9491cf33ba6d08357d802192379bb482f1033ade496f5"}, - {file = "openpyxl-3.1.2.tar.gz", hash = "sha256:a6f5977418eff3b2d5500d54d9db50c8277a368436f4e4f8ddb1be3422870184"}, + {file = "openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2"}, + {file = "openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050"}, ] [package.dependencies] @@ -884,30 +883,19 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4.3)", "pytest- [[package]] name = "pluggy" -version = "1.4.0" +version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" files = [ - {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, - {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, ] [package.extras] dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" -files = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, -] - [[package]] name = "pydocstyle" version = "6.3.0" @@ -1028,37 +1016,35 @@ python-dateutil = ">=2.0" [[package]] name = "pytest" -version = "6.2.5" +version = "8.3.3" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"}, - {file = "pytest-6.2.5.tar.gz", hash = "sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89"}, + {file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"}, + {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"}, ] [package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} -attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=0.12,<2.0" -py = ">=1.8.2" -toml = "*" +pluggy = ">=1.5,<2" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-cov" -version = "4.1.0" +version = "5.0.0" description = "Pytest plugin for measuring coverage." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, - {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, + {file = "pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"}, + {file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"}, ] [package.dependencies] @@ -1066,7 +1052,7 @@ coverage = {version = ">=5.2.1", extras = ["toml"]} pytest = ">=4.6" [package.extras] -testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] [[package]] name = "pytest-expecter" @@ -1098,6 +1084,26 @@ termcolor = ">=2.1.0" [package.extras] dev = ["black", "flake8", "pre-commit"] +[[package]] +name = "pytest-xdist" +version = "3.6.1" +description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest_xdist-3.6.1-py3-none-any.whl", hash = "sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7"}, + {file = "pytest_xdist-3.6.1.tar.gz", hash = "sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d"}, +] + +[package.dependencies] +execnet = ">=2.1" +pytest = ">=7.0.0" + +[package.extras] +psutil = ["psutil (>=3.0)"] +setproctitle = ["setproctitle"] +testing = ["filelock"] + [[package]] name = "python-dateutil" version = "2.8.2" @@ -1191,6 +1197,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -1357,17 +1364,6 @@ files = [ [package.extras] tests = ["pytest", "pytest-cov"] -[[package]] -name = "toml" -version = "0.10.2" -description = "Python Library for Tom's Obvious, Minimal Language" -optional = false -python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" -files = [ - {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, - {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"}, -] - [[package]] name = "tomli" version = "2.0.1" @@ -1523,13 +1519,13 @@ watchmedo = ["PyYAML (>=3.10)"] [[package]] name = "webob" -version = "1.8.7" +version = "1.8.8" description = "WSGI request and response object" optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ - {file = "WebOb-1.8.7-py2.py3-none-any.whl", hash = "sha256:73aae30359291c14fa3b956f8b5ca31960e420c28c1bec002547fb04928cf89b"}, - {file = "WebOb-1.8.7.tar.gz", hash = "sha256:b64ef5141be559cfade448f044fa45c2260351edcb6a8ef6b7e00c7dcef0c323"}, + {file = "WebOb-1.8.8-py2.py3-none-any.whl", hash = "sha256:b60ba63f05c0cf61e086a10c3781a41fcfe30027753a8ae6d819c77592ce83ea"}, + {file = "webob-1.8.8.tar.gz", hash = "sha256:2abc1555e118fc251e705fc6dc66c7f5353bb9fbfab6d20e22f1c02b4b71bcee"}, ] [package.extras] @@ -1653,4 +1649,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "6e106c06f163ef5b218caa5993a62cd99f6ed58a6c902e2a8ebf6c4f4683be58" +content-hash = "2ca9f45c3337d0d6af45b4521a254f6f758dc671aaa065b0203deb4d39073905" diff --git a/pyproject.toml b/pyproject.toml index a424edfb5..fe2fb8cae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,13 +47,16 @@ python = "^3.9" pyyaml = "^6.0" markdown = "^3.3.3" -bottle = "~0.12.25" +bottle = "^0.13.1" requests = "^2.0" python-frontmatter = "^1.0" python-markdown-math = "~0.6" plantuml-markdown = "^3.4.2" six = "*" # fixes https://github.com/dougn/python-plantuml/issues/11 -openpyxl = ">=3.1.2" +openpyxl = "^3.1.5" +pytest-xdist = "^3.6.1" +pytest = "^8.3.3" +pytest-cov = "^5.0.0" [tool.poetry.dev-dependencies] @@ -71,7 +74,6 @@ types-requests = "*" types-setuptools = "*" # Testing -pytest = "^6.2.5" pytest-cov = "*" pytest-expecter = "*" pytest-sugar = "*"