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

Release Version '1.12.3' into 'master' Branch #175

Merged
merged 5 commits into from
Feb 8, 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
1 change: 1 addition & 0 deletions .github/workflows/load-to-rt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ jobs:

- run: git checkout ${{ env.MAIN_BRANCH }}
- run: git checkout -b ${{ env.BOARDING }}
- run: git push origin --delete ${{ env.BOARDING }} || echo "Remote Branch '${{ env.BOARDING }}' does not exist"

- run: git config --global user.email "[email protected]"
- run: git config --global user.name "Konstantinos Lampridis"
Expand Down
9 changes: 8 additions & 1 deletion .github/workflows/merge-rt-in-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ jobs:
merge_rt_in_release:
# ALLOWED Head Branches
# if: github.event.pull_request.merged == true && startsWith(github.head_ref, 'boarding-auto')
if: github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged == true
# if: github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged == true
if: github.event_name == 'pull_request' && github.event.action == 'closed'
# && github.event.pull_request.head.ref == 'boarding-auto' && github.event.pull_request.merged == true
# github.event.pull_request.auto_merge_enabled

runs-on: ubuntu-latest
env:
Expand All @@ -37,6 +40,10 @@ jobs:
RELEASE_BR: 'release'
MAIN_BR: 'master'
steps:
- run: 'echo "[DEBUG] github.event.pull_request.auto_merge_enabled --> ${{ github.event.pull_request.auto_merge_enabled }}"'
- run: 'echo "github.event.pull_request --> ${{ github.event.pull_request }}"'
- run: "echo \"[DEBUG] github.event.pull_request.merged: '${{ github.event.pull_request.merged == true }}', should be 'true'\""
- run: "echo \"[DEBUG] github.head_ref: '${{ startsWith(github.head_ref, 'boarding-auto') }}', should be 'true'\""
- run: "echo \"[DEBUG] HEAD: '${{ github.head_ref }}', should be 'boarding-auto'\""
- run: "echo \"[DEBUG] BASE: '${{ github.base_ref }}', should be 'release-train'\""

Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ notes\.org~
cookie-py\.log
soft-rel\.log
notes\.md

# LOGS generate by our python code

cookie-py.log
26 changes: 26 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,32 @@ Changelog
=========


1.12.3 (2024-02-08)
===================

**Improved Code Coverage.**


Changes
^^^^^^^

test
""""
- verify expected exceptions are thrown, in cases of errors, and add new sanitization test cases

chore
"""""
- chore(gitignore): update .gitignore

ci
""
- trigger Job of merge-rt-in-release only if github.event_name == 'pull_request' && github.event.pull_request.merged == true

release
"""""""
- bump version to 1.12.3


1.12.2 (2024-02-07)
===================

Expand Down
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -275,9 +275,9 @@ Free/Libre and Open Source Software (FLOSS)

.. Github Releases & Tags

.. |commits_since_specific_tag_on_master| image:: https://img.shields.io/github/commits-since/boromir674/cookiecutter-python-package/v1.12.2/master?color=blue&logo=github
.. |commits_since_specific_tag_on_master| image:: https://img.shields.io/github/commits-since/boromir674/cookiecutter-python-package/v1.12.3/master?color=blue&logo=github
:alt: GitHub commits since tagged version (branch)
:target: https://github.com/boromir674/cookiecutter-python-package/compare/v1.12.2..master
:target: https://github.com/boromir674/cookiecutter-python-package/compare/v1.12.3..master

.. |commits_since_latest_github_release| image:: https://img.shields.io/github/commits-since/boromir674/cookiecutter-python-package/latest?color=blue&logo=semver&sort=semver
:alt: GitHub commits since latest release (by SemVer)
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
author = 'Konstantinos Lampridis'

# The full version, including alpha/beta/rc tags
release = '1.12.2'
release = '1.12.3'

