python-kacl 0.6.3__py3-none-any.whl → 0.6.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
kacl/__init__.py CHANGED
@@ -1,5 +1,5 @@
1
1
  # Version of the python-kacl package
2
- __version__ = "0.6.3"
2
+ __version__ = "0.6.5"
3
3
 
4
4
  from kacl.document import KACLDocument
5
5
  from kacl.serializer import KACLMarkdownSerializer
kacl/kacl_cli.py CHANGED
@@ -177,7 +177,12 @@ def next(ctx, version):
177
177
  @cli.command()
178
178
  @click.pass_context
179
179
  @click.argument("version", type=str)
180
- def get(ctx, version):
180
+ @click.option(
181
+ "--no-link",
182
+ is_flag=True,
183
+ help="This option suppresses a link, even if available.",
184
+ )
185
+ def get(ctx, version, no_link):
181
186
  """Returns a given version from the Changelog."""
182
187
  kacl_changelog = load_changelog(ctx)
183
188
 
@@ -185,6 +190,8 @@ def get(ctx, version):
185
190
  kacl_version = kacl_changelog.get(version)
186
191
 
187
192
  if kacl_version:
193
+ if no_link:
194
+ kacl_version.set_link(None)
188
195
  kacl_changelog_content = kacl.dump(kacl_version)
189
196
  click.echo(kacl_changelog_content)
190
197
  else:
kacl/serializer.py CHANGED
@@ -11,30 +11,37 @@ class KACLMarkdownSerializer:
11
11
  pass
12
12
 
13
13
  def serialize(self, document):
14
+ data = []
15
+ link_references = []
14
16
  if isinstance(document, KACLDocument):
15
- data = []
16
-
17
17
  serialized_metadata = self.__serialize_metadata(document.metadata())
18
18
  if serialized_metadata:
19
19
  data.extend(serialized_metadata)
20
20
 
21
21
  data.append(self.__serialize_header(document.header()))
22
- data.append(document.header().body())
22
+ # check if the body starts with a newline. if not add one
23
+ if document.header().body().startswith("\n"):
24
+ data.append(document.header().body())
25
+ else:
26
+ data.append("\n" + document.header().body())
23
27
 
24
- link_references = []
25
28
  for version in document.versions():
26
29
  data.extend([self.__serialize_version(version), ""])
27
30
  if version.has_link_reference():
28
31
  link_references.append(self.__serialize_link_reference(version))
29
32
 
30
- data.extend(link_references)
33
+ elif isinstance(document, KACLVersion):
34
+ data.extend([self.__serialize_version(document), ""])
31
35
 
32
- if data[-1] != "":
33
- data.append("")
36
+ if document.has_link_reference():
37
+ link_references.append(self.__serialize_link_reference(document))
34
38
 
35
- return "\n".join(data)
36
- elif isinstance(document, KACLVersion):
37
- return self.__serialize_version(document)
39
+ data.extend(link_references)
40
+
41
+ if data[-1] != "":
42
+ data.append("")
43
+
44
+ return "\n".join(data)
38
45
 
39
46
  def __serialize_metadata(self, metadata):
40
47
  if not metadata:
@@ -64,11 +71,12 @@ class KACLMarkdownSerializer:
64
71
  return f"# {obj.title()}"
65
72
 
66
73
  def __serialize_version(self, obj):
67
- lines = [self.__serialize_header(obj)]
74
+ lines = [self.__serialize_header(obj), ""]
68
75
  for title, changes in obj.sections().items():
