Skip to content
Merged

Dev #32

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
8 changes: 1 addition & 7 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,6 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.{bat,cmd,ps1}]
end_of_line = crlf

[*.{html,css,js}]
insert_final_newline = false

[*.py]
max_line_length = 100

Expand All @@ -23,4 +17,4 @@ indent_style = tab
insert_final_newline = false

[*.yml]
indent_style = tab
indent_size = 2
3 changes: 3 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ jobs:
fail-fast: false
matrix:
python-version: ["3.11", "3.10", "3.9"]
env:
PYTHONUNBUFFERED: 1
PYTHONWARNINGS: always
steps:
- uses: actions/checkout@v2
with:
Expand Down
15 changes: 14 additions & 1 deletion manageprojects/cli/cli_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,8 +389,21 @@ def test():
"""
Run unittests
"""
args = sys.argv[2:]
if not args:
args = ('--verbose', '--locals', '--buffer')
# Use the CLI from unittest module and pass all args to it:
verbose_check_call(sys.executable, '-m', 'unittest', *sys.argv[2:])
verbose_check_call(
sys.executable,
'-m',
'unittest',
*args,
timeout=15 * 60,
extra_env=dict(
PYTHONUNBUFFERED='1',
PYTHONWARNINGS='always',
),
)


def main():
Expand Down
2 changes: 1 addition & 1 deletion manageprojects/cookiecutter_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def update_managed_project(
print('Seems that the patch was not applied correctly!')
print('Hint: run wiggle on the project:')
print()
print(f'./mp wiggle {project_path}')
print(f'./cli.py wiggle {project_path}')
print()

#############################################################################
Expand Down
42 changes: 42 additions & 0 deletions manageprojects/test_utils/logs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import logging
from pathlib import Path
from unittest import TestCase


class AssertLogs:
"""
Capture and assert log output from different loggers.
"""

def __init__(
self,
test_case: TestCase,
loggers: tuple[str] = ('manageprojects', 'cookiecutter'),
level=logging.DEBUG,
):
assertLogs = test_case.assertLogs

self.logs = []
for logger in loggers:
self.logs.append(assertLogs(logger, level=level))

self.context_managers = None

def __enter__(self):
self.context_managers = [log.__enter__() for log in self.logs]
return self

def __exit__(self, exc_type, exc_val, exc_tb):
for log in self.logs:
log.__exit__(exc_type, exc_val, exc_tb)

def assert_in(self, *test_parts):
outputs = []
for cm in self.context_managers:
outputs.extend(cm.output)

output = '\n'.join(outputs)
for part in test_parts:
if isinstance(part, Path):
part = str(part)
assert part in output, f'Log part {part!r} not found in:\n{output}'
6 changes: 5 additions & 1 deletion manageprojects/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
from manageprojects.utilities.log_utils import log_config


log_config(log_in_file=False)
log_config(
format='%(levelname)s %(name)s.%(funcName)s %(lineno)d | %(message)s',
log_in_file=False,
raise_log_output=True,
)
27 changes: 17 additions & 10 deletions manageprojects/tests/test_cookiecutter_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from bx_py_utils.path import assert_is_dir

from manageprojects.cookiecutter_api import get_repo_path
from manageprojects.test_utils.logs import AssertLogs
from manageprojects.tests.base import BaseTestCase


Expand All @@ -13,11 +14,14 @@ def test_get_repo_path(self):
cookiecutter_template = f'https://github.com/jedie/{repro_name}/'
directory = 'test_template1'

repo_path = get_repo_path(
template=cookiecutter_template,
directory=directory,
checkout='84d23bf', # Old version
)
with AssertLogs(self) as logs:
repo_path = get_repo_path(
template=cookiecutter_template,
directory=directory,
checkout='84d23bf', # Old version
)
logs.assert_in('repo_dir', repo_path)

self.assertIsInstance(repo_path, Path)
self.assertEqual(repo_path.name, directory)
assert_is_dir(repo_path.parent / '.git')
Expand All @@ -34,11 +38,14 @@ def test_get_repo_path(self):
),
)