# -- General configuration ---------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ build-backend = "poetry.core.masonry.api"
## Also renders on pypi as 'subtitle'
[tool.poetry]
name = "cookiecutter_python"
version = "1.12.2"
version = "1.12.3"
description = "1-click Generator of Python Project, from Template with streamlined \"DevOps\" using a powerful CI/CD Pipeline."
authors = ["Konstantinos Lampridis <[email protected]>"]
maintainers = ["Konstantinos Lampridis <[email protected]>"]
Expand Down
2 changes: 1 addition & 1 deletion src/cookiecutter_python/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
__version__ = '1.12.2'
__version__ = '1.12.3'

from . import _logging # noqa
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
# TODO Improvement: use an Enum

SUPPORTED = {
'3.5',
'3.6',
'3.7',
'3.8',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import logging
import typing as t
from typing import Pattern, Tuple

from ..input_sanitization import Sanitize
Expand All @@ -12,8 +13,8 @@


class RegExSanitizer:
regex: Pattern
sanitizer: BaseSanitizer
regex: t.ClassVar[Pattern]
sanitizer: t.ClassVar[BaseSanitizer]

def __call__(self, data):
self.sanitizer(data)
Expand Down
111 changes: 31 additions & 80 deletions src/cookiecutter_python/hooks/post_gen_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
"""
#!/usr/bin/env python3

import json
import shutil
import os
import re
import subprocess
import sys
import typing as t
Expand Down Expand Up @@ -41,18 +41,11 @@

def get_request():
cookie_dict: OrderedDict = get_context()
INITIALIZE_GIT_REPO_FLAG = "{{ cookiecutter.initialize_git_repo|lower }}"

# DATA: str to value mapping
data: t.Dict[str, t.Any] = {
'cookiecutter': cookie_dict,
'vars': cookie_dict,
'project_dir': GEN_PROJ_LOC,
'module_name': cookie_dict['pkg_name'],
'author': "{{ cookiecutter.author }}",
'author_email': "{{ cookiecutter.author_email }}",
'initialize_git_repo': {'yes': True}.get(INITIALIZE_GIT_REPO_FLAG, False),
'project_type': "{{ cookiecutter.project_type }}",
# 'add_cli': {'module+cli': True}.get(project_type, False),
'initialize_git_repo': {'yes': True}.get(cookie_dict['initialize_git_repo'].lower(), False),
'repo': None,
# Docs Website: build/infra config, and Content Templates
'docs_website': {
Expand All @@ -62,21 +55,7 @@
# internally used to get the template folder of each Doc Builder
'docs_extra_info': DOCS,
}
# sanity check on data dict for docs_website and docs_extra_info
# TODO: remove sanity checks
assert 'docs_website' in data.keys(), f"ERROR 1: 'docs_website' not in data.keys()={data.keys()}"
assert 'builder' in data['docs_website'].keys(), f"ERROR 2: 'builder' not in data['docs_website'].keys()={data['docs_website'].keys()}"
assert 'docs_extra_info' in data.keys(), f"ERROR 3a: 'docs_extra_info' not in data.keys()={data.keys()}"
assert data['docs_website']['builder'] in {'mkdocs', 'sphinx'}, f"ERROR 3b: docs_website.builder={data['docs_website']['builder']} not in ['mkdocs', 'sphinx']"

from pprint import pprint
pprint("\n\n")
pprint(data)
assert data['docs_website']['builder'] in data['docs_extra_info'].keys(), f"ERROR 3: docs_website.builder={data['docs_website']['builder']} not in docs_extra_info.keys()={data['docs_extra_info'].keys()}"
request = type('PostGenProjectRequest', (), data)
assert hasattr(request, 'docs_extra_info')
assert hasattr(request, 'docs_website')
return request
return type('PostGenProjectRequest', (), data)

Check warning on line 58 in src/cookiecutter_python/hooks/post_gen_project.py

View check run for this annotation

Codecov / codecov/patch

src/cookiecutter_python/hooks/post_gen_project.py#L58

Added line #L58 was not covered by tests


class PostFileRemovalError(Exception):
Expand Down Expand Up @@ -135,7 +114,7 @@
from pathlib import Path

files_to_remove = [
os.path.join(request.project_dir, *x) for x in delete_files[request.project_type](request)
os.path.join(request.project_dir, *x) for x in delete_files[request.vars['project_type']](request)
]
## Post Removal, given 'Project Type', of potentially extra files ##
for file in files_to_remove:
Expand Down Expand Up @@ -166,47 +145,44 @@
if logs_file.exists():
# unintentional behaviour, is still happening
if logs_file.stat().st_size == 0: # at least expect empty log file
# safely remove the empty log file
try:
try: # safely remove the empty log file
logs_file.unlink()
# windows erro reported on CI
# PermissionError: [WinError 32] The process cannot access the file because it is being used by another process
except PermissionError as e:
print(f"[WARNING]: {e}")
print(f"[WARNING]: Could not remove empty log file: {logs_file}")
print("[WARNING]: Please remove it manually, if you wish to do so.")
except PermissionError as e: # has happened on Windows CI

Check warning on line 150 in src/cookiecutter_python/hooks/post_gen_project.py

View check run for this annotation

Codecov / codecov/patch

src/cookiecutter_python/hooks/post_gen_project.py#L150

Added line #L150 was not covered by tests
# PermissionError: [WinError 32] The process cannot access the
# file because it is being used by another process
logger.debug("Permission Error, when removing empty log file: %s", json.dumps({

Check warning on line 153 in src/cookiecutter_python/hooks/post_gen_project.py

View check run for this annotation

Codecov / codecov/patch

src/cookiecutter_python/hooks/post_gen_project.py#L153

Added line #L153 was not covered by tests
'file': str(logs_file),
'error': str(e),
'platform': str(sys.platform),
}, indent=4, sort_keys=True))
else: # captured logs were written in the file: shy from removing it
# Tell user about this, and let them decide what to do
print(f"[INFO]: Captured Logs were written in {logs_file}")


def _get_run_parameters(python3_minor: int):
def run(args: list, kwargs: dict):
return subprocess.run(*args, **dict(kwargs, check=True)) # pylint: disable=W1510 #nosec
def run_process_python37_n_above(*args, **kwargs):
return [args], dict(capture_output=True, check=True, **kwargs)

def run_process_python36_n_below(*args, **kwargs):
return [args], dict(stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, **kwargs)

Check warning on line 167 in src/cookiecutter_python/hooks/post_gen_project.py

View check run for this annotation

Codecov / codecov/patch

src/cookiecutter_python/hooks/post_gen_project.py#L167

Added line #L167 was not covered by tests


def subprocess_run(*args, **kwargs):
def _subprocess_run(get_params):
def run1(*args, **kwargs):
return run(*get_params(*args, **kwargs))
args_list, kwargs_dict = get_params(*args, **kwargs)
return subprocess.run(*args_list, **dict(kwargs_dict, check=True)) # pylint: disable=W1510 #nosec
return run1

return {
d = {
'legacy': _subprocess_run(run_process_python36_n_below),
'new': _subprocess_run(run_process_python37_n_above),
}[
{True: 'legacy', False: 'new'}[
python3_minor < 7 # is legacy Python 3.x version (ie 3.5 or 3.6) ?
sys.version_info.minor < 7 # is legacy Python 3.x version (ie 3.5 or 3.6) ?
]
]


def run_process_python37_n_above(*args, **kwargs):
return [args], dict(capture_output=True, check=True, **kwargs)

def run_process_python36_n_below(*args, **kwargs):
return [args], dict(stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True, **kwargs)


def subprocess_run(*args, **kwargs):
return _get_run_parameters(sys.version_info.minor)(*args, **kwargs)
return d(*args, **kwargs)


def initialize_git_repo(project_dir: str):
Expand All @@ -216,25 +192,6 @@
subprocess_run('git', 'init', cwd=project_dir)


def exception(subprocess_exception: subprocess.CalledProcessError):
error_message = str(subprocess_exception.stderr, encoding='utf-8')
if re.match(r'error: could not lock config file .+\.gitconfig File exists',
error_message):
return type('LockFileError', (Exception,), {})(error_message)
return subprocess_exception

def grant_basic_permissions(project_dir: str):
try:
return subprocess_run(
'git', 'config', '--global', '--add', 'safe.directory', str(project_dir),
cwd=project_dir,
)
except subprocess.CalledProcessError as error:
print('Did not add an entry in ~/.gitconfig!')
print(str(error.stderr, encoding='utf-8'))
print(exception(error))


def iter_files(request):
path_obj = Path(request.project_dir)
for file_path in path_obj.rglob('*'):
Expand All @@ -250,7 +207,7 @@
def git_commit(request):
"""Commit the staged changes in the generated project."""
cookiecutter_config_str = (
'\n'.join((f" {key}: {val}" for key, val in request.cookiecutter.items())) + '\n'
'\n'.join((f" {key}: {val}" for key, val in request.vars.items())) + '\n'
)
commit_message = (
"Template applied from"
Expand All @@ -263,7 +220,7 @@
request.repo.index.add(list(
iter((path.relpath(x, start=request.project_dir) for x in iter_files(request)))
))
author = Actor(request.author, request.author_email)
author = Actor(request.vars['author'], request.vars['author_email'])

request.repo.index.commit(
commit_message,
Expand All @@ -290,7 +247,7 @@
return False


def _post_hook():
def post_hook():
"""Delete irrelevant to Project Type files and optionally do git commit."""
request = get_request()
# Delete gen Files related to
Expand All @@ -312,7 +269,6 @@
# Git commit
if request.initialize_git_repo:
initialize_git_repo(request.project_dir)
# grant_basic_permissions(request.project_dir)
request.repo = Repo(request.project_dir)
if not is_git_repo_clean(request.project_dir):
git_commit(request)
Expand All @@ -321,14 +277,9 @@
return 0


def post_hook():
"""Delete irrelevant to Project Type files and optionally do git commit."""
sys.exit(_post_hook())


def main():
"""Delete irrelevant to Project Type files and optionally do git commit."""
post_hook()
sys.exit(post_hook())


if __name__ == "__main__":
Expand Down
4 changes: 2 additions & 2 deletions src/cookiecutter_python/hooks/pre_gen_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ def input_sanitization(request):
sanitize['interpreters'](request.interpreters)
except sanitize.exceptions['interpreters'] as error:
logger.warning("Interpreters Data Error: %s", json.dumps({
'error': error,
'error': str(error),
'interpreters_data': request.interpreters,
}, sort_keys=True, indent=4))
raise InputSanitizationError(
"ERROR: {request.interpreters} are not valid 'supported interpreters'!"
f"ERROR: {request.interpreters} are not valid 'supported interpreters'!"
) from error

print("Sanitized Input Variables :)")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ dependency-graphs/
test-results/
uml-diagrams/
pydoer-graphs/

# LOGS

cookie-py.log
9 changes: 6 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,11 @@ class HookRequest:
# TODO improvement: add key/value types
### We want to skip running the templating engine, so we mock the state
### that the templating engine would have produced.
cookiecutter: t.Optional[t.Dict] = attr.ib(

# Templated Vars (cookiecutter) use in Context for Jinja Rendering
vars: t.Optional[t.Dict] = attr.ib(
default=OrderedDict(td_cookiecutter_json_data, **engine_state['cookiecutter'])
)
author: t.Optional[str] = attr.ib(default='Konstantinos Lampridis')
author_email: t.Optional[str] = attr.ib(default='[email protected]')
initialize_git_repo: t.Optional[bool] = attr.ib(default=True)
interpreters: t.Optional[t.Dict] = attr.ib(
default=[
Expand Down Expand Up @@ -265,6 +265,9 @@ class HookRequest:
}
)

def __attrs_post_init__(self):
self.vars['project_type'] = self.project_type

class BaseHookRequest(metaclass=SubclassRegistry):
pass

Expand Down
4 changes: 4 additions & 0 deletions tests/data/snapshots/biskotaki-gold-standard/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ dependency-graphs/
test-results/
uml-diagrams/
pydoer-graphs/

# LOGS

cookie-py.log
Loading
Loading