69
76
  lines.extend(
70
77
  [
71
78
  self.__serialize_header(changes),
79
+ "",
72
80
  self.__serialize_list(changes.items()),
73
81
  "",
74
82
  ]
kacl/version.py CHANGED
@@ -47,9 +47,9 @@ class KACLVersion(KACLElement):
47
47
  return self.__link_reference.body()
48
48
 
49
49
  def set_link(self, link):
50
- if isinstance(link, KACLElement):
50
+ if not link or isinstance(link, KACLElement):
51
51
  self.__link_reference = link
52
- elif link is not None:
52
+ else:
53
53
  self.__link_reference = KACLElement(title=self.version(), body=link)
54
54
 
55
55
  def has_link_reference(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-kacl
3
- Version: 0.6.3
3
+ Version: 0.6.5
4
4
  Summary: Python module and CLI tool for validating and modifying Changelogs in "keep-a-changelog" format"
5
5
  Home-page: https://gitlab.com/schmieder.matthias/python-kacl.git
6
6
  Author: Matthias Schmieder
@@ -0,0 +1,22 @@
1
+ kacl/__init__.py,sha256=WUM42QzTkxNY6Yd-x-FEqcO2NFfzXkqDhRoAyqME1EE,644
2
+ kacl/__main__.py,sha256=cpulIGoFUJNN5ZW9oUoNN1PnBvrOyJ24xwtpf_yRwgQ,91
3
+ kacl/changes.py,sha256=A0POz-xFMpFuq7nISnx_K75xOZOMmBuHq6EZ8NOQDsU,661
4
+ kacl/config.py,sha256=Glw-1hRqS3AHpZ-2QRGzHRQ-TSLc1xtneb2MEATWFEQ,3966
5
+ kacl/document.py,sha256=dzeYCIgLA1WzK04jeeCW_AYSOCampc9x2cAHdbnEMpY,24737
6
+ kacl/element.py,sha256=OG02QI8ND5fJpBMceT6dbIHr4uX9gLxK_fPCsOvMDHI,416
7
+ kacl/exception.py,sha256=MfOVpUvhcQtm10rSY__74-oLo445PG8mLFGJPPIfXH0,41
8
+ kacl/jira_client.py,sha256=KPE94bZDkJFKw3okFsCgf2DjoyMlUUTMZKtQGKreVQY,989
9
+ kacl/kacl_cli.py,sha256=KeCT4DydkHjckt5sbTtTwp2BQf0RllXpBUwLj-G5-U0,19987
10
+ kacl/link_provider.py,sha256=tgvMYhJe2ErH1m_qXMlQEacq9Cg_KGp_-sF03sVFP6E,1866
11
+ kacl/parser.py,sha256=EUtRjgaW0beWVqiYaRJ9Rcf6jbuGoTgWzVBdOdUHnv8,2587
12
+ kacl/serializer.py,sha256=PdR2FFCh9rbBhkxXwUYD0fSjQqTG_Mb6mYws3lNAWQ8,3090
13
+ kacl/utils.py,sha256=bHiDDmjoYB868Bm732vNjpfML-6xcNQQqS7NQn_Sfm0,2824
14
+ kacl/validation.py,sha256=b9r_5CyY6Cmi9BePh47IgZ3j64zdVsoB_fFvucieNbw,2125
15
+ kacl/version.py,sha256=IDYCWIIXzxdYyMptUAidMgf0SXJqoETFVJ8NVyKgA9A,9526
16
+ kacl/config/kacl-default.yml,sha256=BdrQytOsx32_vXXBtR3VRp1-nzWrczNVc-gHuCGYuIA,1424
17
+ python_kacl-0.6.5.dist-info/licenses/LICENSE,sha256=TRSJOIt7LZuMeZXFleJVL_LHczSxqi70HEiTLT-kI8Q,1075
18
+ python_kacl-0.6.5.dist-info/METADATA,sha256=kVBx144zCKsmVBAnZS-RQ1omJ2QiPfIME6DtJRz8loE,24325
19
+ python_kacl-0.6.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
20
+ python_kacl-0.6.5.dist-info/entry_points.txt,sha256=rXqqJKfm6Y7fYfioq_7ay2VWOOM9C-hts1IsoGTtojM,76
21
+ python_kacl-0.6.5.dist-info/top_level.txt,sha256=BcmQgo67JyGnVZ3Jc0Ag8hKMGVOqXc8ex01zW4Njw5M,5
22
+ python_kacl-0.6.5.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (79.0.1)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,2 +1,3 @@
1
1
  [console_scripts]
2
+ kacl = kacl.kacl_cli:start
2
3
  kacl-cli = kacl.kacl_cli:start
@@ -0,0 +1 @@
1
+ kacl
@@ -1,26 +0,0 @@
1
- kacl/__init__.py,sha256=XekPy57r8cGMBo1Kb3tOG9_THW2FkjplUELdl4BBXQ0,644
2
- kacl/__main__.py,sha256=cpulIGoFUJNN5ZW9oUoNN1PnBvrOyJ24xwtpf_yRwgQ,91
3
- kacl/changes.py,sha256=A0POz-xFMpFuq7nISnx_K75xOZOMmBuHq6EZ8NOQDsU,661
4
- kacl/config.py,sha256=Glw-1hRqS3AHpZ-2QRGzHRQ-TSLc1xtneb2MEATWFEQ,3966
5
- kacl/document.py,sha256=dzeYCIgLA1WzK04jeeCW_AYSOCampc9x2cAHdbnEMpY,24737
6
- kacl/element.py,sha256=OG02QI8ND5fJpBMceT6dbIHr4uX9gLxK_fPCsOvMDHI,416
7
- kacl/exception.py,sha256=MfOVpUvhcQtm10rSY__74-oLo445PG8mLFGJPPIfXH0,41
8
- kacl/jira_client.py,sha256=KPE94bZDkJFKw3okFsCgf2DjoyMlUUTMZKtQGKreVQY,989
9
- kacl/kacl_cli.py,sha256=fdTVlhjldQGBRhiSG5x9SnnwKTgysLxhqlkjx8BUSK8,19804
10
- kacl/link_provider.py,sha256=tgvMYhJe2ErH1m_qXMlQEacq9Cg_KGp_-sF03sVFP6E,1866
11
- kacl/parser.py,sha256=EUtRjgaW0beWVqiYaRJ9Rcf6jbuGoTgWzVBdOdUHnv8,2587
12
- kacl/serializer.py,sha256=4HU0G6ETbsvf6TbuRdhuNcuWFfifMT6jAEyhtJkAL8s,2734
13
- kacl/utils.py,sha256=bHiDDmjoYB868Bm732vNjpfML-6xcNQQqS7NQn_Sfm0,2824
14
- kacl/validation.py,sha256=b9r_5CyY6Cmi9BePh47IgZ3j64zdVsoB_fFvucieNbw,2125
15
- kacl/version.py,sha256=_yi7OxKOyM17L-G3imjQ2ZBgiVzUoR5rqhhFX2b4faM,9531
16
- kacl/config/kacl-default.yml,sha256=BdrQytOsx32_vXXBtR3VRp1-nzWrczNVc-gHuCGYuIA,1424
17
- python_kacl-0.6.3.dist-info/licenses/LICENSE,sha256=TRSJOIt7LZuMeZXFleJVL_LHczSxqi70HEiTLT-kI8Q,1075
18
- tests/__init__.py,sha256=dwb12vsojIwrtIgqwjc2fWhEVgVoiedUaVpZ7kusfY0,23
19
- tests/snapshot_directory.py,sha256=yH_ZpzJG5nA6F1ZxCrFPpbxBBON6bxSYO5OYZqKuzZA,1264
20
- tests/test_cli.py,sha256=Fc8DA_72cYyjXQm9AfJdAzz89D5zVJGInIxwIBhqrKA,14286
21
- tests/test_kacl.py,sha256=7hxrBVnj2srkhJGVrfpt651QEItthq-iDntxGnEbt_g,15919
22
- python_kacl-0.6.3.dist-info/METADATA,sha256=l3MYi-NX0YVCOZjSUJlLx9xITYn6oLkXxtjPWQwGHB8,24325
23
- python_kacl-0.6.3.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
24
- python_kacl-0.6.3.dist-info/entry_points.txt,sha256=8oCwuEyBEH-Z1M_xZIUePgfM7HfkYUAwcXdTPdrnwt4,49
25
- python_kacl-0.6.3.dist-info/top_level.txt,sha256=25gO0j-S3j_-DCptjHqVBlJi3tH_tiN8qyympi1E_Ys,11
26
- python_kacl-0.6.3.dist-info/RECORD,,
@@ -1,2 +0,0 @@
1
- kacl
2
- tests
tests/__init__.py DELETED
@@ -1 +0,0 @@
1
- __version__ = "0.4.51"
@@ -1,42 +0,0 @@
1
- import os
2
- from pathlib import Path
3
-
4
-
5
- def snapshot_directory(
6
- snapshot,
7
- directory_path,
8
- dir_excludes=[".git"],
9
- file_excludes=[],
10
- sanitize_callbacks={},
11
- ):
12
- snapshot_dir = {}
13
-
14
- for root, dirs, files in os.walk(directory_path, topdown=True):
15
- dirs[:] = [d for d in dirs if d not in dir_excludes]
16
-
17
- for file in files:
18
- if file in file_excludes:
19
- continue
20
- current = snapshot_dir
21
- parts = Path(root).relative_to(directory_path).parts
22
- for part in parts:
23
- current = current.setdefault(part, {})
24
-
25
- file_path = os.path.join(root, f"{file}")
26
- if __is_binary(file_path):
27
- content = open(file_path, "rb").read()
28
- else:
29
- content = open(file_path, "r").read()
30
-
31
- if file in sanitize_callbacks:
32
- callback = sanitize_callbacks[file]
33
- content = callback(content)
34
-
35
- current[f"{file}.snap"] = content
36
-
37
- snapshot.assert_match_dir(snapshot_dir, "snapshots")
38
-
39
-
40
- def __is_binary(file_path):
41
- textchars = bytearray({7, 8, 9, 10, 12, 13, 27} | set(range(0x20, 0x100)) - {0x7F})
42
- return bool(open(file_path, "rb").read(1024).translate(None, textchars))
tests/test_cli.py DELETED
@@ -1,418 +0,0 @@
1
- import json
2
- import os
3
- import shutil
4
-
5
- import pytest
6
- from click.testing import CliRunner
7
- from freezegun import freeze_time
8
-
9
- from kacl.kacl_cli import cli
10
- from tests.snapshot_directory import snapshot_directory
11
-
12
-
13
- def test_verify():
14
- runner = CliRunner()
15
- result = runner.invoke(cli, ["-f", "tests/data/CHANGELOG.md", "verify"])
16
- assert result.exit_code == 0
17
- assert result.output == "Success\n"
18
-
19
- result = runner.invoke(cli, ["-f", "tests/data/CHANGELOG_invalid.md", "verify"])
20
- assert result.exit_code == 10 # spawns 8 errors
21
-
22
-
23
- def test_verify_invalid_duplicates():
24
- runner = CliRunner()
25
- result = runner.invoke(
26
- cli, ["-f", "tests/data/CHANGELOG_invalid_duplicates.md", "verify"]
27
- )
28
- assert result.exit_code == 2
29
-
30
-
31
- def test_verify_with_json_output():
32
- runner = CliRunner()
33
- result = runner.invoke(
34
- cli, ["-f", "tests/data/CHANGELOG_invalid.md", "verify", "--json"]
35
- )
36
- validation_result = json.loads(result.output)
37
-
38
- assert len(validation_result["errors"]) == 10
39
- assert validation_result["valid"] is False
40
-
41
-
42
- def test_current(tmp_path, snapshot):
43
- runner = CliRunner()
44
- resources_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data/")
45
- changelog_file = os.path.join(resources_dir, "CHANGELOG_with_changes.md")
46
-
47
- with runner.isolated_filesystem(temp_dir=tmp_path):
48
- result = runner.invoke(
49
- cli,
50
- [
51
- "-f",
52
- changelog_file,
53
- "current",
54
- ],
55
- catch_exceptions=False,
56
- )
57
- assert result.exit_code == 0, result.output
58
- assert result.output == "1.0.0\n"
59
-
60
-
61
- def test_next(tmp_path, snapshot):
62
- runner = CliRunner()
63
- resources_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data/")
64
- changelog_file = os.path.join(resources_dir, "CHANGELOG_with_changes.md")
65
-
66
- with runner.isolated_filesystem(temp_dir=tmp_path):
67
- result = runner.invoke(
68
- cli,
69
- ["-f", changelog_file, "next", "patch"],
70
- catch_exceptions=False,
71
- )
72
- assert result.exit_code == 0, result.output
73
- assert result.output == "1.0.1\n"
74
-
75
-
76
- @freeze_time("2023-01-01")
77
- def test_release_patch(tmp_path, snapshot):
78
- runner = CliRunner()
79
- resources_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data/")
80
- changelog_file = os.path.join(resources_dir, "CHANGELOG_with_changes.md")
81
-
82
- with runner.isolated_filesystem(temp_dir=tmp_path) as project_root_path:
83
- shutil.copyfile(changelog_file, os.path.join(project_root_path, "CHANGELOG.md"))
84
- result = runner.invoke(
85
- cli,
86
- [
87
- "-f",
88
- "CHANGELOG.md",
89
- "release",
90
- "patch",
91
- "-m",
92
- ],
93
- catch_exceptions=False,
94
- )
95
- assert result.exit_code == 0, result.output
96
- snapshot_directory(snapshot=snapshot, directory_path=project_root_path)
97
-
98
-
99
- @freeze_time("2023-01-01")
100
- def test_release_post_bump(tmp_path, snapshot):
101
- runner = CliRunner()
102
- resources_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data/")
103
- changelog_file = os.path.join(resources_dir, "CHANGELOG_with_changes.md")
104
-
105
- with runner.isolated_filesystem(temp_dir=tmp_path) as project_root_path:
106
- shutil.copyfile(changelog_file, os.path.join(project_root_path, "CHANGELOG.md"))
107
- result = runner.invoke(
108
- cli,
109
- [
110
- "-c",
111
- os.path.join(resources_dir, "extension-config.yml"),
112
- "-f",
113
- "CHANGELOG.md",
114
- "release",
115
- "post",
116
- "-m",
117
- ],
118
- catch_exceptions=False,
119
- )
120
- assert result.exit_code == 0, result.output
121
- snapshot_directory(snapshot=snapshot, directory_path=project_root_path)
122
-
123
-
124
- @freeze_time("2023-01-01")
125
- def test_release_post_manual(tmp_path, snapshot):
126
- runner = CliRunner()
127
- resources_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data/")
128
- changelog_file = os.path.join(resources_dir, "CHANGELOG_with_changes.md")
129
-
130
- with runner.isolated_filesystem(temp_dir=tmp_path) as project_root_path:
131
- shutil.copyfile(changelog_file, os.path.join(project_root_path, "CHANGELOG.md"))
132
- result = runner.invoke(
133
- cli,
134
- [
135
- "-c",
136
- os.path.join(resources_dir, "extension-config.yml"),
137
- "-f",
138
- "CHANGELOG.md",
139
- "release",
140
- "2.0.0-hotfix.0",
141
- "-m",
142
- ],
143
- catch_exceptions=False,
144
- )
145
- assert result.exit_code == 0, result.output
146
- snapshot_directory(snapshot=snapshot, directory_path=project_root_path)
147
-
148
-
149
- @freeze_time("2023-01-01")
150
- def test_release_post_manual_fail(tmp_path, snapshot):
151
- runner = CliRunner()
152
- resources_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data/")
153
- changelog_file = os.path.join(resources_dir, "CHANGELOG_with_changes.md")
154
-
155
- with runner.isolated_filesystem(temp_dir=tmp_path) as project_root_path:
156
- shutil.copyfile(changelog_file, os.path.join(project_root_path, "CHANGELOG.md"))
157
- result = runner.invoke(
158
- cli,
159
- [
160
- "-c",
161
- os.path.join(resources_dir, "extension-config.yml"),
162
- "-f",
163
- "CHANGELOG.md",
164
- "release",
165
- "0.5.0-hotfix.0",
166
- "-m",
167
- ],
168
- catch_exceptions=True,
169
- )
170
- assert result.exit_code == 1, result.output
171
-
172
-
173
- @freeze_time("2023-01-01")
174
- def test_release_version_manual_fail_same_base_after_post(tmp_path, snapshot):
175
- runner = CliRunner()
176
- resources_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data/")
177
- changelog_file = os.path.join(resources_dir, "CHANGELOG_post_with_changes.md")
178
-
179
- with runner.isolated_filesystem(temp_dir=tmp_path) as project_root_path:
180
- shutil.copyfile(changelog_file, os.path.join(project_root_path, "CHANGELOG.md"))
181
- result = runner.invoke(
182
- cli,
183
- [
184
- "-c",
185
- os.path.join(resources_dir, "extension-config.yml"),
186
- "-f",
187
- "CHANGELOG.md",
188
- "release",
189
- "1.0.0",
190
- "-m",
191
- ],
192
- catch_exceptions=True,
193
- )
194
- assert result.exit_code == 1, result.output
195
-
196
-
197
- @freeze_time("2023-01-01")
198
- def test_release_post_manual_same_base(tmp_path, snapshot):
199
- runner = CliRunner()
200
- resources_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data/")
201
- changelog_file = os.path.join(resources_dir, "CHANGELOG_with_changes.md")
202
-
203
- with runner.isolated_filesystem(temp_dir=tmp_path) as project_root_path:
204
- shutil.copyfile(changelog_file, os.path.join(project_root_path, "CHANGELOG.md"))
205
- result = runner.invoke(
206
- cli,
207
- [
208
- "-c",
209
- os.path.join(resources_dir, "extension-config.yml"),
210
- "-f",
211
- "CHANGELOG.md",
212
- "release",
213
- "1.0.0-post.0",
214
- "-m",
215
- ],
216
- catch_exceptions=False,
217
- )
218
- assert result.exit_code == 0, result.output
219
-
220
-
221
- @freeze_time("2023-01-01")
222
- def test_release_minor(tmp_path, snapshot):
223
- runner = CliRunner()
224
- resources_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data/")
225
- changelog_file = os.path.join(resources_dir, "CHANGELOG_with_changes.md")
226
-
227
- with runner.isolated_filesystem(temp_dir=tmp_path) as project_root_path:
228
- shutil.copyfile(changelog_file, os.path.join(project_root_path, "CHANGELOG.md"))
229
- result = runner.invoke(
230
- cli,
231
- [
232
- "-f",
233
- "CHANGELOG.md",
234
- "release",
235
- "minor",
236
- "-m",
237
- ],
238
- catch_exceptions=False,
239
- )
240
- assert result.exit_code == 0, result.output
241
- snapshot_directory(snapshot=snapshot, directory_path=project_root_path)
242
-
243
-
244
- @freeze_time("2023-01-01")
245
- def test_release_major(tmp_path, snapshot):
246
- runner = CliRunner()
247
- resources_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data/")
248
- changelog_file = os.path.join(resources_dir, "CHANGELOG_with_changes.md")
249
-
250
- with runner.isolated_filesystem(temp_dir=tmp_path) as project_root_path:
251
- shutil.copyfile(changelog_file, os.path.join(project_root_path, "CHANGELOG.md"))
252
- result = runner.invoke(
253
- cli,
254
- [
255
- "-f",
256
- "CHANGELOG.md",
257
- "release",
258
- "major",
259
- "-m",
260
- ],
261
- catch_exceptions=False,
262
- )
263
- assert result.exit_code == 0, result.output
264
- snapshot_directory(snapshot=snapshot, directory_path=project_root_path)
265
-
266
-
267
- @freeze_time("2023-01-01")
268
- def test_release_custom(tmp_path, snapshot):
269
- runner = CliRunner()
270
- resources_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data/")
271
- changelog_file = os.path.join(resources_dir, "CHANGELOG_with_changes.md")
272
-
273
- with runner.isolated_filesystem(temp_dir=tmp_path) as project_root_path:
274
- shutil.copyfile(changelog_file, os.path.join(project_root_path, "CHANGELOG.md"))
275
- result = runner.invoke(
276
- cli,
277
- [
278
- "-f",
279
- "CHANGELOG.md",
280
- "release",
281
- "2.1.1",
282
- "-m",
283
- ],
284
- catch_exceptions=False,
285
- )
286
- assert result.exit_code == 0, result.output
287
- snapshot_directory(snapshot=snapshot, directory_path=project_root_path)
288
-
289
-
290
- @freeze_time("2023-01-01")
291
- def test_add_change_security(tmp_path, snapshot):
292
- runner = CliRunner()
293
- resources_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data/")
294
- changelog_file = os.path.join(resources_dir, "CHANGELOG_with_changes.md")
295
-
296
- with runner.isolated_filesystem(temp_dir=tmp_path) as project_root_path:
297
- shutil.copyfile(changelog_file, os.path.join(project_root_path, "CHANGELOG.md"))
298
- result = runner.invoke(
299
- cli,
300
- [
301
- "-f",
302
- "CHANGELOG.md",
303
- "add",
304
- "Security",
305
- "Important Security Change",
306
- "-m",
307
- ],
308
- catch_exceptions=False,
309
- )
310
- assert result.exit_code == 0, result.output
311
- snapshot_directory(snapshot=snapshot, directory_path=project_root_path)
312
-
313
-
314
- def test_config(tmp_path, snapshot):
315
- runner = CliRunner()
316
- resources_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data/")
317
-
318
- result = runner.invoke(
319
- cli,
320
- [
321
- "-c",
322
- os.path.join(resources_dir, "config.yml"),
323
- "-f",
324
- "CHANGELOG.md",
325
- "verify",
326
- ],
327
- catch_exceptions=False,
328
- )
329
- assert result.exit_code != 0, result.output
330
-
331
-
332
- @freeze_time("2023-01-01")
333
- def test_squash(tmp_path, snapshot):
334
- runner = CliRunner()
335
- resources_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data/")
336
- changelog_file = os.path.join(resources_dir, "CHANGELOG_keepachangelog.com.md")
337
-
338
- with runner.isolated_filesystem(temp_dir=tmp_path) as project_root_path:
339
- shutil.copyfile(changelog_file, os.path.join(project_root_path, "CHANGELOG.md"))
340
- result = runner.invoke(
341
- cli,
342
- [
343
- "-f",
344
- "CHANGELOG.md",
345
- "squash",
346
- "--from-version",
347
- "0.0.1",
348
- "--to-version",
349
- "0.3.0",
350
- "-m",
351
- ],
352
- catch_exceptions=False,
353
- )
354
- assert result.exit_code == 0, result.output
355
- snapshot_directory(snapshot=snapshot, directory_path=project_root_path)
356
-
357
-
358
- def test_squash_current(tmp_path, snapshot):
359
- runner = CliRunner()
360
- resources_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data/")
361
- changelog_file = os.path.join(resources_dir, "CHANGELOG_keepachangelog.com.md")
362
-
363
- with runner.isolated_filesystem(temp_dir=tmp_path) as project_root_path:
364
- shutil.copyfile(changelog_file, os.path.join(project_root_path, "CHANGELOG.md"))
365
- result = runner.invoke(
366
- cli,
367
- [
368
- "-f",
369
- "CHANGELOG.md",
370
- "squash",
371
- "--from-version",
372
- "0.0.1",
373
- "-m",
374
- ],
375
- catch_exceptions=False,
376
- )
377
- assert result.exit_code == 0, result.output
378
- snapshot_directory(snapshot=snapshot, directory_path=project_root_path)
379
-
380
-
381
- @pytest.mark.skip(reason="No issue tracker openly available, test locally.")
382
- def test_add_comments(tmp_path):
383
- runner = CliRunner()
384
- root_dir = os.path.join(
385
- os.path.dirname(os.path.realpath(__file__)),
386
- "..",
387
- )
388
- resources_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "data/")
389
- changelog_file = os.path.join(resources_dir, "CHANGELOG_issue_management.md")
390
-
391
- with runner.isolated_filesystem(temp_dir=tmp_path) as project_root_path:
392
- shutil.copyfile(changelog_file, os.path.join(project_root_path, "CHANGELOG.md"))
393
- shutil.copytree(
394
- os.path.join(root_dir, ".git"), os.path.join(project_root_path, ".git")
395
- )
396
- result = runner.invoke(
397
- cli,
398
- [
399
- "-f",
400
- "CHANGELOG.md",
401
- "add-comments",
402
- "1.0.0",
403
- "--jira-username",
404
- os.getenv("JIRA_USERNAME"),
405
- "--jira-password",
406
- os.getenv("JIRA_PASSWORD"),
407
- "--jira-host",
408
- os.getenv("JIRA_HOST"),
409
- "--jira-issue-pattern",
410
- "JIRA-[0-9]+",
411
- "--jira-issue-pattern",
412
- "MYJIRA-[0-9]+",
413
- "--jira-issue-pattern",
414
- "[A-Z]+-[0-9]+",
415
- ],
416
- catch_exceptions=False,
417
- )
418
- assert result.exit_code == 0, result.output
tests/test_kacl.py DELETED
@@ -1,479 +0,0 @@
1
- import os
2
- from unittest import TestCase
3
-
4
- import pytest
5
- import yaml
6
-
7
- import kacl
8
- from kacl.config import KACLConfig
9
- from kacl.exception import KACLException
10
- from tests.snapshot_directory import snapshot_directory
11
-
12
-
13
- class TestKacl(TestCase):
14
- def test_load_valid(self):
15
- changelog_file = os.path.join(
16
- os.path.dirname(os.path.realpath(__file__)), "data/CHANGELOG.md"
17
- )
18
- changelog = kacl.load(changelog_file)
19
-
20
- self.assertEqual(changelog.title(), "Changelog")
21
- self.assertGreater(len(changelog.versions()), 0)
22
-
23
- version = changelog.get("1.0.0")
24
- self.assertIsNotNone(version)
25
-
26
- added_changes = version.changes("Added")
27
- self.assertIsNotNone(added_changes)
28
-
29
- added_items = added_changes.items()
30
- self.assertIsNotNone(added_items)
31
-
32
- def test_dump(self):
33
- changelog_file = os.path.join(
34
- os.path.dirname(os.path.realpath(__file__)), "data/CHANGELOG.md"
35
- )
36
- changelog = kacl.load(changelog_file)
37
- changelog_dump = kacl.dump(changelog)
38
- self.assertIsNotNone(changelog_dump)
39
-
40
- with open(changelog_file, "r") as reference_file:
41
- changelog_reference = reference_file.read()
42
- reference_file.close()
43
-
44
- changelog_dump_lines = changelog_dump.split("\n")
45
- changelog_reference_lines = changelog_reference.split("\n")
46
-
47
- self.assertEqual(len(changelog_dump_lines), len(changelog_reference_lines))
48
- self.assertEqual(changelog_dump, changelog_reference)
49
-
50
- def test_add_change(self):
51
- changelog_file = os.path.join(
52
- os.path.dirname(os.path.realpath(__file__)), "data/CHANGELOG.md"
53
- )
54
-
55
- changelog = kacl.load(changelog_file)
56
-
57
- msg = "This is my first added change"
58
- changelog.add("Added", msg)
59
-
60
- changelog_dump = kacl.dump(changelog)
61
- self.assertIsNotNone(changelog_dump)
62
-
63
- changelog_changed = kacl.parse(changelog_dump)
64
- self.assertIsNotNone(changelog_changed)
65
-
66
- unreleased = changelog_changed.get("Unreleased")
67
- self.assertIsNotNone(unreleased)
68
-
69
- unreleased_change_sections = unreleased.sections()
70
- self.assertIsNotNone(unreleased_change_sections)
71
- self.assertIn("Added", unreleased_change_sections)
72
-
73
- unreleased_changes_added = unreleased.changes("Added")
74
- self.assertIsNotNone(unreleased_changes_added)
75
-
76
- self.assertIn(msg, unreleased_changes_added.items())
77
-
78
- def test_release(self):
79
- valid_files = ["CHANGELOG.md", "CHANGELOG_unrelease_only.md"]
80
-
81
- for filename in valid_files:
82
- changelog_file = os.path.join(
83
- os.path.dirname(os.path.realpath(__file__)), "data", filename
84
- )
85
- changelog = kacl.load(changelog_file)
86
-
87
- msg = "This is my first added change"
88
- changelog.add("Added", msg)
89
-
90
- self.assertTrue(changelog.has_changes())
91
-
92
- changelog.release(version="2.0.0", link="https://my-new-version/2.0.0.html")
93
-
94
- changelog_dump = kacl.dump(changelog)
95
- self.assertIsNotNone(changelog_dump)
96
-
97
- changelog_changed = kacl.parse(changelog_dump)
98
- self.assertIsNotNone(changelog_changed)
99
-
100
- version = changelog_changed.get("2.0.0")
101
- self.assertIsNotNone(version)
102
-
103
- self.assertIn(msg, version.changes("Added").items())
104
-
105
- def test_invalid(self):
106
- invalid_files = [
107
- "CHANGELOG_invalid.md",
108
- "CHANGELOG_missing_sections.md",
109
- "CHANGELOG_no_unreleased.md",
110
- ]
111
-
112
- for filename in invalid_files:
113
- changelog_file = os.path.join(
114
- os.path.dirname(os.path.realpath(__file__)), "data", filename
115
- )
116
- changelog = kacl.load(changelog_file)
117
- self.assertFalse(changelog.is_valid())
118
-
119
- def test_valid(self):
120
- changelog_file = os.path.join(
121
- os.path.dirname(os.path.realpath(__file__)), "data/CHANGELOG.md"
122
- )
123
- changelog = kacl.load(changelog_file)
124
- self.assertTrue(changelog.is_valid())
125
-
126
- validation = changelog.validate()
127
- self.assertGreaterEqual(len(validation.errors()), 0)
128
-
129
- def test_valid_keepachangelogcom(self):
130
- changelog_file = os.path.join(
131
- os.path.dirname(os.path.realpath(__file__)),
132
- "data/CHANGELOG_keepachangelog.com.md",
133
- )
134
- changelog = kacl.load(changelog_file)
135
- self.assertTrue(changelog.is_valid())
136
-
137
- validation = changelog.validate()
138
- self.assertGreaterEqual(len(validation.errors()), 0)
139
-
140
- def test_valid_project_changelog(self):
141
- changelog_file = os.path.join(
142
- os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "CHANGELOG.md"
143
- )
144
- changelog = kacl.load(changelog_file)
145
- self.assertTrue(changelog.is_valid())
146
-
147
- validation = changelog.validate()
148
- self.assertGreaterEqual(len(validation.errors()), 0)
149
-
150
- def test_load_empty(self):
151
- changelog = kacl.parse("")
152
- self.assertFalse(changelog.is_valid())
153
-
154
- def test_release_without_changes(self):
155
- changelog_file = os.path.join(
156
- os.path.dirname(os.path.realpath(__file__)),
157
- "data/CHANGELOG_no_unreleased.md",
158
- )
159
- changelog = kacl.load(changelog_file)
160
-
161
- self.assertFalse(changelog.has_changes())
162
- self.assertRaises(
163
- Exception,
164
- changelog.release,
165
- "1.1.1",
166
- "https://gitlab.com/schmieder.matthias/python-kacl.git/-/compare/v1.0.0...HEAD",
167
- )
168
-
169
- def test_release_existing_version(self):
170
- changelog_file = os.path.join(
171
- os.path.dirname(os.path.realpath(__file__)), "data/CHANGELOG.md"
172
- )
173
- changelog = kacl.load(changelog_file)
174
-
175
- msg = "This is my first added change"
176
- changelog.add("Added", msg)
177
-
178
- self.assertTrue(changelog.has_changes())
179
- self.assertRaises(
180
- Exception,
181
- changelog.release,
182
- "1.0.0",
183
- "https://gitlab.com/schmieder.matthias/python-kacl.git/-/compare/v1.0.0...HEAD",
184
- )
185
-
186
- def test_release_without_older_version(self):
187
- changelog_file = os.path.join(
188
- os.path.dirname(os.path.realpath(__file__)), "data/CHANGELOG.md"
189
- )
190
- changelog = kacl.load(changelog_file)
191
-
192
- msg = "This is my first added change"
193
- changelog.add("Added", msg)
194
-
195
- self.assertTrue(changelog.has_changes())
196
- self.assertRaises(
197
- Exception,
198
- changelog.release,
199
- "0.9.0",
200
- "https://gitlab.com/schmieder.matthias/python-kacl.git/-/compare/v1.0.0...HEAD",
201
- )
202
-
203
- def test_release_with_non_semver(self):
204
- changelog_file = os.path.join(
205
- os.path.dirname(os.path.realpath(__file__)), "data/CHANGELOG.md"
206
- )
207
- changelog = kacl.load(changelog_file)
208
-
209
- msg = "This is my first added change"
210
- changelog.add("Added", msg)
211
-
212
- self.assertTrue(changelog.has_changes())
213
- self.assertRaises(
214
- Exception,
215
- changelog.release,
216
- "a0.9.0",
217
- "https://gitlab.com/schmieder.matthias/python-kacl.git/-/compare/v1.0.0...HEAD",
218
- )
219
-
220
- def test_release_with_allow_no_changes_flag(self):
221
- changelog_file = os.path.join(
222
- os.path.dirname(os.path.realpath(__file__)),
223
- "data/CHANGELOG_without_changes.md",
224
- )
225
- changelog = kacl.load(changelog_file)
226
-
227
- self.assertFalse(changelog.has_changes())
228
- changelog.release("1.0.1", allow_no_changes=True)
229
- self.assertEqual("1.0.1", changelog.current_version())
230
-
231
- def test_release_with_increment(self):
232
- tests = {
233
- "major": "2.0.0",
234
- "minor": "1.1.0",
235
- "patch": "1.0.1",
236
- }
237
- changelog_file = os.path.join(
238
- os.path.dirname(os.path.realpath(__file__)), "data/CHANGELOG.md"
239
- )
240
-
241
- for increment, expected_version in tests.items():
242
- changelog = kacl.load(changelog_file)
243
-
244
- msg = "This is my first added change"
245
- changelog.add("Added", msg)
246
-
247
- self.assertTrue(changelog.has_changes())
248
- changelog.release(increment=increment)
249
- self.assertEqual(expected_version, changelog.current_version())
250
-
251
- fail_tests = {"post": "1.0.0-post.1"}
252
-
253
- for increment, expected_version in fail_tests.items():
254
- changelog = kacl.load(changelog_file)
255
- changelog.config.post_release_version_prefix = None
256
-
257
- msg = "This is my first added change"
258
- changelog.add("Added", msg)
259
-
260
- self.assertTrue(changelog.has_changes())
261
- self.assertRaises(KACLException, changelog.release, increment=increment)
262
-
263
- def test_release_with_increment_extension(self):
264
- tests = {
265
- "major": "2.0.0",
266
- "minor": "1.1.0",
267
- "patch": "1.0.1",
268
- "post": "1.0.0-post.1",
269
- }
270
- changelog_file = os.path.join(
271
- os.path.dirname(os.path.realpath(__file__)), "data/CHANGELOG.md"
272
- )
273
-
274
- for increment, expected_version in tests.items():
275
- changelog = kacl.load(changelog_file)
276
- changelog.config.post_release_version_prefix = "post"
277
-
278
- msg = "This is my first added change"
279
- changelog.add("Added", msg)
280
-
281
- self.assertTrue(changelog.has_changes())
282
- changelog.release(increment=increment)
283
- self.assertEqual(expected_version, changelog.current_version())
284
-
285
- def test_release_with_increment_extension_hotfix(self):
286
- tests = {
287
- "major": "2.0.0",
288
- "minor": "1.1.0",
289
- "patch": "1.0.1",
290
- "post": "1.0.0-hotfix.1",
291
- }
292
- changelog_file = os.path.join(
293
- os.path.dirname(os.path.realpath(__file__)), "data/CHANGELOG.md"
294
- )
295
-
296
- for increment, expected_version in tests.items():
297
- changelog = kacl.load(changelog_file)
298
- changelog.config.post_release_version_prefix = "hotfix"
299
-
300
- msg = "This is my first added change"
301
- changelog.add("Added", msg)
302
-
303
- self.assertTrue(changelog.has_changes())
304
- changelog.release(increment=increment)
305
- self.assertEqual(expected_version, changelog.current_version())
306
-
307
- def test_post_release_with_increment(self):
308
- tests = {
309
- "major": "2.0.0",
310
- "minor": "1.1.0",
311
- "patch": "1.0.1",
312
- "post": "1.0.0-post.2",
313
- }
314
- changelog_file = os.path.join(
315
- os.path.dirname(os.path.realpath(__file__)), "data/CHANGELOG_post.md"
316
- )
317
-
318
- for increment, expected_version in tests.items():
319
- changelog = kacl.load(changelog_file)
320
- changelog.config.post_release_version_prefix = "post"
321
-
322
- msg = "This is my first added change"
323
- changelog.add("Added", msg)
324
-
325
- self.assertTrue(changelog.has_changes())
326
- changelog.release(increment=increment)
327
- self.assertEqual(expected_version, changelog.current_version())
328
-
329
- def test_unreleased_missing_sections(self):
330
- changelog_file = os.path.join(
331
- os.path.dirname(os.path.realpath(__file__)),
332
- "data/CHANGELOG_missing_sections.md",
333
- )
334
-
335
- changelog = kacl.load(changelog_file)
336
- changelog.validate()
337
- self.assertFalse(changelog.is_valid())
338
-
339
- def test_config(self):
340
- config_file = os.path.join(
341
- os.path.dirname(os.path.realpath(__file__)), "data/config.yml"
342
- )
343
- kacl_config = KACLConfig(config_file=config_file)
344
-
345
- default_config = dict()
346
- with open("kacl/config/kacl-default.yml", "r") as f:
347
- default_config = yaml.safe_load(f)["kacl"]
348
-
349
- # changes in config_file
350
- # changelog_file: CHANGELOG.md
351
- # allowed_header_titles:
352
- # - ChangeLog
353
- # allowed_version_sections:
354
- # - Security
355
- # git:
356
- # commit: False
357
-
358
- self.assertNotEqual(
359
- kacl_config.allowed_header_titles, default_config["allowed_header_titles"]
360
- )
361
- self.assertEqual(kacl_config.allowed_header_titles, ["ChangeLog"])
362
-
363
- self.assertNotEqual(
364
- kacl_config.allowed_version_sections,
365
- default_config["allowed_version_sections"],
366
- )
367
- self.assertEqual(kacl_config.allowed_version_sections, ["Security"])
368
-
369
- self.assertNotEqual(
370
- kacl_config.git_create_commit, default_config["git"]["commit"]
371
- )
372
- self.assertEqual(kacl_config.git_create_commit, True)
373
-
374
- def test_link_generation(self):
375
- valid_files = ["CHANGELOG_unrelease_only.md"]
376
-
377
- for filename in valid_files:
378
- changelog_file = os.path.join(
379
- os.path.dirname(os.path.realpath(__file__)), "data", filename
380
- )
381
- changelog = kacl.load(changelog_file)
382
-
383
- changelog = kacl.load(changelog_file)
384
- changelog.generate_links()
385
-
386
- versions = changelog.versions()
387
- for v in versions:
388
- self.assertIsNotNone(v.link())
389
-
390
-
391
- def test_squash(tmp_path, snapshot):
392
- changelog_file = os.path.join(
393
- os.path.dirname(os.path.realpath(__file__)),
394
- "data/CHANGELOG_keepachangelog.com.md",
395
- )
396
- changelog = kacl.load(changelog_file)
397
- assert changelog.is_valid()
398
-
399
- validation = changelog.validate()
400
- assert len(validation.errors()) < 1
401
-
402
- changelog.squash(version_start="0.0.1", version_end="0.3.0", keep_version_info=True)
403
-
404
- squashed_changelog_file = os.path.join(tmp_path, "CHANGELOG.md")
405
- # Open the file for writing.
406
- with open(squashed_changelog_file, "w") as f:
407
- f.write(kacl.dump(changelog))
408
-
409
- snapshot_directory(snapshot=snapshot, directory_path=tmp_path)
410
-
411
-
412
- @pytest.mark.skip(reason="No issue tracker openly available, test locally.")
413
- def test_issue_tracker_comment(tmp_path):
414
- changelog_file = os.path.join(
415
- os.path.dirname(os.path.realpath(__file__)),
416
- "data/CHANGELOG_issue_management.md",
417
- )
418
- changelog = kacl.load(changelog_file)
419
- assert changelog.is_valid()
420
-
421
- changelog.add_comments(version=changelog.current_version())
422
-
423
-
424
- def test_render_comments(tmp_path):
425
- changelog_file = os.path.join(
426
- os.path.dirname(os.path.realpath(__file__)),
427
- "data/CHANGELOG_issue_management.md",
428
- )
429
- changelog = kacl.load(changelog_file)
430
- assert changelog.is_valid()
431
-
432
- rendered_comments = changelog.render_comments(version=changelog.current_version())
433
-
434
- assert "jira" in rendered_comments
435
-
436
-
437
- def test_get_issues(tmp_path):
438
- changelog_file = os.path.join(
439
- os.path.dirname(os.path.realpath(__file__)),
440
- "data/CHANGELOG_issue_management.md",
441
- )
442
- changelog = kacl.load(changelog_file)
443
- assert changelog.is_valid()
444
-
445
- issues = changelog.get_associated_issues(version=changelog.current_version())
446
- assert len(issues["jira"]) == 5
447
-
448
-
449
- def test_simple_metadata(tmp_path):
450
- changelog_file = os.path.join(
451
- os.path.dirname(os.path.realpath(__file__)),
452
- "data/CHANGELOG_with_simple_metadata.md",
453
- )
454
- changelog = kacl.load(changelog_file)
455
- assert changelog.is_valid()
456
-
457
- changelog.release(increment="major")
458
-
459
- content = kacl.dump(changelog)
460
-
461
- assert "---\ntitle: CHANGELOG\n---\n" in str(content)
462
-
463
-
464
- def test_complex_metadata(tmp_path):
465
- changelog_file = os.path.join(
466
- os.path.dirname(os.path.realpath(__file__)),
467
- "data/CHANGELOG_with_complex_metadata.md",
468
- )
469
- changelog = kacl.load(changelog_file)
470
- assert changelog.is_valid()
471
-
472
- changelog.release(increment="major")
473
-
474
- content = kacl.dump(changelog)
475
-
476
- assert (
477
- "---\nlist:\n- entry1\n- additional: true\n key: value\ntitle: CHANGELOG\n---\n"
478
- in str(content)
479
- )