Skip to content

Commit 5c78034

Browse files
committed
[NEW] Migrating Away from setup.cfg
2 parents 223e65b + ca8896a commit 5c78034

File tree

14 files changed

+321
-359
lines changed

14 files changed

+321
-359
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
name: Bug report
3+
about: Create a report to help us improve
4+
title: "[BUG]"
5+
labels: bug
6+
assignees: ''
7+
8+
---
9+
10+
**Describe the bug**
11+
A clear and concise description of what the bug is.
12+
13+
**To Reproduce**
14+
Steps to reproduce the behavior:
15+
1. Install the *cookiecutter-python* package with *python3 -m pip install cookiecutter-python*
16+
2. Run the **cli** as: *generate-python ...*
17+
please provided the arguments supplied to the cli
18+
3. See error
19+
20+
**Expected behavior**
21+
A clear and concise description of what you expected to happen.
22+
23+
**Screenshots**
24+
If applicable, add screenshots to help explain your problem.
25+
26+
**Desktop (please complete the following information):**
27+
- OS: [e.g. Linux Mint, iOS, Windows]
28+
- Version [e.g. 1.2.0]
29+
run: *generate-python --version*
30+
- Python Interpreter
31+
run: *generate-python --version*
32+
33+
34+
**Additional context**
35+
Add any other context about the problem here.
36+
For example, what input values were supplied to the *generate-python*
37+
cli (ie paste contents of your *config file*)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
name: Feature request
3+
about: Suggest an idea for this project
4+
title: "[FEATURE]"
5+
labels: enhancement
6+
assignees: ''
7+
8+
---
9+
10+
**Is your feature request related to a problem? Please describe.**
11+
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12+
13+
**Describe the solution you'd like**
14+
A clear and concise description of what you want to happen.
15+
16+
**Describe alternatives you've considered**
17+
A clear and concise description of any alternative solutions or features you've considered.
18+
19+
**Additional context**
20+
Add any other context or screenshots about the feature request here.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
name: Issue Inquiry
3+
about: Make an inquiry about an "issue" which is not a 'bug' nor a 'feature request'
4+
title: "[OTHER ISSUE]"
5+
labels: question
6+
assignees: ''
7+
8+
---
9+
10+
**TODO: Title Goes Here**
11+
12+
**Do you have a question related to the *cookiecutter-python* package?**
13+
Please submit your question :)
14+
15+
Examples:
16+
- Why is *A* designed the way it is designed?
17+
- How does *A* accomplish whatever it accomplishes?

.github/biskotaki.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ default_context:
99
author_email: k.lampridis@hotmail.com
1010
github_username: boromir674
1111
project_short_description: Project generated from the https://github.com/boromir674/cookiecutter-python-package/tree/master/src/cookiecutter_python cookiecutter
12-
initialize_git_repo: yes
12+
initialize_git_repo: no

.github/workflows/generate.yaml

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ on:
44
push:
55
branches:
66
- 'develop'
7+
- update-generate
78
pull_request:
89
branches:
910
- 'master'
@@ -13,7 +14,7 @@ jobs:
1314
generate:
1415
runs-on: ubuntu-latest
1516
env:
16-
branch: apply-cookiecutter-python-package-template
17+
branch: auto-generated
1718
SUPER_SECRET: ${{ secrets.BISKOTAKI_GH_TOKEN }}
1819
# GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1920
steps:
@@ -71,31 +72,32 @@ jobs:
7172
sudo apt update -y && sudo apt install -y aptitude
7273
sudo aptitude install -y graphviz
7374
python -m pip install --upgrade pip
74-
python -m pip install cookiecutter tox
75+
python -m pip install tox
7576
7677
- name: Clone Biskotaki repo
7778
uses: actions/checkout@v3
7879
with:
7980
repository: boromir674/biskotaki
81+
ref: ${{ env.branch }}
8082
path: 'cloned/biskotaki'
8183

8284
- name: Find Biskotaki version
8385
run: |
8486
cd cloned/biskotaki
85-
chmod +x ./scripts/parse_version.py
86-
echo "PKG_VERSION=$(scripts/parse_version.py)" >> $GITHUB_ENV
87+
echo "PKG_VERSION=$(python scripts/parse_version.py)" >> $GITHUB_ENV
8788
8889
- name: Generate Biskotaki from Template
8990
run: |
9091
pip install --user -e .
9192
echo " version: \"${{ env.PKG_VERSION }}\"" >> .github/biskotaki.yaml
92-
generate-python -o gen --config-file ./.github/biskotaki.yaml --no-input
93+
generate-python -o gen --config-file ./.github/biskotaki.yaml --no-input -f
9394
94-
- name: Test against multiple 'installation' scenarios
95+
- name: Test distributions 'Source', 'Built' and 'edit' (dev env) mode installation
9596
run: |
9697
cd gen/biskotaki
97-
tox -e "py38{-path, -sdist, -wheel, -dev}"
98-
- name: Test Operations such as 'build process' and 'linting'
98+
tox -e "py38{-sdist, -wheel, -dev}"
99+
tox -e coverage
100+
- name: Run Lint, Type Check, Build, Pyroma and PyDeps commands
99101
run: |
100102
cd gen/biskotaki
101103
tox -e lint