repo_path = get_repo_path(
template=cookiecutter_template,
directory=directory,
checkout=None, # Current main branch
)
with AssertLogs(self) as logs:
repo_path = get_repo_path(
template=cookiecutter_template,
directory=directory,
checkout=None, # Current main branch
)
logs.assert_in('repo_dir', repo_path)

self.assertIsInstance(repo_path, Path)
self.assertEqual(repo_path.name, directory)
assert_is_dir(repo_path.parent / '.git')
Expand Down
88 changes: 56 additions & 32 deletions manageprojects/tests/test_cookiecutter_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
ManageProjectsMeta,
)
from manageprojects.test_utils.git_utils import init_git
from manageprojects.test_utils.logs import AssertLogs
from manageprojects.tests.base import BaseTestCase
from manageprojects.utilities.pyproject_toml import PyProjectToml
from manageprojects.utilities.temp_path import TemporaryDirectory
Expand Down Expand Up @@ -44,17 +45,20 @@ def test_start_managed_project(self):
assert cookiecutter_output_dir.exists() is False
assert cookiecutters_dir.exists() is False

result: CookiecutterResult = start_managed_project(
template=cookiecutter_template,
output_dir=cookiecutter_output_dir,
no_input=True,
directory=directory,
config_file=config_file_path,
extra_context={
'dir_name': 'a_dir_name',
'file_name': 'a_file_name',
},
)
with AssertLogs(self) as logs:
result: CookiecutterResult = start_managed_project(
template=cookiecutter_template,
output_dir=cookiecutter_output_dir,
no_input=True,
directory=directory,
config_file=config_file_path,
extra_context={
'dir_name': 'a_dir_name',
'file_name': 'a_file_name',
},
)
logs.assert_in('Cookiecutter generated here', cookiecutter_output_dir)

self.assertIsInstance(result, CookiecutterResult)
git_path = cookiecutters_dir / repro_name
self.assertEqual(result.git_path, git_path)
Expand All @@ -80,8 +84,10 @@ def test_start_managed_project(self):
project_path = cookiecutter_output_dir / 'a_dir_name'

