Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump to 0.0.4 #8

Merged
merged 8 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
# refers
*<p style="text-align: center;">reference code simply</p>*
![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 |
Expand Down
2 changes: 1 addition & 1 deletion examples/example1/readme.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
2 changes: 1 addition & 1 deletion examples/example1/readme_refers.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -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 <[email protected]>"]
readme = "README.md"
Expand Down Expand Up @@ -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="
Expand Down
53 changes: 27 additions & 26 deletions refers/refers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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][
Expand Down Expand Up @@ -354,6 +345,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
Expand Down
16 changes: 16 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
"""
Expand Down
120 changes: 110 additions & 10 deletions tests/test_refers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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",
[
Expand Down Expand Up @@ -729,10 +833,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(
Expand All @@ -753,8 +854,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""",
),
)
],
Expand All @@ -769,10 +869,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(
Expand Down
Loading