diff --git a/manageprojects/cli/cli_app.py b/manageprojects/cli/cli_app.py index 5ad5884..94a027b 100644 --- a/manageprojects/cli/cli_app.py +++ b/manageprojects/cli/cli_app.py @@ -243,6 +243,16 @@ def start_project( @click.command() @click.argument('project_path', **ARGUMENT_EXISTING_DIR) +@click.option( + '--overwrite/--no-overwrite', + **OPTION_ARGS_DEFAULT_FALSE, + help=( + 'Overwrite all Cookiecutter template files to the last template state and' + ' do not apply the changes via git patches.' + ' The developer is supposed to apply the differences manually via git.' + ' Will be aborted if the project git repro is not in a clean state.' + ), +) @click.option( '--password', default=None, @@ -257,7 +267,7 @@ def start_project( @click.option( '--input/--no-input', **OPTION_ARGS_DEFAULT_FALSE, - help=('Cookiecutter Option: Do not prompt for parameters' ' and only use cookiecutter.json file content'), + help='Cookiecutter Option: Do not prompt for parameters and only use cookiecutter.json file content', ) @click.option( '--cleanup/--no-cleanup', @@ -266,6 +276,7 @@ def start_project( ) def update_project( project_path: Path, + overwrite: bool, password: Optional[str], config_file: Optional[Path], input: bool, @@ -280,6 +291,7 @@ def update_project( print(f'Update project: "{project_path}"...') update_managed_project( project_path=project_path, + overwrite=overwrite, password=password, config_file=config_file, cleanup=cleanup, diff --git a/manageprojects/cookiecutter_templates.py b/manageprojects/cookiecutter_templates.py index 9860ef7..b78a8d0 100644 --- a/manageprojects/cookiecutter_templates.py +++ b/manageprojects/cookiecutter_templates.py @@ -12,8 +12,10 @@ CookiecutterResult, GenerateTemplatePatchResult, ManageProjectsMeta, + OverwriteResult, ) from manageprojects.git import Git +from manageprojects.overwrite import overwrite_project from manageprojects.patching import generate_template_patch from manageprojects.utilities.pyproject_toml import PyProjectToml @@ -83,6 +85,7 @@ def start_managed_project( def update_managed_project( project_path: Path, + overwrite: bool = False, # Don't apply git patches -> Just overwrite all template files! password: Optional[str] = None, config_file: Optional[Path] = None, # CookieCutter config file cleanup: bool = True, # Remove temp files if not exceptions happens @@ -108,46 +111,64 @@ def update_managed_project( cookiecutter_template = meta.cookiecutter_template assert cookiecutter_template, f'Missing template in {toml.path}' - ############################################################################# - # Generate the git diff/patch - - result = generate_template_patch( - project_path=project_path, - template=cookiecutter_template, - directory=meta.cookiecutter_directory, - from_rev=from_rev, - replay_context=cookiecutter_context, - password=password, - config_file=config_file, - cleanup=cleanup, - no_input=not input, - ) - if not result: - logger.info('No git patch was created, nothing to apply.') - return None - assert isinstance(result, GenerateTemplatePatchResult) - - ############################################################################# - # Apply the patch - - patch_file_path = result.patch_file_path - try: - git.apply(patch_path=patch_file_path) - except subprocess.CalledProcessError as err: - print(err.stdout) - if err.returncode == 1: - print() - print('Seems that the patch was not applied correctly!') - print('Hint: run wiggle on the project:') - print() - print(f'./cli.py wiggle {project_path}') - print() + if overwrite: + # Don't apply git patches -> Just overwrite all template files: + result = overwrite_project( + git=git, + project_path=project_path, + template=cookiecutter_template, + replay_context=cookiecutter_context, + directory=meta.cookiecutter_directory, + from_rev=from_rev, + password=password, + config_file=config_file, + cleanup=cleanup, + no_input=not input, + ) + if not result: + logger.info('Project is up-to-date, no changed to applied.') + return None + assert isinstance(result, OverwriteResult) + else: + # Generate the git diff/patch + + result = generate_template_patch( + project_path=project_path, + template=cookiecutter_template, + directory=meta.cookiecutter_directory, + from_rev=from_rev, + replay_context=cookiecutter_context, + password=password, + config_file=config_file, + cleanup=cleanup, + no_input=not input, + ) + if not result: + logger.info('No git patch was created, nothing to apply.') + return None + assert isinstance(result, GenerateTemplatePatchResult) + + ############################################################################# + # Apply the patch + + patch_file_path = result.patch_file_path + try: + git.apply(patch_path=patch_file_path) + except subprocess.CalledProcessError as err: + print(err.stdout) + if err.returncode == 1: + print() + print('Seems that the patch was not applied correctly!') + print('Hint: run wiggle on the project:') + print() + print(f'./cli.py wiggle {project_path}') + print() ############################################################################# # Update "pyproject.toml" with applied patch information # Important: We *must* read the current "pyproject.toml" here again! - # Otherwise we may overwrite template changed with old content! + # Otherwise, we may overwrite template changed with old content! toml = PyProjectToml(project_path=project_path) toml.add_applied_migrations(git_hash=result.to_rev, dt=result.to_commit_date) toml.save() diff --git a/manageprojects/data_classes.py b/manageprojects/data_classes.py index 6e03cad..013eed2 100644 --- a/manageprojects/data_classes.py +++ b/manageprojects/data_classes.py @@ -45,13 +45,22 @@ def get_last_git_hash(self) -> str: @dataclasses.dataclass -class GenerateTemplatePatchResult: +class ResultBase: + to_rev: str + to_commit_date: datetime.datetime + + +@dataclasses.dataclass +class GenerateTemplatePatchResult(ResultBase): repo_path: Path # Cookiecutter template path patch_file_path: Path from_rev: str compiled_from_path: Path - to_rev: str - to_commit_date: datetime.datetime compiled_to_path: Path + + +@dataclasses.dataclass +class OverwriteResult(ResultBase): + pass diff --git a/manageprojects/git.py b/manageprojects/git.py index e47bcaa..628f30e 100644 --- a/manageprojects/git.py +++ b/manageprojects/git.py @@ -241,3 +241,15 @@ def reset(self, *, commit, hard=True, verbose=True) -> None: assert output.startswith( test_str ), f'Reset error: {output!r} does not start with {test_str!r}' + + def status(self, verbose=True) -> list: + """ + Returns the changed files, if any. + """ + output = self.git_verbose_check_output('status', '--porcelain', verbose=verbose, exit_on_error=True) + result = [] + for line in output.splitlines(): + line = line.strip() + status, filepath = line.split(' ', 1) + result.append((status, filepath)) + return result diff --git a/manageprojects/overwrite.py b/manageprojects/overwrite.py new file mode 100644 index 0000000..a3adf4b --- /dev/null +++ b/manageprojects/overwrite.py @@ -0,0 +1,88 @@ +import filecmp +import logging +import shutil +import sys +from pathlib import Path +from typing import Optional + +from bx_py_utils.path import assert_is_dir +from rich import print + +from manageprojects.cookiecutter_api import execute_cookiecutter +from manageprojects.data_classes import OverwriteResult +from manageprojects.git import Git +from manageprojects.utilities.temp_path import TemporaryDirectory + + +logger = logging.getLogger(__name__) + + +def overwrite_project( + *, + git: Git, + project_path: Path, + template: str, # CookieCutter Template path or GitHub url + from_rev: str, + replay_context: dict, + directory: Optional[str] = None, # Directory name of the CookieCutter Template + password: Optional[str] = None, + config_file: Optional[Path] = None, # Optional path to 'cookiecutter_config.yaml' + cleanup: bool = True, # Remove temp files if not exceptions happens + no_input: bool = False, # Prompt the user at command line for manual configuration? +) -> OverwriteResult: + print(f'Update by overwrite project: {project_path} from {template}') + + status = git.status() + if status: + print(f'Abort: project {project_path} is not clean:', file=sys.stderr) + for flag, filepath in status: + print(flag, filepath) + sys.exit(1) + + extra_context = replay_context.get('cookiecutter') + if not extra_context: + print('WARNING: No "cookiecutter" in replay context!') + + project_name = project_path.name + with TemporaryDirectory(prefix=f'manageprojects_{project_name}_', cleanup=cleanup) as temp_path: + print(f'Compile cookiecutter template in the current version here: {temp_path}') + print('Use extra context:') + print(extra_context) + to_rev_context, to_rev_dst_path, to_rev_repo_path = execute_cookiecutter( + template=template, + directory=directory, + output_dir=temp_path, + no_input=no_input, + extra_context=extra_context, + checkout=None, # Checkout HEAD/main revision + password=password, + config_file=config_file, + ) + assert_is_dir(to_rev_repo_path) + + git = Git(cwd=to_rev_repo_path, detect_root=True) + to_rev = git.get_current_hash(verbose=False) + to_commit_date = git.get_commit_date(verbose=False) + print(f'Update from rev. {from_rev} to rev. {to_rev} ({to_commit_date})') + + updated_file_count = 0 + for src_file_path in to_rev_dst_path.rglob('*'): + if not src_file_path.is_file(): + continue + + dst_file_path = project_path / src_file_path.relative_to(to_rev_dst_path) + if dst_file_path.exists(): + print(f'NEW file: {dst_file_path}') + elif filecmp.cmp(dst_file_path, src_file_path, shallow=False): + print(f'Skip unchanged file: {dst_file_path}, ok.') + continue + else: + print(f'UPDATE file: {dst_file_path}') + + shutil.copyfile(src_file_path, dst_file_path) + updated_file_count += 1 + + logger.info('%i files updated by overwriting', updated_file_count) + + if updated_file_count > 0: + return OverwriteResult(to_rev=to_rev, to_commit_date=to_commit_date) diff --git a/manageprojects/tests/test_cli.py b/manageprojects/tests/test_cli.py index 6a4c029..e23cb04 100644 --- a/manageprojects/tests/test_cli.py +++ b/manageprojects/tests/test_cli.py @@ -100,6 +100,7 @@ def test_update_project_cli(self): m.assert_called_once_with( project_path=Path(tempdir), + overwrite=False, password=None, config_file=None, cleanup=True, diff --git a/manageprojects/tests/test_cli_update_project_help_1.snapshot.txt b/manageprojects/tests/test_cli_update_project_help_1.snapshot.txt index 0e29c2c..62129ea 100644 --- a/manageprojects/tests/test_cli_update_project_help_1.snapshot.txt +++ b/manageprojects/tests/test_cli_update_project_help_1.snapshot.txt @@ -5,13 +5,20 @@ ./cli.py update-project ~/foo/bar/ ╭─ Options ────────────────────────────────────────────────────────────────────────────────────────╮ -│ --password TEXT Cookiecutter Option: Password to use when extracting the │ -│ repository │ -│ --config-file FILE Cookiecutter Option: Optional path to "cookiecutter_config.yaml" │ -│ --input/--no-input Cookiecutter Option: Do not prompt for parameters and only use │ -│ cookiecutter.json file content │ -│ [default: no-input] │ -│ --cleanup/--no-cleanup Cleanup created temporary files [default: cleanup] │ -│ --help Show this message and exit. │ +│ --overwrite/--no-overwrite Overwrite all Cookiecutter template files to the last │ +│ template state and do not apply the changes via git patches. │ +│ The developer is supposed to apply the differences manually │ +│ via git. Will be aborted if the project git repro is not in │ +│ a clean state. │ +│ [default: no-overwrite] │ +│ --password TEXT Cookiecutter Option: Password to use when extracting the │ +│ repository │ +│ --config-file FILE Cookiecutter Option: Optional path to │ +│ "cookiecutter_config.yaml" │ +│ --input/--no-input Cookiecutter Option: Do not prompt for parameters and only │ +│ use cookiecutter.json file content │ +│ [default: no-input] │ +│ --cleanup/--no-cleanup Cleanup created temporary files [default: cleanup] │ +│ --help Show this message and exit. │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ diff --git a/manageprojects/tests/test_git.py b/manageprojects/tests/test_git.py index a3473a6..44e2584 100644 --- a/manageprojects/tests/test_git.py +++ b/manageprojects/tests/test_git.py @@ -208,3 +208,22 @@ def test_git_apply_patch(self): ''' ), ) + + def test_status(self): + with TemporaryDirectory(prefix='test_status_') as temp_path: + change_txt_path = Path(temp_path, 'change.txt') + change_txt_path.write_text('This is the first revision!') + + git, first_hash = init_git(temp_path) + + change_txt_path.write_text('Changed content') + Path(temp_path, 'added.txt').write_text('Added file') + + status = git.status(verbose=False) + self.assertEqual(status, [('M', 'change.txt'), ('??', 'added.txt')]) + + git.add('.', verbose=False) + git.commit('The second commit', verbose=False) + + status = git.status(verbose=False) + self.assertEqual(status, []) diff --git a/manageprojects/tests/test_overwrite.py b/manageprojects/tests/test_overwrite.py new file mode 100644 index 0000000..ffabbd4 --- /dev/null +++ b/manageprojects/tests/test_overwrite.py @@ -0,0 +1,182 @@ +import inspect +import json +from pathlib import Path + +from bx_py_utils.test_utils.redirect import RedirectOut + +from manageprojects.cookiecutter_templates import update_managed_project +from manageprojects.data_classes import ManageProjectsMeta, OverwriteResult +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 + + +class UpdateByOverwriteTestCase(BaseTestCase): + def test_happy_path(self): + cookiecutter_context = { + 'dir_name': 'a_directory', + 'file_name': 'a_file_name', + 'value': 'FooBar', + } + context = {'cookiecutter': cookiecutter_context} + + with TemporaryDirectory(prefix='test_update_by_overwrite_') as main_temp_path: + project_path = main_temp_path / 'project_path' + dst_file_path = project_path / 'a_file_name.py' + + template_path = main_temp_path / 'template' + template_dir_name = 'template_dir' + template_dir_path = template_path / template_dir_name + config_file_path = template_dir_path / 'cookiecutter.json' + + test_file_path = template_dir_path / '{{cookiecutter.dir_name}}' / '{{cookiecutter.file_name}}.py' + + dst_file_path.parent.mkdir(parents=True) + dst_file_path.write_text('# This is a test line, not changed') + + config_file_path.parent.mkdir(parents=True) + config_file_path.write_text(json.dumps(cookiecutter_context)) + + project_git, project_from_rev = init_git(project_path, comment='Git init project.') + dst_file_path.write_text( + inspect.cleandoc( + ''' + # This is a test line, not changed + # + # Revision 1 + # + # The same cookiecutter value: + print('Test: FooBar') + ''' + ) + ) + project_git.add('.') + project_git.commit('Store revision 1') + + test_file_path.parent.mkdir(parents=True) + test_file_path.write_text( + inspect.cleandoc( + ''' + # This is a test line, not changed + # + # Revision 1 + # + # The same cookiecutter value: + print('Test: {{ cookiecutter.value }}') + ''' + ) + ) + + git, from_rev = init_git(template_path, comment='Git init template.') + from_date = git.get_commit_date(verbose=False) + + 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() + self.assertIn('# Created by manageprojects', toml_content) + self.assertIn('[manageprojects] # https://github.com/jedie/manageprojects', toml_content) + self.assertIn(f'initial_revision = "{from_rev}"', toml_content) + self.assertIn(f'cookiecutter_template = "{template_path}"', toml_content) + self.assertIn('cookiecutter_directory = "template_dir"', toml_content) + + test_file_path.write_text( + inspect.cleandoc( + ''' + # This is a test line, not changed + # + # Revision 2 + # + # The same cookiecutter value: + print('Test: {{ cookiecutter.value }}') + ''' + ) + ) + git.add('.', verbose=False) + git.commit('Template rev 2', verbose=False) + to_rev = git.get_current_hash(verbose=False) + to_date = git.get_commit_date(verbose=False) + assert to_date + + patch_file_path = Path( + main_temp_path, + 'repo_path', + '.manageprojects', + 'patches', + f'{from_rev}_{to_rev}.patch', + ) + self.assertFalse(patch_file_path.exists()) + + # Don't overwrite if destination project git is not clean: + with RedirectOut() as buffer: + with self.assertRaises(SystemExit), AssertLogs(self): + update_managed_project( + project_path=project_path, + overwrite=True, # Update by overwrite + password=None, + config_file=config_file_path, + cleanup=False, # Keep temp files if this test fails, for better debugging + input=False, # No user input in tests ;) + ) + self.assertIn('Abort', buffer.stderr) + self.assertIn('is not clean', buffer.stderr) + self.assertIn('?? pyproject.toml', buffer.stdout) + + # Make project git "clean": + project_git.add('.', verbose=False) + project_git.commit('add pyproject.toml', verbose=False) + + with RedirectOut() as buffer: + with AssertLogs(self) as logs: + result = update_managed_project( + project_path=project_path, + overwrite=True, # Update by overwrite + password=None, + config_file=config_file_path, + cleanup=False, # Keep temp files if this test fails, for better debugging + input=False, # No user input in tests ;) + ) + self.assertEqual(buffer.stderr, '') + self.assertIn('Update by overwrite', buffer.stdout) + self.assertIn('NEW file', buffer.stdout) + + self.assert_file_content( + dst_file_path, + inspect.cleandoc( + ''' + # This is a test line, not changed + # + # Revision 2 + # + # The same cookiecutter value: + print('Test: FooBar') + ''' + ), + ) + + self.assertIsInstance(result, OverwriteResult) + self.assertEqual( + result, + OverwriteResult( + to_rev=to_rev, + to_commit_date=to_date, + ), + ) + + # Check updated toml file: + 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]) diff --git a/pyproject.toml b/pyproject.toml index dbaf4d1..a8cea4f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "manageprojects" -version = "0.6.0" +version = "0.7.0" description = "Manage Python / Django projects" readme = "README.md" authors = [ diff --git a/requirements.dev.txt b/requirements.dev.txt index 197210e..bb6ebfc 100644 --- a/requirements.dev.txt +++ b/requirements.dev.txt @@ -26,9 +26,9 @@ black==23.1a1 \ --hash=sha256:ddbf9da228726d46f45c29024263e160d41030a415097254817d65127012d1a2 \ --hash=sha256:e88e4b633d64b9e7adc4a6b922f52bb204af9f90d7b1e3317e6490f2b598b1ea # via darker -bleach==5.0.1 \ - --hash=sha256:085f7f33c15bd408dd9b17a4ad77c577db66d76203e5984b1bd59baeee948b2a \ - --hash=sha256:0d03255c47eb9bd2f26aa9bb7f2107732e7e8fe195ca2f64709fcf3b0a4a085c +bleach==6.0.0 \ + --hash=sha256:1a1a85c1595e07d8db14c5f09f09e6433502c51c595970edc090551f0db99414 \ + --hash=sha256:33c16e3353dbd13028ab4799a0f89a83f113405c766e9c122df8a06f5b85b3f4 # via readme-renderer build==0.10.0 \ --hash=sha256:af266720050a66c893a6096a2f410989eeac74ff9a68ba194b3f6473e8e26171 \ @@ -38,9 +38,9 @@ bx-py-utils==74 \ --hash=sha256:39a354727facc1a970102cbd2f786f7be6977dcf299c7d27aa5a46f580341043 \ --hash=sha256:9656a8e4c9aef4c876e39ac3decc0796709412dff5a549385acf1bd834e40e88 # via manageprojects (pyproject.toml) -cachetools==5.2.1 \ - --hash=sha256:5991bc0e08a1319bb618d3195ca5b6bc76646a49c21d55962977197b301cc1fe \ - --hash=sha256:8462eebf3a6c15d25430a8c27c56ac61340b2ecf60c9ce57afc2b97e450e47da +cachetools==5.3.0 \ + --hash=sha256:13dfddc7b8df938c21a940dfa6557ce6e94a2f1cdfa58eb90c805721d58f2c14 \ + --hash=sha256:429e1a1e845c008ea6c85aa35d4b98b65d6a9763eeef3e37e92728a12d1de9d4 # via tox certifi==2022.12.7 \ --hash=sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3 \ @@ -222,10 +222,6 @@ colorama==0.4.6 \ --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 # via tox -commonmark==0.9.1 \ - --hash=sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60 \ - --hash=sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9 - # via rich cookiecutter==2.1.1 \ --hash=sha256:9f3ab027cec4f70916e28f03470bdb41e637a3ad354b4d65c765d93aad160022 \ --hash=sha256:f3982be8d9c53dac1261864013fdec7f83afd2e42ede6f6dd069c5e149c540d5 @@ -384,52 +380,70 @@ keyring==23.13.1 \ --hash=sha256:771ed2a91909389ed6148631de678f82ddc73737d85a927f382a8a1b157898cd \ --hash=sha256:ba2e15a9b35e21908d0aaf4e0a47acc52d6ae33444df0da2b49d41a46ef6d678 # via twine -markupsafe==2.1.1 \ - --hash=sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003 \ - --hash=sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88 \ - --hash=sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5 \ - --hash=sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7 \ - --hash=sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a \ - --hash=sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603 \ - --hash=sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1 \ - --hash=sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135 \ - --hash=sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247 \ - --hash=sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6 \ - --hash=sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601 \ - --hash=sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77 \ - --hash=sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02 \ - --hash=sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e \ - --hash=sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63 \ - --hash=sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f \ - --hash=sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980 \ - --hash=sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b \ - --hash=sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812 \ - --hash=sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff \ - --hash=sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96 \ - --hash=sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1 \ - --hash=sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925 \ - --hash=sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a \ - --hash=sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6 \ - --hash=sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e \ - --hash=sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f \ - --hash=sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4 \ - --hash=sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f \ - --hash=sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3 \ - --hash=sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c \ - --hash=sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a \ - --hash=sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417 \ - --hash=sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a \ - --hash=sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a \ - --hash=sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37 \ - --hash=sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452 \ - --hash=sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933 \ - --hash=sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a \ - --hash=sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7 +markdown-it-py==2.1.0 \ + --hash=sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27 \ + --hash=sha256:cf7e59fed14b5ae17c0006eff14a2d9a00ed5f3a846148153899a0224e2c07da + # via rich +markupsafe==2.1.2 \ + --hash=sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed \ + --hash=sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc \ + --hash=sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2 \ + --hash=sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460 \ + --hash=sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7 \ + --hash=sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0 \ + --hash=sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1 \ + --hash=sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa \ + --hash=sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03 \ + --hash=sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323 \ + --hash=sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65 \ + --hash=sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013 \ + --hash=sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036 \ + --hash=sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f \ + --hash=sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4 \ + --hash=sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419 \ + --hash=sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2 \ + --hash=sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619 \ + --hash=sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a \ + --hash=sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a \ + --hash=sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd \ + --hash=sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7 \ + --hash=sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666 \ + --hash=sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65 \ + --hash=sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859 \ + --hash=sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625 \ + --hash=sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff \ + --hash=sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156 \ + --hash=sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd \ + --hash=sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba \ + --hash=sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f \ + --hash=sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1 \ + --hash=sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094 \ + --hash=sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a \ + --hash=sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513 \ + --hash=sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed \ + --hash=sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d \ + --hash=sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3 \ + --hash=sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147 \ + --hash=sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c \ + --hash=sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603 \ + --hash=sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601 \ + --hash=sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a \ + --hash=sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1 \ + --hash=sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d \ + --hash=sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3 \ + --hash=sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54 \ + --hash=sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2 \ + --hash=sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6 \ + --hash=sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58 # via jinja2 mccabe==0.7.0 \ --hash=sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325 \ --hash=sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e # via flake8 +mdurl==0.1.2 \ + --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ + --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba + # via markdown-it-py more-itertools==9.0.0 \ --hash=sha256:250e83d7e81d0c87ca6bd942e6aeab8cc9daa6096d12c5308f3f92fa5e5c1f41 \ --hash=sha256:5a6257e40878ef0520b1803990e3e22303a41b5714006c32a3fd8304b26ea1ab @@ -481,9 +495,9 @@ packaging==23.0 \ # pyproject-api # safety # tox -pathspec==0.10.3 \ - --hash=sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6 \ - --hash=sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6 +pathspec==0.11.0 \ + --hash=sha256:3a66eb970cbac598f9e5ccb5b2cf58930cd8e3ed86d393d541eaf2d8b1705229 \ + --hash=sha256:64d338d4e0914e91c1792321e6907b5a593f1ab1851de7fc269557a21b30ebbc # via black pip==22.3.1 \ --hash=sha256:65fd48317359f3af8e593943e6ae1506b66325085ea64b706a998c6e83eeaf38 \ @@ -530,9 +544,9 @@ pygments==2.14.0 \ # via # readme-renderer # rich -pyproject-api==1.4.0 \ - --hash=sha256:ac85c1f82e0291dbae5a7739dbb9a990e11ee4034c9b5599ea714f07a24ecd71 \ - --hash=sha256:c34226297781efdd1ba4dfb74ce21076d9a8360e2125ea31803c1a02c76b2460 +pyproject-api==1.5.0 \ + --hash=sha256:0962df21f3e633b8ddb9567c011e6c1b3dcdfc31b7860c0ede7e24c5a1200fbe \ + --hash=sha256:4c111277dfb96bcd562c6245428f27250b794bfe3e210b8714c4f893952f2c17 # via tox pyproject-hooks==1.0.0 \ --hash=sha256:283c11acd6b928d2f6a7c73fa0d01cb2bdc5f07c57a2eeb6e83d5e56b97976f8 \ @@ -613,16 +627,16 @@ rfc3986==2.0.0 \ --hash=sha256:50b1502b60e289cb37883f3dfd34532b8873c7de9f49bb546641ce9cbd256ebd \ --hash=sha256:97aacf9dbd4bfd829baad6e6309fa6573aaf1be3f6fa735c8ab05e46cecb261c # via twine -rich==13.0.1 \ - --hash=sha256:25f83363f636995627a99f6e4abc52ed0970ebbd544960cc63cbb43aaac3d6f0 \ - --hash=sha256:41fe1d05f433b0f4724cda8345219213d2bfa472ef56b2f64f415b5b94d51b04 +rich==13.2.0 \ + --hash=sha256:7c963f0d03819221e9ac561e1bc866e3f95a02248c1234daa48954e6d381c003 \ + --hash=sha256:f1a00cdd3eebf999a15d85ec498bfe0b1a77efe9b34f645768a54132ef444ac5 # via # manageprojects (pyproject.toml) # rich-click # twine -rich-click==1.6.0 \ - --hash=sha256:33799c31f8817101f2eb8fe90e95d2c2acd428a567ee64358ca487f963f75e9c \ - --hash=sha256:aefb0450c22462cf3bf9fa854457e6b3cdf692073174823a00d3b0541a81b19d +rich-click==1.6.1 \ + --hash=sha256:0fcf4d1a09029d79322dd814ab0b2e66ac183633037561881d45abae8a161d95 \ + --hash=sha256:f8ff96693ec6e261d1544e9f7d9a5811c5ef5d74c8adb4978430fc0dac16777e # via manageprojects (pyproject.toml) ruamel-yaml==0.17.21 \ --hash=sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7 \ @@ -672,9 +686,9 @@ secretstorage==3.3.3 \ --hash=sha256:2403533ef369eca6d2ba81718576c5e0f564d5cca1b58f73a8b23e7d4eeebd77 \ --hash=sha256:f356e6628222568e3af06f2eba8df495efa13b3b63081dafd4f7d9a7b7bc9f99 # via keyring -setuptools==65.7.0 \ - --hash=sha256:4d3c92fac8f1118bb77a22181355e29c239cabfe2b9effdaa665c66b711136d7 \ - --hash=sha256:8ab4f1dbf2b4a65f7eec5ad0c620e84c34111a68d3349833494b9088212214dd +setuptools==66.1.1 \ + --hash=sha256:6f590d76b713d5de4e49fe4fbca24474469f53c83632d5d0fd056f7ff7e8112b \ + --hash=sha256:ac4008d396bc9cd983ea483cb7139c0240a07bbc74ffb6232fceffedc6cf03a8 # via # pip-tools # safety @@ -709,9 +723,9 @@ tomlkit==0.11.6 \ --hash=sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b \ --hash=sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73 # via manageprojects (pyproject.toml) -tox==4.2.8 \ - --hash=sha256:7c31940d755355210151e8bef23feab3d714a8a4795e513c454ff0baccd995b1 \ - --hash=sha256:e9d5006a533d280e2ca26e3ca61052ffa55a65b683486f92d12563a14a9b7a4f +tox==4.3.5 \ + --hash=sha256:307993257d792a12a63ff86a0b67a71a5ab2d4a2cc12bbae947115224d4ac3fb \ + --hash=sha256:6dddc4c69718b65aacbef0921ffa8af065b0f63ff0b24ffc403477975853c918 # via manageprojects (pyproject.toml) twine==4.0.2 \ --hash=sha256:929bc3c280033347a00f847236564d1c52a3e61b1ac2516c97c48f3ceab756d8 \ diff --git a/requirements.txt b/requirements.txt index c970256..8b80641 100644 --- a/requirements.txt +++ b/requirements.txt @@ -121,10 +121,6 @@ click==8.1.3 \ # cookiecutter # manageprojects (pyproject.toml) # rich-click -commonmark==0.9.1 \ - --hash=sha256:452f9dc859be7f06631ddcb328b6919c67984aca654e5fefb3914d54691aed60 \ - --hash=sha256:da2f38c92590f83de410ba1a3cbceafbc74fee9def35f9251ba9a971d6d66fd9 - # via rich cookiecutter==2.1.1 \ --hash=sha256:9f3ab027cec4f70916e28f03470bdb41e637a3ad354b4d65c765d93aad160022 \ --hash=sha256:f3982be8d9c53dac1261864013fdec7f83afd2e42ede6f6dd069c5e149c540d5 @@ -143,48 +139,66 @@ jinja2-time==0.2.0 \ --hash=sha256:d14eaa4d315e7688daa4969f616f226614350c48730bfa1692d2caebd8c90d40 \ --hash=sha256:d3eab6605e3ec8b7a0863df09cc1d23714908fa61aa6986a845c20ba488b4efa # via cookiecutter -markupsafe==2.1.1 \ - --hash=sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003 \ - --hash=sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88 \ - --hash=sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5 \ - --hash=sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7 \ - --hash=sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a \ - --hash=sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603 \ - --hash=sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1 \ - --hash=sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135 \ - --hash=sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247 \ - --hash=sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6 \ - --hash=sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601 \ - --hash=sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77 \ - --hash=sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02 \ - --hash=sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e \ - --hash=sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63 \ - --hash=sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f \ - --hash=sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980 \ - --hash=sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b \ - --hash=sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812 \ - --hash=sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff \ - --hash=sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96 \ - --hash=sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1 \ - --hash=sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925 \ - --hash=sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a \ - --hash=sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6 \ - --hash=sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e \ - --hash=sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f \ - --hash=sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4 \ - --hash=sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f \ - --hash=sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3 \ - --hash=sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c \ - --hash=sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a \ - --hash=sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417 \ - --hash=sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a \ - --hash=sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a \ - --hash=sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37 \ - --hash=sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452 \ - --hash=sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933 \ - --hash=sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a \ - --hash=sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7 +markdown-it-py==2.1.0 \ + --hash=sha256:93de681e5c021a432c63147656fe21790bc01231e0cd2da73626f1aa3ac0fe27 \ + --hash=sha256:cf7e59fed14b5ae17c0006eff14a2d9a00ed5f3a846148153899a0224e2c07da + # via rich +markupsafe==2.1.2 \ + --hash=sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed \ + --hash=sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc \ + --hash=sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2 \ + --hash=sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460 \ + --hash=sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7 \ + --hash=sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0 \ + --hash=sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1 \ + --hash=sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa \ + --hash=sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03 \ + --hash=sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323 \ + --hash=sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65 \ + --hash=sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013 \ + --hash=sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036 \ + --hash=sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f \ + --hash=sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4 \ + --hash=sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419 \ + --hash=sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2 \ + --hash=sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619 \ + --hash=sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a \ + --hash=sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a \ + --hash=sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd \ + --hash=sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7 \ + --hash=sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666 \ + --hash=sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65 \ + --hash=sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859 \ + --hash=sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625 \ + --hash=sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff \ + --hash=sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156 \ + --hash=sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd \ + --hash=sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba \ + --hash=sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f \ + --hash=sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1 \ + --hash=sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094 \ + --hash=sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a \ + --hash=sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513 \ + --hash=sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed \ + --hash=sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d \ + --hash=sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3 \ + --hash=sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147 \ + --hash=sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c \ + --hash=sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603 \ + --hash=sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601 \ + --hash=sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a \ + --hash=sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1 \ + --hash=sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d \ + --hash=sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3 \ + --hash=sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54 \ + --hash=sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2 \ + --hash=sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6 \ + --hash=sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58 # via jinja2 +mdurl==0.1.2 \ + --hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \ + --hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba + # via markdown-it-py pygments==2.14.0 \ --hash=sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297 \ --hash=sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717 @@ -243,15 +257,15 @@ requests==2.28.2 \ --hash=sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa \ --hash=sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf # via cookiecutter -rich==13.0.1 \ - --hash=sha256:25f83363f636995627a99f6e4abc52ed0970ebbd544960cc63cbb43aaac3d6f0 \ - --hash=sha256:41fe1d05f433b0f4724cda8345219213d2bfa472ef56b2f64f415b5b94d51b04 +rich==13.2.0 \ + --hash=sha256:7c963f0d03819221e9ac561e1bc866e3f95a02248c1234daa48954e6d381c003 \ + --hash=sha256:f1a00cdd3eebf999a15d85ec498bfe0b1a77efe9b34f645768a54132ef444ac5 # via # manageprojects (pyproject.toml) # rich-click -rich-click==1.6.0 \ - --hash=sha256:33799c31f8817101f2eb8fe90e95d2c2acd428a567ee64358ca487f963f75e9c \ - --hash=sha256:aefb0450c22462cf3bf9fa854457e6b3cdf692073174823a00d3b0541a81b19d +rich-click==1.6.1 \ + --hash=sha256:0fcf4d1a09029d79322dd814ab0b2e66ac183633037561881d45abae8a161d95 \ + --hash=sha256:f8ff96693ec6e261d1544e9f7d9a5811c5ef5d74c8adb4978430fc0dac16777e # via manageprojects (pyproject.toml) six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \