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

git diff support #296

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ source =
omit =
# Don't worry about covering vendored libraries
src/sphobjinv/_vendored/*
setup.py

[report]
exclude_lines =
Expand Down
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
tests/resource/objects_mkdoc_zlib0.inv binary
tests/resource/objects_attrs.txt binary
*.inv binary diff=inv
117 changes: 117 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,123 @@ and this project follows an extension of
fourth number represents an administrative maintenance release with no code
changes.

### [2.4.1.11] - 2024-08-28

#### Administrative

* azure-pipelines coverage report omit setup.py
* README.md affected by version. Update version
* azure-pipelines need --testall to get 100% coverage

#### Tests

* test conftest fixture ensure_doc_scratch
* test WorkDir
* fix inventory path must surround by single quotes
* fix use git config to set textconv executable
* add to WorkDir git config list/get/set support
* in tests/test_api_good_nonlocal.py provide explicit reasons to skip test
* in test_api_inventory_many_url_imports, sequence of inventory file names to skip
* add resources objects_attrs_plus_one_entry.{txt|inv}
* compare existing resources. Rather modify then .txt --> .inv
* add fixtures res_cmp_plus_one_line is_linux gitconfig gitattributes
* on windows, print txt inventory to check line endings

### [2.4.1.10] - 2024-08-28
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@msftcangoblowm Unless it strongly benefits your development process, please don't bother with bumping versions and documenting microchanges in the CHANGELOG this way.

I'll be cutting the actual v2.4.0 release only after this PR is merged to main, and anything you've added to the CHANGELOG I'll coalesce and probably squash.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine.

These are actually development prereleases, not administrative prereleases. So these entries are wrong and spammy. The final changelog entries are left to your discretion

Also refrained from making any tags


#### Tests

* consistantly use sphobjinv.cli.load:import_infile so compare apple with apples

### [2.4.1.9] - 2024-08-28

#### Tests

* read inventory on disk
there is a object count discrepency. Track down reason
* print diagnostic before assertions

### [2.4.1.8] - 2024-08-28

#### Tests

* regression when to use resolved or unresolved executable path

### [2.4.1.7] - 2024-08-28

#### Tests

* resolve both soi and soi-textconv executables path

### [2.4.1.6] - 2024-08-28

#### Tests

* .git/config textconv executable resolve path
shutil.which to resolve path to executable

### [2.4.1.5] - 2024-08-28

#### Tests

* carefully escape regex metacharacters
* print source .inv file and diff. On windows, issue with regex
* remove fixture windows_paths

### [2.4.1.4] - 2024-08-28

#### Tests

* for subprocess calls use relative path not absolute path

### [2.4.1.3] - 2024-08-27

#### Tests

* wrong params for list.append instead use list.insert

### [2.4.1.2] - 2024-08-27

#### Tests

* for Windows, attempt add SCRIPTS folder to sys.path
* for Windows, walk SCRIPTS folder print files and folders

### [2.4.1.1] - 2024-08-27

#### Tests

* print entire os.environ rather than a single key

### [2.4.1] - 2024-08-27

#### Fixed

* py38 with statements multiple --> nested
* py38 standard types typing isms e.g. List
* use Windows friendly line seperators

#### Tests

* print diagnostic info on Windows bin and site folders

### [2.4.0] - 2024-08-26

#### Added

* Entrypoint sphobjinv-textconv ([#295])

#### Tests

* Unittests both offline and online
* Integration test to demonstrate git diff objects.inv
* add pytest module with class to interact with git

#### Documentation

* Added step by step guide to configure git. Both bash and python code examples
* Added sphobjinv-textconv API docs

### [2.3.1.1] - 2024-05-21

#### Tests
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,11 @@ inventory creation/modification:
>>> import sphobjinv as soi
>>> inv = soi.Inventory('doc/build/html/objects.inv')
>>> print(inv)
<Inventory (fname_zlib): sphobjinv v2.3, 220 objects>
<Inventory (fname_zlib): sphobjinv v2.4, 234 objects>
>>> inv.project
'sphobjinv'
>>> inv.version
'2.3'
'2.4'
>>> inv.objects[0]
DataObjStr(name='sphobjinv.cli.convert', domain='py', role='module', priority='0', uri='cli/implementation/convert.html#module-$', dispname='-')

Expand Down
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ stages:
- script: cd doc; make html; mkdir scratch
displayName: Build docset

- script: pytest --cov=. --nonloc --flake8_ext
- script: pytest --cov=. --nonloc --flake8_ext --testall
displayName: Run pytest with coverage on the entire project tree

- script: coverage report --include="tests/*" --fail-under=100
Expand Down
159 changes: 154 additions & 5 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@

"""


import logging
import os
import os.path as osp
import platform
import re
Expand Down Expand Up @@ -82,6 +83,51 @@ def res_dec(res_path, misc_info):
return res_path / (misc_info.FNames.RES.value + misc_info.Extensions.DEC.value)


@pytest.fixture(scope="session")
def res_cmp_plus_one_line(res_path, misc_info):
"""res_cmp with a line appended. Overwrites objects.inv file."""

def func(path_cwd):
"""Overwrite objects.inv file. New objects.inv contains one additional line.

Parameters
----------
path_cwd

|Path| -- test sessions current working directory

"""
logger = logging.getLogger()

# src
str_postfix = "_plus_one_entry"
fname = (
f"{misc_info.FNames.RES.value}{str_postfix}{misc_info.Extensions.CMP.value}"
)
path_f_src = res_path / fname
reason = f"source file not found src {path_f_src}"
assert path_f_src.is_file() and path_f_src.exists(), reason

# dst
fname_dst = f"{misc_info.FNames.INIT.value}{misc_info.Extensions.CMP.value}"
path_f_dst = path_cwd / fname_dst
reason = f"dest file not found src {path_f_src} dest {path_f_dst}"
assert path_f_dst.is_file() and path_f_dst.exists(), reason

# file sizes differ
objects_inv_size_existing = path_f_dst.stat().st_size
objects_inv_size_new = path_f_src.stat().st_size
reason = f"file sizes do not differ src {path_f_src} dest {path_f_dst}"
assert objects_inv_size_new != objects_inv_size_existing, reason

msg_info = f"copy {path_f_src} --> {path_f_dst}"
logger.info(msg_info)

shutil.copy2(str(path_f_src), str(path_f_dst))

return func


@pytest.fixture(scope="session")
def misc_info(res_path):
"""Supply Info object with various test-relevant content."""
Expand Down Expand Up @@ -152,7 +198,7 @@ def scratch_path(tmp_path, res_path, misc_info, is_win, unix2dos):
# With the conversion of resources/objects_attrs.txt to Unix EOLs in order to
# provide for a Unix-testable sdist, on Windows systems this resource needs
# to be converted to DOS EOLs for consistency.
if is_win:
if is_win: # pragma: no cover
win_path = tmp_path / f"{scr_base}{misc_info.Extensions.DEC.value}"
win_path.write_bytes(unix2dos(win_path.read_bytes()))

Expand Down Expand Up @@ -212,7 +258,7 @@ def func(path):
"""Perform the 'live' inventory load test."""
try:
sphinx_ifile_load(path)
except Exception as e: # noqa: PIE786
except Exception as e: # noqa: PIE786 # pragma: no cover
# An exception here is a failing test, not a test error.
pytest.fail(e)

Expand Down Expand Up @@ -252,7 +298,7 @@ def func(arglist, *, expect=0): # , suffix=None):
except SystemExit as e:
retcode = e.args[0]
ok = True
else:
else: # pragma: no cover
ok = False

# Do all pytesty stuff outside monkeypatch context
Expand All @@ -264,6 +310,68 @@ def func(arglist, *, expect=0): # , suffix=None):
return func


@pytest.fixture() # Must be function scope since uses monkeypatch
def run_cmdline_textconv(monkeypatch):
"""Return function to perform command line exit code test."""
from sphobjinv.cli.core_textconv import main

def func(arglist, *, expect=0): # , suffix=None):
"""Perform the CLI exit-code test."""

# Assemble execution arguments
runargs = ["sphobjinv-textconv"]
runargs.extend(str(a) for a in arglist)

# Mock sys.argv, run main, and restore sys.argv
with monkeypatch.context() as m:
m.setattr(sys, "argv", runargs)

try:
main()
except SystemExit as e:
retcode = e.args[0]
ok = True
else: # pragma: no cover
ok = False

# Do all pytesty stuff outside monkeypatch context
assert ok, "SystemExit not raised on termination."

# Test that execution completed w/indicated exit code
assert retcode == expect, runargs

return func


@pytest.fixture() # Must be function scope since uses monkeypatch
def run_cmdline_no_checks(monkeypatch):
"""Return function to perform command line. So as to debug issues no tests."""
from sphobjinv.cli.core_textconv import main

def func(arglist, *, prog="sphobjinv-textconv"):
"""Perform the CLI exit-code test."""

# Assemble execution arguments
runargs = [prog]
runargs.extend(str(a) for a in arglist)

# Mock sys.argv, run main, and restore sys.argv
with monkeypatch.context() as m:
m.setattr(sys, "argv", runargs)

try:
main()
except SystemExit as e:
retcode = e.args[0]
is_system_exit = True
else: # pragma: no cover
is_system_exit = False

return retcode, is_system_exit

return func


@pytest.fixture(scope="session")
def decomp_cmp_test(misc_info, is_win, unix2dos):
"""Return function to confirm a decompressed file is identical to resource."""
Expand All @@ -274,7 +382,7 @@ def func(path):
res_bytes = Path(misc_info.res_decomp_path).read_bytes()
tgt_bytes = Path(path).read_bytes() # .replace(b"\r\n", b"\n")

if is_win:
if is_win: # pragma: no cover
# Have to explicitly convert these newlines, now that the
# tests/resource/objects_attrs.txt file is marked 'binary' in
# .gitattributes
Expand Down Expand Up @@ -324,6 +432,12 @@ def is_win():
return platform.system().lower() == "windows"


@pytest.fixture(scope="session")
def is_linux():
"""Report boolean of whether the current system is Linux."""
return platform.system() in ("Linux",)


@pytest.fixture(scope="session")
def unix2dos():
"""Provide function for converting POSIX to Windows EOLs."""
Expand All @@ -334,3 +448,38 @@ def unix2dos():
def jsonschema_validator():
"""Provide the standard JSON schema validator."""
return jsonschema.Draft4Validator


@pytest.fixture(scope="session")
def gitattributes():
"""Projects .gitattributes resource."""

def func(path_cwd):
"""Copy over projects .gitattributes to test current sessions folder.

Parameters
----------
path_cwd

|Path| -- test sessions current working directory

"""
path_dir = Path(__file__).parent
path_f_src = path_dir.joinpath(".gitattributes")
path_f_dst = path_cwd / path_f_src.name
path_f_dst.touch()
assert path_f_dst.is_file()
if not path_f_src.exists(): # pragma: no cover
# workflow "Run test suite in sandbox" fails to find .gitattributes
sep = os.linesep
contents = (
f"tests/resource/objects_mkdoc_zlib0.inv binary{sep}"
f"tests/resource/objects_attrs.txt binary{sep}"
f"*.inv binary diff=inv{sep}"
)
path_f_dst.write_text(contents)
else:
shutil.copy2(path_f_src, path_f_dst)
return path_f_dst

return func
Loading