From 7b6e5ce843e721599e8c571a323c076eb84cbedb Mon Sep 17 00:00:00 2001 From: Daniel Stoops Date: Thu, 2 May 2024 14:11:49 +0300 Subject: [PATCH 1/8] Update readme --- README.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c74ead0..08fd9b0 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,28 @@ # refers *

reference code simply

* ![Tests](https://github.com/Stoops-ML/refers/actions/workflows/test.yml/badge.svg) +[![PyPI version](https://badge.fury.io/py/refers.svg)](https://badge.fury.io/py/refers) The refers library allows referencing plain text files from plain text files. Usage: -1. Add a `@tag` to the line that you want to reference: `@tag:TAG_NAME` -2. To reference the tag use `@ref` followed by an *optional* option: `@ref:TAG_NAME:OPTION` +1. Add a `@tag` to the line that you want to reference: `@tag:NAME` +2. To reference the tag use `@ref` followed by an *optional* option: `@ref:NAME:OPTION` 3. run the refers library in the command line The refers library will create new files with the outputted references in place of the tags. Changes of line placement, file name, relative path etc. are reflected in the updated references when the refers library is executed. -## Reference options +## Installation -| `ref` option | result | +`pip install refers` + +## Reference Options + +A reference has the following structure: `@ref:NAME:OPTION`. This will reference the named tag with the specified option. The available options are outlined in the table below. + +| Option | Output | |---------------|--------------------------------------| | *blank* | file name and line number | | :file | file name | From 263c7083a33f2822f98326fda178d0d96ae8a28c Mon Sep 17 00:00:00 2001 From: Daniel Stoops Date: Thu, 2 May 2024 15:14:31 +0300 Subject: [PATCH 2/8] FIX: test_replace_tags_tag_not_found() --- .pre-commit-config.yaml | 2 +- examples/example1/readme.md | 2 +- examples/example1/readme_refers.md | 2 +- tests/test_refers.py | 6 ++---- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 77a6d69..49c8a87 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -64,7 +64,7 @@ repos: always_run: true stages: [push] - id: update examples - name: refers + name: update examples entry: refers -r examples/example1 language: system pass_filenames: false diff --git a/examples/example1/readme.md b/examples/example1/readme.md index 080b390..2f5ef09 100644 --- a/examples/example1/readme.md +++ b/examples/example1/readme.md @@ -1,7 +1,7 @@ # Example 1 This document demonstrates the `refers` library in action. -Run `refers -r example1` in command prompt to output the file [readme_refers.md](readme_refers.md), which will convert the references using the requested tags. +Run `refers -r example1` in command prompt to output the file [readme_refers.md](readme_refers.md), which will convert the referenced tag using the option. ## Demonstration The file [@ref:dist_eq:file](@ref:dist_eq:link) is a script that simulates linear motion. diff --git a/examples/example1/readme_refers.md b/examples/example1/readme_refers.md index d5fcfb8..d648ce5 100644 --- a/examples/example1/readme_refers.md +++ b/examples/example1/readme_refers.md @@ -1,7 +1,7 @@ # Example 1 This document demonstrates the `refers` library in action. -Run `refers -r example1` in command prompt to output the file [readme_refers.md](readme_refers.md), which will convert the references using the requested tags. +Run `refers -r example1` in command prompt to output the file [readme_refers.md](readme_refers.md), which will convert the referenced tag using the option. ## Demonstration The file [suvat.py](src/suvat.py) is a script that simulates linear motion. diff --git a/tests/test_refers.py b/tests/test_refers.py index 5d59446..0349236 100644 --- a/tests/test_refers.py +++ b/tests/test_refers.py @@ -2,6 +2,7 @@ from pathlib import Path import pytest + from refers.definitions import COMMENT_SYMBOL from refers.errors import MultipleTagsInOneLine from refers.errors import OptionNotFoundError @@ -729,10 +730,7 @@ def test_replace_tags_tag_not_found(create_tmp_file): False, [".md"], ) - assert ( - re.search(r"^Tag c and keyword not found\.", str(exc_info.value)) - is not None - ) + assert "Tag c not found" == str(exc_info.value) @pytest.mark.parametrize( From 47a0ad8dbec8b33e0eddac9322f13f0f680e0578 Mon Sep 17 00:00:00 2001 From: Daniel Stoops Date: Thu, 2 May 2024 15:15:36 +0300 Subject: [PATCH 3/8] FIX: test_replace_tags_option_not_found() --- tests/test_refers.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/test_refers.py b/tests/test_refers.py index 0349236..ec6245a 100644 --- a/tests/test_refers.py +++ b/tests/test_refers.py @@ -1,4 +1,3 @@ -import re from pathlib import Path import pytest @@ -751,8 +750,7 @@ def test_replace_tags_tag_not_found(create_tmp_file): """# Test file On line [@ref:a:line1](@ref:a:linkline) the code has @ref:a:quotecode. This is it's link: @ref:a:link. `b` appears in @ref:b, is located @ref:b:fulllink and has contents: @ref:b:quote. -`d` appears in file @ref:d:file, which has a relative path one parent up of and a relative path three parents up of . The full link with line is @ref:d:fulllinkline -There is no tag for 'c': @ref:c""", +`d` appears in file @ref:d:file, which has a relative path one parent up of and a relative path three parents up of . The full link with line is @ref:d:fulllinkline""", ), ) ], @@ -767,10 +765,10 @@ def test_replace_tags_option_not_found(create_tmp_file): False, [".md"], ) - assert ( - re.search(r"^Tag c and keyword not found\.", str(exc_info.value)) - is not None - ) + assert ( + "Option :line1 of tag a not found. Possible options: ['class', 'default', 'file', 'full_line', 'fulllink', 'fulllinkline', 'func', 'line', 'line_num', 'line_num_end', 'line_num_start', 'link', 'linkline', 'name', 'quote', 'quotecode', 'unknown_tag']" + == str(exc_info.value) + ) @pytest.mark.parametrize( From 146daa081e4c6605aa4d09f5f4d4a39a8e6af983 Mon Sep 17 00:00:00 2001 From: Daniel Stoops Date: Thu, 2 May 2024 15:16:25 +0300 Subject: [PATCH 4/8] format_doc() checks if dirs2search and rootdir exists --- refers/refers.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/refers/refers.py b/refers/refers.py index d827399..77cae01 100644 --- a/refers/refers.py +++ b/refers/refers.py @@ -354,6 +354,16 @@ def format_doc( else: tag_files = None + # checks + if not rootdir.exists(): + raise ValueError(f"The root directory does not exist: {rootdir}.") + if dirs2search is not None: + for d in dirs2search: + if not d.exists(): + raise ValueError( + f"The following directory which was requested to be searched does not exist: {d}." + ) + # get tags tags = get_tags( rootdir, accepted_tag_extensions, dirs2search, dirs2ignore, tag_files From 105cd6cf2a03bf3f6308a0c66c968d2173b42172 Mon Sep 17 00:00:00 2001 From: Daniel Stoops Date: Thu, 2 May 2024 15:35:54 +0300 Subject: [PATCH 5/8] FIX: rootdir of pyproject can be in relation to pyproject or not --- refers/refers.py | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/refers/refers.py b/refers/refers.py index 77cae01..a19d7e0 100644 --- a/refers/refers.py +++ b/refers/refers.py @@ -2,9 +2,7 @@ from pathlib import Path from typing import List from typing import Optional -from typing import ( - TypeVar, -) +from typing import TypeVar from typing import Union import black @@ -240,50 +238,43 @@ def format_doc( pyproject_path = rootdir / "pyproject.toml" if pyproject_path.is_file(): pyproject = toml.load(str(pyproject_path)) - if LIBRARY_NAME not in pyproject["tool"].keys(): - if "refers_path" in pyproject["tool"][LIBRARY_NAME].keys(): - rootdir = Path(pyproject["tool"][LIBRARY_NAME]["refers_path"]) - if "allow_not_found_tags" in pyproject["tool"][LIBRARY_NAME].keys(): + if LIBRARY_NAME in pyproject["tool"].keys(): + inputs_to_change = pyproject["tool"][LIBRARY_NAME].keys() + if "refers_path" in inputs_to_change: + rootdir_tmp = Path(pyproject["tool"][LIBRARY_NAME]["refers_path"]) + if rootdir_tmp.exists(): + rootdir = rootdir_tmp + else: # refers_path is defined in relation to pyproject_path + rootdir = rootdir / rootdir_tmp + if "allow_not_found_tags" in inputs_to_change: allow_not_found_tags = pyproject["tool"][LIBRARY_NAME][ "allow_not_found_tags" ] - if ( - "dirs2ignore" in pyproject["tool"][LIBRARY_NAME].keys() - and dirs2ignore is None - ): + if "dirs2ignore" in inputs_to_change and dirs2ignore is None: dirs2ignore = [ Path(f) for f in pyproject["tool"][LIBRARY_NAME]["dirs2ignore"] ] - if ( - "dirs2search" in pyproject["tool"][LIBRARY_NAME].keys() - and dirs2search is None - ): + if "dirs2search" in inputs_to_change and dirs2search is None: dirs2search = [ Path(f) for f in pyproject["tool"][LIBRARY_NAME]["dirs2search"] ] - if ( - "ref_files" in pyproject["tool"][LIBRARY_NAME].keys() - and ref_files is None - ): + if "ref_files" in inputs_to_change and ref_files is None: ref_files = [ Path(f) for f in pyproject["tool"][LIBRARY_NAME]["ref_files"] ] - if ( - "tag_files" in pyproject["tool"][LIBRARY_NAME].keys() - and tag_files is None - ): + if "tag_files" in inputs_to_change and tag_files is None: tag_files = [ Path(f) for f in pyproject["tool"][LIBRARY_NAME]["tag_files"] ] if ( - "accepted_tag_extensions" in pyproject["tool"][LIBRARY_NAME].keys() + "accepted_tag_extensions" in inputs_to_change and accepted_tag_extensions is None ): accepted_tag_extensions = pyproject["tool"][LIBRARY_NAME][ - "accepted_mime_tag_types" + "accepted_tag_extensions" ] if ( - "accepted_ref_extensions" in pyproject["tool"][LIBRARY_NAME].keys() + "accepted_ref_extensions" in inputs_to_change and accepted_ref_extensions is None ): accepted_ref_extensions = pyproject["tool"][LIBRARY_NAME][ From f96da19012c18a6ddb5c03c8a048ef8f1778d313 Mon Sep 17 00:00:00 2001 From: Daniel Stoops Date: Thu, 2 May 2024 15:40:07 +0300 Subject: [PATCH 6/8] Add test_format_doc_pyproject_rootdir_noexist() --- tests/conftest.py | 16 +++++++ tests/test_refers.py | 104 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index 19db5bb..c4679cd 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -25,6 +25,22 @@ def create_tmp_file(request, tmp_path): refers_file.unlink() +@pytest.fixture +def create_files(request, tmp_path): + """ + :param request: Tuple containing files to create + :return: + """ + + tmp_folder = tmp_path / "test" + tmp_folder.mkdir(exist_ok=True) + for fname, flines in request.param: + tmp_file = tmp_folder / fname + with open(tmp_file, "w") as f: + f.write(flines) + yield tmp_folder + + @pytest.fixture def check_refers_test_files(request, tmp_path): """ diff --git a/tests/test_refers.py b/tests/test_refers.py index ec6245a..2fe5dcc 100644 --- a/tests/test_refers.py +++ b/tests/test_refers.py @@ -1,3 +1,4 @@ +import re from pathlib import Path import pytest @@ -316,6 +317,109 @@ def test_format_doc_full_path(check_refers_test_files: Path): format_doc(check_refers_test_files) +@pytest.mark.parametrize( + "create_files", + [ + ( + ( + "file_with_refs.md", + """# Test file +Function `f` has a comment: @ref:f_a:link and and @ref:f_a +Function `f` has a comment: @ref:f_a:line in the [file](@ref:f_a:link) and and @ref:f_a and @ref:f_a:quotecode +""", + ), + ( + "file_with_tags.py", + """def f(): + a = 1 # @tag:f_a this is a comment + return a +def f1(): + a = 1 # @tag:a this is a comment + return a +def f2(): + b = 1 # @tag:b this is a comment + return a +def f3(): + a = 1 # @tag:d this is a comment + return a +""", + ), + ( + "file_no_refs.py", + "# This is a test file with no refs", + ), + ), + ], + indirect=True, +) +def test_format_doc_pyproject_rootdir_noexist(create_files: Path): + refers_path = "DIR_NO_EXIST" + assert not Path(refers_path).exists() + with open(create_files / "pyproject.toml", "w") as f: + f.write( + f"""[tool.refers] +refers_path = "{refers_path}" +accepted_tag_extensions = [".py"] +accepted_ref_extensions = [".md"]""" + ) + with pytest.raises(ValueError) as exc_info: + format_doc(create_files) + assert ( + re.search( + rf"^The root directory does not exist: .+{refers_path}\.", + str(exc_info.value), + ) + is not None + ) + + +@pytest.mark.parametrize( + "check_refers_test_files", + [ + ( + ( + "file_with_refs.md", + """# Test file +Function `f` has a comment: @ref:f_a:link and and @ref:f_a +Function `f` has a comment: @ref:f_a:line in the [file](@ref:f_a:link) and and @ref:f_a and @ref:f_a:quotecode +""", + ), + ( + "file_with_tags.py", + """def f(): + a = 1 # @tag:f_a this is a comment + return a +def f1(): + a = 1 # @tag:a this is a comment + return a +def f2(): + b = 1 # @tag:b this is a comment + return a +def f3(): + a = 1 # @tag:d this is a comment + return a +""", + ), + ( + "file_no_refs.py", + "# This is a test file with no refs", + ), + ), + ], + indirect=True, +) +def test_format_doc_pyproject(check_refers_test_files: Path): + refers_path = str(check_refers_test_files).replace("\\", "/") + with open(check_refers_test_files / "pyproject.toml", "w") as f: + f.write( + f"""[tool.refers] +refers_path = "{refers_path}" +accepted_tag_extensions = [".py"] +accepted_ref_extensions = [".md"]""" + ) + format_doc(check_refers_test_files) + + @pytest.mark.parametrize( "create_tmp_file", [ From 0af078c41944c19b190f196dbb5cfd5bb251afb1 Mon Sep 17 00:00:00 2001 From: Daniel Stoops Date: Thu, 2 May 2024 15:40:57 +0300 Subject: [PATCH 7/8] Increase required coverage to 81% --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 23c9ef3..715fa6a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,7 +51,7 @@ no_implicit_reexport = true testpaths = "tests" addopts = [ "--cov=refers", - "--cov-fail-under=75", + "--cov-fail-under=81", "--cov-report=term-missing", "--cov-report=term", "--cov-report=" From 692079e3d1a6a18880e4779e2299059a3b535b61 Mon Sep 17 00:00:00 2001 From: Daniel Stoops Date: Thu, 2 May 2024 15:41:55 +0300 Subject: [PATCH 8/8] Update to 0.0.4 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 715fa6a..9cbbcb5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "refers" -version = "0.0.3" +version = "0.0.4" description = "Reference code to improve explainability" authors = ["Daniel Stoops "] readme = "README.md"