ansys-pre-commit-hooks 0.7.1__tar.gz → 0.7.2__tar.gz

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.
Files changed (33) hide show
  1. {ansys_pre_commit_hooks-0.7.1/src/ansys_pre_commit_hooks.egg-info → ansys_pre_commit_hooks-0.7.2}/PKG-INFO +2 -2
  2. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/pyproject.toml +20 -14
  3. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/setup.py +1 -1
  4. ansys_pre_commit_hooks-0.7.2/src/ansys/pre_commit_hooks/VERSION +1 -0
  5. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys/pre_commit_hooks/add_license_headers.py +28 -18
  6. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2/src/ansys_pre_commit_hooks.egg-info}/PKG-INFO +2 -2
  7. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys_pre_commit_hooks.egg-info/requires.txt +1 -1
  8. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/tests/test_add_license_headers.py +68 -0
  9. ansys_pre_commit_hooks-0.7.1/src/ansys/pre_commit_hooks/VERSION +0 -1
  10. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/LICENSE +0 -0
  11. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/MANIFEST.in +0 -0
  12. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/README.rst +0 -0
  13. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/setup.cfg +0 -0
  14. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys/pre_commit_hooks/__init__.py +0 -0
  15. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys/pre_commit_hooks/assets/.reuse/templates/ansys.jinja2 +0 -0
  16. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys/pre_commit_hooks/assets/LICENSES/Apache-2.0.txt +0 -0
  17. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys/pre_commit_hooks/assets/LICENSES/MIT.txt +0 -0
  18. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys/pre_commit_hooks/assets/licenses.json +0 -0
  19. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys/pre_commit_hooks/tech_review.py +0 -0
  20. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys/pre_commit_hooks/templates/AUTHORS +0 -0
  21. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys/pre_commit_hooks/templates/CODE_OF_CONDUCT.md +0 -0
  22. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys/pre_commit_hooks/templates/CONTRIBUTING.md +0 -0
  23. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys/pre_commit_hooks/templates/CONTRIBUTORS.md +0 -0
  24. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys/pre_commit_hooks/templates/LICENSE +0 -0
  25. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys/pre_commit_hooks/templates/README.md +0 -0
  26. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys/pre_commit_hooks/templates/README.rst +0 -0
  27. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys/pre_commit_hooks/templates/dependabot.yml +0 -0
  28. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys_pre_commit_hooks.egg-info/SOURCES.txt +0 -0
  29. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys_pre_commit_hooks.egg-info/dependency_links.txt +0 -0
  30. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys_pre_commit_hooks.egg-info/entry_points.txt +0 -0
  31. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/src/ansys_pre_commit_hooks.egg-info/top_level.txt +0 -0
  32. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/tests/test_metadata.py +0 -0
  33. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.7.2}/tests/test_tech_review.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ansys-pre-commit-hooks
3
- Version: 0.7.1
3
+ Version: 0.7.2
4
4
  Home-page: https://github.com/ansys/pre-commit-hooks
5
5
  Author: ANSYS, Inc.
6
6
  Author-email: "ANSYS, Inc." <pyansys.core@ansys.com>
@@ -24,7 +24,7 @@ Classifier: Programming Language :: Python :: 3.13
24
24
  Requires-Python: >=3.10,<4
25
25
  Description-Content-Type: text/x-rst
26
26
  License-File: LICENSE
27
- Requires-Dist: GitPython==3.1.46
27
+ Requires-Dist: GitPython==3.1.49
28
28
  Requires-Dist: importlib-metadata==9.0.0
29
29
  Requires-Dist: Jinja2==3.1.6
30
30
  Requires-Dist: reuse==6.2.0
@@ -1,7 +1,7 @@
1
1
  [build-system]