CHANGELOG.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,23 @@
22
Changelog
33
=========
44

5+
1.2.1 (2022-05-27)
6+
==================
7+
8+
Compeltely migrate away from *setup.cfg*.
9+
Add Issue Templates, as markdown files, to help create well documented Issues on github.
10+
11+
Changes
12+
^^^^^^^
13+
14+
ci
15+
""
16+
- do not run py38-path tox env & improve ci steps names
17+
- push generated package to 'auto-generated' branch on 'origin' remote
18+
- do not initialize a git repository after package generation
19+
- refactor parse script to read from pyproject.toml
20+
21+
522
1.2.0 (2022-05-24)
623
==================
724

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,9 @@ For more complex use cases, you can modify the Template and also leverage all of
196196

197197
.. Github Releases & Tags
198198
199-
.. |commits_since_specific_tag_on_master| image:: https://img.shields.io/github/commits-since/boromir674/cookiecutter-python-package/v1.2.0/master?color=blue&logo=github
199+
.. |commits_since_specific_tag_on_master| image:: https://img.shields.io/github/commits-since/boromir674/cookiecutter-python-package/v1.2.1/master?color=blue&logo=github
200200
:alt: GitHub commits since tagged version (branch)
201-
:target: https://github.com/boromir674/cookiecutter-python-package/compare/v1.2.0..master
201+
:target: https://github.com/boromir674/cookiecutter-python-package/compare/v1.2.1..master
202202

203203
.. |commits_since_latest_github_release| image:: https://img.shields.io/github/commits-since/boromir674/cookiecutter-python-package/latest?color=blue&logo=semver&sort=semver
204204
:alt: GitHub commits since latest release (by SemVer)

pyproject.toml

100644100755
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ build-backend = "poetry.core.masonry.api"
1010
## Also renders on pypi as 'subtitle'
1111
[tool.poetry]
1212
name = "cookiecutter_python"
13-
version = "1.2.0"
13+
version = "1.2.1"
1414
description = "Yet another modern Python Package (pypi) with emphasis in CI/CD and automation."
1515
authors = ["Konstantinos Lampridis <k.lampridis@hotmail.com>"]
1616
maintainers = ["Konstantinos Lampridis <k.lampridis@hotmail.com>"]
@@ -190,3 +190,7 @@ hooks/post_gen_project.py
190190

191191
[tool.isort]
192192
profile = 'black'
193+
194+
195+
[tool.software-release]
196+
version_variable = "src/cookiecutter_python/__init__.py:__version__"

scripts/parse_version.py

Lines changed: 105 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,126 @@
11
#!/usr/bin/env python
22

3-
43
import os
54
import re
65
import sys
6+
import typing as t
7+
8+
# TODO Improve: try using the semantic_version_checker package for semver regex
9+
10+
ExceptionFactory = t.Callable[[str, str, str], Exception]
11+
ClientCallback = t.Callable[[str, str], t.Tuple]
12+
13+
MatchConverter = t.Callable[[t.Match], t.Tuple]
14+
MatchData = t.Tuple[str, t.List[t.Any], t.Callable[[t.Match], t.Tuple]]
15+
# 1st item (str): 'method'/'callable attribute' of the 're' python module)
16+
# 2nd item (list): zero or more additional runtime arguments
17+
# 3rd item (Callable): takes a Match object and return a tuple of strings
718

819
my_dir = os.path.dirname(os.path.realpath(__file__))
920

10-
SETUP_CFG_FILENAME = 'setup.cfg'
11-
SETUP_CFG = os.path.join(my_dir, '../', SETUP_CFG_FILENAME)
21+
TOML = 'pyproject.toml'
22+
TOML_FILE = os.path.abspath(os.path.join(my_dir, '..', TOML))
1223

24+
DEMO_SECTION: str = (
25+
"[tool.software-release]\nversion_variable = "
26+
"src/package_name/__init__.py:__version__"
27+
)
1328