# pyproject.toml created?
toml = PyProjectToml(project_path=project_path)
result: ManageProjectsMeta = toml.get_mp_meta()
with AssertLogs(self, loggers=('manageprojects',)) as logs:
toml = PyProjectToml(project_path=project_path)
result: ManageProjectsMeta = toml.get_mp_meta()
logs.assert_in('Read existing pyproject.toml')
self.assertIsInstance(result, ManageProjectsMeta)
self.assertEqual(
result,
Expand All @@ -105,8 +111,14 @@ def test_start_managed_project(self):
# Test clone a existing project

cloned_path = main_temp_path / 'cloned_project'
clone_result: CookiecutterResult = clone_project(
project_path=project_path, destination=cloned_path, no_input=True
with AssertLogs(self) as logs:
clone_result: CookiecutterResult = clone_project(
project_path=project_path, destination=cloned_path, no_input=True
)
logs.assert_in(
'Read existing pyproject.toml',
"Call 'cookiecutter'",
'Create new pyproject.toml',
)
self.assertEqual(
clone_result.cookiecutter_context,
Expand All @@ -123,8 +135,10 @@ def test_start_managed_project(self):
self.assertEqual(clone_result.destination_path, end_path)

# pyproject.toml created?
toml = PyProjectToml(project_path=end_path)
result: ManageProjectsMeta = toml.get_mp_meta()
with AssertLogs(self, loggers=('manageprojects',)) as logs:
toml = PyProjectToml(project_path=end_path)
result: ManageProjectsMeta = toml.get_mp_meta()
logs.assert_in('Read existing pyproject.toml')
self.assertIsInstance(result, ManageProjectsMeta)
self.assertEqual(
result,
Expand Down Expand Up @@ -204,13 +218,15 @@ def test_update_project(self):
git, from_rev = init_git(template_path, comment='Git init template.')
from_date = git.get_commit_date(verbose=False)

toml = PyProjectToml(project_path=project_path)
toml.init(
revision=from_rev,
dt=from_date,
template=str(template_path),
directory=template_dir_name,
)
with AssertLogs(self, loggers=('manageprojects',)) as logs:
toml = PyProjectToml(project_path=project_path)
toml.init(
revision=from_rev,
dt=from_date,
template=str(template_path),
directory=template_dir_name,
)
logs.assert_in('Create new pyproject.toml')
toml.create_or_update_cookiecutter_context(context=context)
toml.save()
toml_content = toml.path.read_text()
Expand Down Expand Up @@ -249,12 +265,18 @@ def test_update_project(self):
)
self.assertFalse(patch_file_path.exists())

result = update_managed_project(
project_path=project_path,
password=None,
config_file=config_file_path,
cleanup=False, # Keep temp files if this test fails, for better debugging
no_input=True, # No user input in tests ;)
with AssertLogs(self) as logs:
result = update_managed_project(
project_path=project_path,
password=None,
config_file=config_file_path,
cleanup=False, # Keep temp files if this test fails, for better debugging
no_input=True, # No user input in tests ;)
)
logs.assert_in(
'No temp files cleanup',
'Cookiecutter generated',
'Read existing pyproject.toml',
)

self.assert_file_content(
Expand Down Expand Up @@ -294,7 +316,9 @@ def test_update_project(self):
)

# Check updated toml file:
toml = PyProjectToml(project_path=project_path)
mp_meta: ManageProjectsMeta = toml.get_mp_meta()
with AssertLogs(self, loggers=('manageprojects',)) as logs:
toml = PyProjectToml(project_path=project_path)
mp_meta: ManageProjectsMeta = toml.get_mp_meta()
logs.assert_in('Read existing pyproject.toml')
self.assertEqual(mp_meta.initial_revision, from_rev)
self.assertEqual(mp_meta.applied_migrations, [to_rev])
35 changes: 20 additions & 15 deletions manageprojects/tests/test_patching.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from manageprojects.data_classes import GenerateTemplatePatchResult
from manageprojects.patching import generate_template_patch, make_git_diff
from manageprojects.test_utils.git_utils import init_git
from manageprojects.test_utils.logs import AssertLogs
from manageprojects.tests.base import BaseTestCase
from manageprojects.utilities.temp_path import TemporaryDirectory

Expand All @@ -33,12 +34,14 @@ def test_make_git_diff(self):
Path(from_path, 'old_name.txt').write_text(renamed_file_content)
Path(to_path, 'new_name.txt').write_text(renamed_file_content)

patch = make_git_diff(
temp_path=main_temp_path,
from_path=from_path,
to_path=to_path,
verbose=True,
)
with AssertLogs(self, loggers=('manageprojects',)) as logs:
patch = make_git_diff(
temp_path=main_temp_path,
from_path=from_path,
to_path=to_path,
verbose=True,
)
logs.assert_in('old_name.txt', 'new_name.txt')
self.assertIn('diff --git a/file1.txt b/file1.txt', patch)
self.assertIn('-Rev 1', patch)
self.assertIn('+Rev 2', patch)
Expand Down Expand Up @@ -104,15 +107,17 @@ def test_generate_template_patch(self):
)
self.assertFalse(patch_file_path.exists())

result = generate_template_patch(
project_path=project_path,
template=str(repo_path),
directory=None,
from_rev=from_rev,
replay_context={},
cleanup=False, # Keep temp files if this test fails, for better debugging
no_input=True, # No user input in tests ;)
)
with AssertLogs(self) as logs:
result = generate_template_patch(
project_path=project_path,
template=str(repo_path),
directory=None,
from_rev=from_rev,
replay_context={},
cleanup=False, # Keep temp files if this test fails, for better debugging
no_input=True, # No user input in tests ;)
)
logs.assert_in("Call 'cookiecutter'", 'Write patch file')
self.assertIsInstance(result, GenerateTemplatePatchResult)

self.assertEqual(result.patch_file_path, patch_file_path)
Expand Down
Loading