2
2
  requires = [
3
3
  "setuptools>=65.5.1",
4
- "GitPython==3.1.46",
4
+ "GitPython==3.1.49",
5
5
  "Jinja2==3.1.6",
6
6
  "reuse==6.2.0",
7
7
  "requests==2.33.1",
@@ -20,7 +20,7 @@ license-files = ["LICENSE"]
20
20
  authors = [{ name = "ANSYS, Inc.", email = "pyansys.core@ansys.com" }]
21
21
  maintainers = [{ name = "ANSYS, Inc.", email = "pyansys.core@ansys.com" }]
22
22
  dependencies = [
23
- "GitPython==3.1.46",
23
+ "GitPython==3.1.49",
24
24
  "importlib-metadata==9.0.0",
25
25
  "Jinja2==3.1.6",
26
26
  "reuse==6.2.0",
@@ -105,13 +105,13 @@ title_format = "`{version} <https://github.com/ansys/pre-commit-hooks/releases/t
105
105
  issue_format = "`#{issue} <https://github.com/ansys/pre-commit-hooks/pull/{issue}>`_"
106
106
 
107
107
  [[tool.towncrier.type]]
108
- directory = "added"
109
- name = "Added"
108
+ directory = "breaking"
109
+ name = "Breaking"
110
110
  showcontent = true
111
111
 
112
112
  [[tool.towncrier.type]]
113
- directory = "changed"
114
- name = "Changed"
113
+ directory = "added"
114
+ name = "Added"
115
115
  showcontent = true
116
116
 
117
117
  [[tool.towncrier.type]]
@@ -120,26 +120,32 @@ name = "Fixed"
120
120
  showcontent = true
121
121
 
122
122
  [[tool.towncrier.type]]
123
- directory = "dependencies"
124
- name = "Dependencies"
123
+ directory = "documentation"
124
+ name = "Documentation"
125
125
  showcontent = true
126
126
 
127
127
  [[tool.towncrier.type]]
128
- directory = "miscellaneous"
129
- name = "Miscellaneous"
128
+ directory = "dependencies"
129
+ name = "Dependencies"
130
130
  showcontent = true
131
131
 
132
132
  [[tool.towncrier.type]]
133
- directory = "documentation"
134
- name = "Documentation"
133
+ directory = "maintenance"
134
+ name = "Maintenance"
135
135
  showcontent = true
136
136
 
137
137
  [[tool.towncrier.type]]
138
- directory = "maintenance"
139
- name = "Maintenance"
138
+ directory = "miscellaneous"
139
+ name = "Miscellaneous"
140
140
  showcontent = true
141
141
 
142
142
  [[tool.towncrier.type]]
143
143
  directory = "test"
144
144
  name = "Test"
145
145
  showcontent = true
146
+
147
+ [[tool.towncrier.type]]
148
+ directory = "changed"
149
+ name = "Changed"
150
+ showcontent = true
151
+
@@ -39,7 +39,7 @@ setup(
39
39
  url="https://github.com/ansys/pre-commit-hooks",
40
40
  python_requires=">=3.10,<4",
41
41
  install_requires=[
42
- "GitPython==3.1.46",
42
+ "GitPython==3.1.49",
43
43
  "importlib-metadata==9.0.0",
44
44
  "Jinja2==3.1.6",
45
45
  "reuse==6.2.0",
@@ -29,6 +29,7 @@ A license header consists of the Ansys copyright statement and licensing informa
29
29
  import argparse
30
30
  from datetime import date as dt
31
31
  import filecmp
32
+ import io
32
33
  from pathlib import Path
33
34
  import re
34
35
  import shutil
@@ -201,22 +202,31 @@ def update_license_file(
201
202
  template_parent_dir = hook_loc / "assets" / "LICENSES"
202
203
  generate_license_file(template_parent_dir, year_span, repo_license_path, license)
203
204
  else:
204
- # The year regex to match the year or year range in the LICENSE file
205
- year_regex = r"(\d{4}) - (\d{4})|\d{4}"
206
-
207
205
  content = existing_content
208
- # Get the first instance of the year range, either one year or a range of years
209
- year_range_match = re.search(year_regex, content)
210
- # Get the group from the year_range_match
211
- year_range = year_range_match.group()
212
-
213
- # Replace the current year span with the updated year span
214
- if year_range != year_span:
215
- # Update the year span in the LICENSE file. "1" is the max number of replacements
216
- content = re.sub(year_regex, year_span, content, 1)
217
-
218
- with repo_license_path.open(encoding="utf-8", newline="", mode="w") as file:
219
- file.write(content)
206
+ # Match the year (or year range) specifically in the Copyright line.
207
+ # Searching for the first year in the file is incorrect for licenses like
208
+ # Apache-2.0 whose boilerplate contains "January 2004" before the copyright
209
+ # notice, which would otherwise be overwritten with the current year.
210
+ copyright_year_regex = r"(Copyright(?:\s+\(c\))?\s+)((?:\d{4}\s+-\s+)?\d{4})"
211
+ year_range_match = re.search(copyright_year_regex, content)
212
+
213
+ if year_range_match:
214
+ # Get the group from the year_range_match
215
+ year_range = year_range_match.group(2)
216
+
217
+ # Replace the current year span with the updated year span
218
+ if year_range != year_span:
219
+ # Update the year span in the LICENSE file. "1" is the max number of replacements
220
+ content = re.sub(copyright_year_regex, rf"\g<1>{year_span}", content, 1)
221
+
222
+ with repo_license_path.open(encoding="utf-8", newline="", mode="w") as file:
223
+ file.write(content)
224
+ else:
225
+ # No year found in the Copyright line (e.g. "Copyright [yyyy]" placeholder
226
+ # in a stock Apache-2.0 LICENSE). Regenerate the file from the template.
227
+ hook_loc = Path(__file__).parent.resolve()
228
+ template_parent_dir = hook_loc / "assets" / "LICENSES"
229
+ generate_license_file(template_parent_dir, year_span, repo_license_path, license)
220
230
 
221
231
  # If the file changed, print a message that the LICENSE file was changed
222
232
  if not check_same_content(temp_file, repo_license_path):
@@ -507,7 +517,7 @@ def non_recursive_file_check(
507
517
  before_hook = NamedTemporaryFile(mode="w", delete=False).name
508
518
  shutil.copyfile(file, before_hook)
509
519
  _strip_reuse_header(file)
510
- add_header(copyright, license, years, file, template, commented, sys.stdout)
520
+ add_header(copyright, license, years, file, template, commented, io.StringIO())
511
521
  if not check_same_content(before_hook, file):
512
522
  changed_headers = 1
513
523
  print(f"Successfully changed header of {file}")
@@ -673,7 +683,7 @@ def add_header(
673
683
  The template to use for the license header. For example, "ansys.jinja2".
674
684
  commented: bool
675
685
  Whether the template is commented or not.
676
- tmp: Union[NamedTemporaryFile, IO[str]]
686
+ out: Union[NamedTemporaryFile, IO[str]]
677
687
  Temporary file to capture the stdout of the add_header_to_file() function or ``sys.stdout``.
678
688
  """
679
689
  from reuse.cli.annotate import add_header_to_file, get_comment_style, get_reuse_info
@@ -957,7 +967,7 @@ def main():
957
967
  "copyright": args.custom_copyright,
958
968
  "template": args.custom_template,
959
969
  "license": args.custom_license,
960
- "start_year": args.start_year,
970
+ "start_year": int(args.start_year),
961
971
  "current_year": dt.today().year,
962
972
  "git_repo": git_repo,
963
973
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ansys-pre-commit-hooks
3
- Version: 0.7.1
3
+ Version: 0.7.2
4
4
  Home-page: https://github.com/ansys/pre-commit-hooks
5
5
  Author: ANSYS, Inc.
6
6
  Author-email: "ANSYS, Inc." <pyansys.core@ansys.com>
@@ -24,7 +24,7 @@ Classifier: Programming Language :: Python :: 3.13
24
24
  Requires-Python: >=3.10,<4
25
25
  Description-Content-Type: text/x-rst
26
26
  License-File: LICENSE
27
- Requires-Dist: GitPython==3.1.46
27
+ Requires-Dist: GitPython==3.1.49
28
28
  Requires-Dist: importlib-metadata==9.0.0
29
29
  Requires-Dist: Jinja2==3.1.6
30
30
  Requires-Dist: reuse==6.2.0
@@ -1,4 +1,4 @@
1
- GitPython==3.1.46
1
+ GitPython==3.1.49
2
2
  importlib-metadata==9.0.0
3
3
  Jinja2==3.1.6
4
4
  reuse==6.2.0
@@ -950,6 +950,46 @@ def test_mit_header_replaced_with_apache(tmp_path: pytest.TempPathFactory):
950
950
  os.chdir(REPO_PATH)
951
951
 
952
952
 
953
+ @pytest.mark.add_license_headers
954
+ def test_no_duplicate_prints_on_license_switch(
955
+ tmp_path: pytest.TempPathFactory, capsys: pytest.CaptureFixture
956
+ ):
957
+ """Test that switching from MIT to Apache-2.0 prints each changed file exactly once."""
958
+ template_name = "ansys.jinja2"
959
+ license_name = "Apache-2.0.txt"
960
+ template_path = Path(REPO_PATH) / ".reuse" / "templates" / template_name
961
+ license_path = (
962
+ Path(REPO_PATH)
963
+ / "src"
964
+ / "ansys"
965
+ / "pre_commit_hooks"
966
+ / "assets"
967
+ / "LICENSES"
968
+ / license_name
969
+ )
970
+
971
+ repo, tmp_file = set_up_repo(tmp_path, template_path, template_name, license_path, license_name)
972
+
973
+ # First run: add the MIT header
974
+ add_argv_run(repo, tmp_file, [tmp_file])
975
+ repo.index.add([tmp_file])
976
+ capsys.readouterr() # discard output from the MIT-header run
977
+
978
+ # Second run: switch to Apache-2.0 — triggers the license-switch branch
979
+ add_argv_run(repo, tmp_file, [tmp_file, "--custom_license=Apache-2.0"])
980
+
981
+ captured = capsys.readouterr()
982
+ file_lines = [
983
+ line for line in captured.out.splitlines() if "Successfully changed header" in line
984
+ ]
985
+ assert len(file_lines) == 1, (
986
+ f"Expected 'Successfully changed header' to appear exactly once, "
987
+ f"but got {len(file_lines)} time(s):\n{captured.out}"
988
+ )
989
+
990
+ os.chdir(REPO_PATH)
991
+
992
+
953
993
  @pytest.mark.add_license_headers
954
994
  def test_mit_license_file_replaced_with_apache(tmp_path: pytest.TempPathFactory):
955
995
  """Test that LICENSE file is regenerated as Apache-2.0 when it's the custom license."""
@@ -991,6 +1031,34 @@ def test_mit_license_file_replaced_with_apache(tmp_path: pytest.TempPathFactory)
991
1031
  os.chdir(REPO_PATH)
992
1032
 
993
1033
 
1034
+ @pytest.mark.add_license_headers
1035
+ def test_apache_license_year_update_preserves_boilerplate(tmp_path):
1036
+ """Test that updating the year in an Apache-2.0 LICENSE does not corrupt the boilerplate.
1037
+
1038
+ Regression test: the 'January 2004' text in the Apache boilerplate header must not
1039
+ be replaced with the current year when the copyright year is updated.
1040
+ """
1041
+ hook_loc = Path(REPO_PATH) / "src" / "ansys" / "pre_commit_hooks"
1042
+ template_dir = hook_loc / "assets" / "LICENSES"
1043
+ license_file = tmp_path / "LICENSE"
1044
+
1045
+ # Generate an Apache-2.0 LICENSE file with a fixed start year
1046
+ hook.generate_license_file(template_dir, "2023", license_file, "Apache-2.0")
1047
+
1048
+ initial_content = license_file.read_text(encoding="utf-8")
1049
+ assert "January 2004" in initial_content
1050
+ assert "Copyright 2023 ANSYS" in initial_content
1051
+
1052
+ # Simulate a year-span update (e.g., a new calendar year)
1053
+ hook.update_license_file(license_file, "2023 - 2026", "Apache-2.0")
1054
+
1055
+ updated_content = license_file.read_text(encoding="utf-8")
1056
+ assert (
1057
+ "January 2004" in updated_content
1058
+ ), "The Apache boilerplate 'January 2004' must not be overwritten by the year update"
1059
+ assert "Copyright 2023 - 2026 ANSYS" in updated_content
1060
+
1061
+
994
1062
  @pytest.mark.add_license_headers
995
1063
  def test_line_endings(tmp_path: pytest.TempPathFactory):
996
1064
  """Test line endings remain the same before and after running the hook."""