14-
def main():
15-
"""Get the package version string provided that the developer has setup indication how to find it. Reads the
16-
[semantic_release] section found in setup.cfg and then determines where is the actual version string
17-
"""
18-
# Automatically compute package version from the [semantic_release] section in setup.cfg
19-
with open(SETUP_CFG, 'r') as _file:
20-
regex = r"\[semantic_release\][\w\s=/\.:\d]+version_variable[\ \t]*=[\ \t]*([\w\.]+(?:/[\w\.]+)*):(\w+)"
21-
match = re.search(regex, _file.read(), re.MULTILINE)
29+
30+
def build_client_callback(data: MatchData, factory: ExceptionFactory) -> ClientCallback:
31+
32+
def client_callback(file_path: str, regex: str) -> t.Tuple:
33+
with open(file_path, 'r') as _file:
34+
contents = _file.read()
35+
match = getattr(re, data[0])(regex, contents, *data[1])
2236
if match:
23-
file_with_version_string = os.path.join(my_dir, '../', match.group(1))
24-
variable_holding_version_value = match.group(2)
37+
extracted_tuple = data[2](match)
38+
return extracted_tuple
2539
else:
26-
raise RuntimeError(
27-
f"Expected to find the '[semantic_release]' section, in the '{SETUP_CFG}' file, with key "
28-
f"'version_variable'.\nFor example:\n[semantic_release]\nversion_variable = "
29-
f"src/package_name/__init__.py:__version__\n indicated that the version string should be looked up in "
30-
f"the src/package_name/__init__.py file registered under the __version__ 'name'")
31-
32-
# (it does not have to be a.py file)
33-
# to indicate that the version is stored in the '__version__'
34-
if not os.path.isfile(file_with_version_string):
35-
raise FileNotFoundError(
36-
f"Path '{file_with_version_string} does not appear to be valid. Please go to the '{SETUP_CFG}' file, at the"
37-
f" [semantic_release] section and set the 'version_variable' key with a valid file path (to look for the "
38-
f"version string)")
40+
raise factory(file_path, regex, contents)
41+
return client_callback
3942

40-
reg_string = r'\s*=\s*[\'\"]([^\'\"]*)[\'\"]'
4143

44+
# PARSERS
4245

43-
with open(file_with_version_string, 'r') as _file:
44-
content = _file.read()
45-
reg = f'^{variable_holding_version_value}' + reg_string
46-
match = re.search(reg, content, re.MULTILINE)
47-
if match:
48-
_version = match.group(1)
49-
return _version
50-
raise AttributeError(f"Could not find a match for regex {reg} when applied to:\n{content}")
46+
software_release_parser = build_client_callback((
47+
'search',
48+
[re.MULTILINE,],
49+
lambda match: (match.group(1), match.group(2))
50+
),
51+
lambda file_path, reg, string: RuntimeError(
52+
"Expected to find the '[tool.software-release]' section, in "
53+
f"the '{file_path}' file, with key "
54+
"'version_variable'.\nFor example:\n"
55+
f"{DEMO_SECTION}\n "
56+
"indicates that the version string should be looked up in "
57+
f"the src/package_name/__init__.py file and specifically "
58+
"a '__version__ = 1.2.3' kind of line is expected to be found."
59+
)
60+
)
5161

5262

53-
if __name__ == '__main__':
63+
version_file_parser = build_client_callback((
64+
'search',
65+
[re.MULTILINE,],
66+
lambda match: (match.group(1),)
67+
),
68+
lambda file_path, reg, string: AttributeError(
69+
"Could not find a match for regex {regex} when applied to:".format(
70+
regex=reg
71+
) + "\n{content}".format(content=string)
72+
)
73+
)
74+
75+
76+
def parse_version(software_release_cfg: str) -> str:
77+
"""Detect, parse and return the version (string) from python source code.
78+
79+
Get the package version (string) provided that the developer has setup
80+
indication how to find it.
81+
82+
Reads the [tool.software-release] section found in pyproject.toml and then
83+
determines where is the actual version string.
84+
"""
85+
header = r'\[tool\.software-release\]'
86+
sep = r'[\w\s=/\.:\d]+' # in some cases accounts for miss-typed characters!
87+
version_specification = \
88+
r"version_variable[\ \t]*=[\ \t]*['\"]?([\w\.]+(?:/[\w\.]+)*):(\w+)['\"]?"
89+
regex = f"{header}{sep}{version_specification}"
90+
91+
file_name_with_version, version_variable_name = \
92+
software_release_parser(software_release_cfg, regex)
93+
94+
file_with_version_string = \
95+
os.path.abspath(os.path.join(my_dir, '../', file_name_with_version))
96+
97+
if not os.path.isfile(file_with_version_string):
98+
raise FileNotFoundError(
99+
f"Path '{file_with_version_string} does not appear to be valid. "
100+
f"Please go to the '{software_release_cfg}' file, at the"
101+
" [tool.software-release] section and set the 'version_variable' "
102+
"key with a valid file path (to look for the version string). "
103+
f"For example:\n{DEMO_SECTION}\n"
104+
)
105+
106+
reg = f'^{version_variable_name}' + r'\s*=\s*[\'\"]([^\'\"]*)[\'\"]'
107+
version, = version_file_parser(file_with_version_string, reg)
108+
return version
109+
110+
111+
def _main():
54112
try:
55-
version_string = main()
113+
version_string = parse_version(TOML_FILE)
56114
print(version_string)
115+
return 0
57116
except (RuntimeError, FileNotFoundError, AttributeError) as exception:
58117
print(exception)
59-
sys.exit(1)
118+
return 1
119+
120+
121+
def main():
122+
sys.exit(_main())
123+
124+
125+
if __name__ == '__main__':
126+
main()

0 commit comments

Comments
 (0)