ansys-pre-commit-hooks 0.7.1__tar.gz → 0.8.0__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 → ansys_pre_commit_hooks-0.8.0}/LICENSE +1 -1
  2. {ansys_pre_commit_hooks-0.7.1/src/ansys_pre_commit_hooks.egg-info → ansys_pre_commit_hooks-0.8.0}/PKG-INFO +8 -8
  3. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/pyproject.toml +25 -19
  4. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/setup.py +7 -7
  5. ansys_pre_commit_hooks-0.8.0/src/ansys/pre_commit_hooks/VERSION +1 -0
  6. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys/pre_commit_hooks/__init__.py +1 -1
  7. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys/pre_commit_hooks/add_license_headers.py +135 -42
  8. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys/pre_commit_hooks/assets/LICENSES/Apache-2.0.txt +1 -1
  9. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys/pre_commit_hooks/assets/LICENSES/MIT.txt +1 -1
  10. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys/pre_commit_hooks/tech_review.py +3 -3
  11. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys/pre_commit_hooks/templates/AUTHORS +1 -1
  12. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys/pre_commit_hooks/templates/LICENSE +1 -1
  13. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0/src/ansys_pre_commit_hooks.egg-info}/PKG-INFO +8 -8
  14. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys_pre_commit_hooks.egg-info/requires.txt +3 -3
  15. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/tests/test_add_license_headers.py +209 -8
  16. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/tests/test_metadata.py +1 -1
  17. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/tests/test_tech_review.py +4 -4
  18. ansys_pre_commit_hooks-0.7.1/src/ansys/pre_commit_hooks/VERSION +0 -1
  19. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/MANIFEST.in +0 -0
  20. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/README.rst +0 -0
  21. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/setup.cfg +0 -0
  22. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys/pre_commit_hooks/assets/.reuse/templates/ansys.jinja2 +0 -0
  23. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys/pre_commit_hooks/assets/licenses.json +0 -0
  24. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys/pre_commit_hooks/templates/CODE_OF_CONDUCT.md +0 -0
  25. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys/pre_commit_hooks/templates/CONTRIBUTING.md +0 -0
  26. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys/pre_commit_hooks/templates/CONTRIBUTORS.md +0 -0
  27. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys/pre_commit_hooks/templates/README.md +0 -0
  28. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys/pre_commit_hooks/templates/README.rst +0 -0
  29. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys/pre_commit_hooks/templates/dependabot.yml +0 -0
  30. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys_pre_commit_hooks.egg-info/SOURCES.txt +0 -0
  31. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys_pre_commit_hooks.egg-info/dependency_links.txt +0 -0
  32. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys_pre_commit_hooks.egg-info/entry_points.txt +0 -0
  33. {ansys_pre_commit_hooks-0.7.1 → ansys_pre_commit_hooks-0.8.0}/src/ansys_pre_commit_hooks.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 - 2026 ANSYS, Inc. and/or its affiliates.
3
+ Copyright (c) 2023 - 2026 Synopsys, Inc. and ANSYS, Inc. All rights reserved.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of
6
6
  this software and associated documentation files (the "Software"), to deal in
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ansys-pre-commit-hooks
3
- Version: 0.7.1
3
+ Version: 0.8.0
4
4
  Home-page: https://github.com/ansys/pre-commit-hooks
5
- Author: ANSYS, Inc.
6
- Author-email: "ANSYS, Inc." <pyansys.core@ansys.com>
7
- Maintainer: ANSYS, Inc.
8
- Maintainer-email: "ANSYS, Inc." <pyansys.core@ansys.com>
5
+ Author: Synopsys, Inc. and ANSYS, Inc.
6
+ Author-email: "Synopsys, Inc. and ANSYS, Inc." <pyansys-core@synopsys.com>
7
+ Maintainer: Synopsys, Inc. and ANSYS, Inc.
8
+ Maintainer-email: "Synopsys, Inc. and ANSYS, Inc." <pyansys-core@synopsys.com>
9
9
  License-Expression: MIT
10
10
  Project-URL: Source, https://github.com/ansys/pre-commit-hooks/
11
11
  Project-URL: Issues, https://github.com/ansys/pre-commit-hooks/issues
@@ -24,15 +24,15 @@ 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.50
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
31
- Requires-Dist: requests==2.33.1
31
+ Requires-Dist: requests==2.34.2
32
32
  Requires-Dist: semver==3.0.4
33
33
  Requires-Dist: toml==0.10.2
34
34
  Provides-Extra: doc
35
- Requires-Dist: ansys-sphinx-theme[autoapi]==1.7.2; extra == "doc"
35
+ Requires-Dist: ansys-sphinx-theme[autoapi]==1.8.2; extra == "doc"
36
36
  Requires-Dist: numpydoc==1.10.0; extra == "doc"
37
37
  Requires-Dist: sphinx==8.2.3; extra == "doc"
38
38
  Requires-Dist: sphinx-autodoc-typehints==3.1.0; extra == "doc"
@@ -1,10 +1,10 @@
1
1
  [build-system]
2
2
  requires = [
3
3
  "setuptools>=65.5.1",
4
- "GitPython==3.1.46",
4
+ "GitPython==3.1.50",
5
5
  "Jinja2==3.1.6",
6
6
  "reuse==6.2.0",
7
- "requests==2.33.1",
7
+ "requests==2.34.2",
8
8
  "semver==3.0.4",
9
9
  "toml==0.10.2",
10
10
  "wheel",
@@ -17,14 +17,14 @@ dynamic = ["version", "classifiers", "description", "readme", "scripts"]
17
17
  requires-python = ">=3.10,<4"
18
18
  license = "MIT"
19
19
  license-files = ["LICENSE"]
20
- authors = [{ name = "ANSYS, Inc.", email = "pyansys.core@ansys.com" }]
21
- maintainers = [{ name = "ANSYS, Inc.", email = "pyansys.core@ansys.com" }]
20
+ authors = [{ name = "Synopsys, Inc. and ANSYS, Inc.", email = "pyansys-core@synopsys.com" }]
21
+ maintainers = [{ name = "Synopsys, Inc. and ANSYS, Inc.", email = "pyansys-core@synopsys.com" }]
22
22
  dependencies = [
23
- "GitPython==3.1.46",
23
+ "GitPython==3.1.50",
24
24
  "importlib-metadata==9.0.0",
25
25
  "Jinja2==3.1.6",
26
26
  "reuse==6.2.0",
27
- "requests==2.33.1",
27
+ "requests==2.34.2",
28
28
  "semver==3.0.4",
29
29
  "toml==0.10.2",
30
30
  ]
@@ -47,7 +47,7 @@ classifiers = {file = """
47
47
 
48
48
  [project.optional-dependencies]
49
49
  doc = [
50
- "ansys-sphinx-theme[autoapi]==1.7.2",
50
+ "ansys-sphinx-theme[autoapi]==1.8.2",
51
51
  "numpydoc==1.10.0",
52
52
  "sphinx==8.2.3",
53
53
  "sphinx-autodoc-typehints==3.1.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
+
@@ -22,10 +22,10 @@ setup(
22
22
  description=description,
23
23
  long_description=long_description,
24
24
  license="MIT",
25
- author="ANSYS, Inc.",
26
- author_email="pyansys.core@ansys.com",
27
- maintainer="ANSYS, Inc.",
28
- maintainer_email="pyansys.core@ansys.com",
25
+ author="Synopsys, Inc. and ANSYS, Inc.",
26
+ author_email="pyansys-core@synopsys.com",
27
+ maintainer="Synopsys, Inc. and ANSYS, Inc.",
28
+ maintainer_email="pyansys-core@synopsys.com",
29
29
  classifiers=[
30
30
  "Development Status :: 4 - Beta",
31
31
  "Intended Audience :: Science/Research",
@@ -39,17 +39,17 @@ 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.50",
43
43
  "importlib-metadata==9.0.0",
44
44
  "Jinja2==3.1.6",
45
45
  "reuse==6.2.0",
46
- "requests==2.33.1",
46
+ "requests==2.34.2",
47
47
  "semver==3.0.4",
48
48
  "toml==0.10.2",
49
49
  ],
50
50
  extras_require={
51
51
  "doc": [
52
- "ansys-sphinx-theme[autoapi]==1.7.2",
52
+ "ansys-sphinx-theme[autoapi]==1.8.2",
53
53
  "numpydoc==1.10.0",
54
54
  "sphinx==8.2.3",
55
55
  "sphinx-autodoc-typehints==3.1.0",
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2023 - 2026 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2023 - 2026 Synopsys, Inc. and ANSYS, Inc. All rights reserved.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2023 - 2026 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2023 - 2026 Synopsys, Inc. and ANSYS, Inc. All rights reserved.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -29,6 +29,8 @@ 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
33
+ from logging import Logger
32
34
  from pathlib import Path
33
35
  import re
34
36
  import shutil
@@ -36,16 +38,76 @@ import sys
36
38
  from tempfile import NamedTemporaryFile
37
39
  from typing import IO, Union
38
40
 
41
+ logger = Logger(__name__)
42
+
39
43
  DEFAULT_TEMPLATE = "ansys"
40
44
  """Default template to use for license headers."""
41
- DEFAULT_COPYRIGHT = "ANSYS, Inc. and/or its affiliates."
45
+ DEFAULT_COPYRIGHT = "Synopsys, Inc. and ANSYS, Inc. All rights reserved."
42
46
  """Default copyright line for license headers."""
43
47
  DEFAULT_LICENSE = "MIT"
44
48
  """Default license for headers."""
45
49
  DEFAULT_START_YEAR = dt.today().year
46
- """Default start year for license headers."""
50
+ """Fallback start year used when git history is unavailable."""
47
51
  YEAR_REGEX = r"(\d{4}) - (\d{4})|\d{4}"
48
52
  """Year regex to match year or year range in files."""
53
+ HEADER_PEEK_BYTES = 1024
54
+ """Number of bytes read from the top of a file to check for an existing license header.
55
+
56
+ License headers always appear at the very start of a file and are at most a few hundred
57
+ bytes, so reading only this many bytes avoids loading the full file for every checked file."""
58
+
59
+
60
+ def get_start_year_from_git(git_repo) -> int:
61
+ """Return the year of the first (oldest) commit in the git repository.
62
+
63
+ Uses ``git log --reverse`` to find the oldest commit and extracts its year.
64
+ When the repository is a shallow clone (e.g. ``fetch-depth: 1`` in CI/CD),
65
+ attempts ``git fetch --unshallow`` to retrieve the full history before
66
+ reading the first commit year. If unshallowing fails (no network access,
67
+ no remote configured, etc.) the function continues with the limited history
68
+ that is locally available.
69
+ Falls back to :data:`DEFAULT_START_YEAR` (the current year) when the
70
+ repository has no commits yet.
71
+
72
+ Parameters
73
+ ----------
74
+ git_repo: git.Repo
75
+ The git repository object.
76
+
77
+ Returns
78
+ -------
79
+ int
80
+ The four-digit year of the first commit, or the current year if the
81
+ repository has no commits.
82
+ """
83
+ # Detect shallow clones produced by CI/CD checkouts with fetch-depth: 1.
84
+ # In that case git log --reverse only sees the single fetched commit, not
85
+ # the true first commit in history.
86
+ try:
87
+ is_shallow = git_repo.git.rev_parse("--is-shallow-repository").strip() == "true"
88
+ except Exception:
89
+ # Older git versions (<2.15) do not support --is-shallow-repository;
90
+ # fall back to checking for the presence of the .git/shallow file.
91
+ is_shallow = (Path(git_repo.git_dir) / "shallow").is_file()
92
+
93
+ if is_shallow:
94
+ # Attempt to retrieve the full history so the real first commit is visible.
95
+ try:
96
+ git_repo.git.fetch("--unshallow")
97
+ except Exception as e:
98
+ # Unshallow can fail when there is no network, no remote is configured,
99
+ # or the server does not support it. Continue with whatever history is
100
+ # available locally.
101
+ logger.debug(f"Failure during unshallow: {e}")
102
+ logger.debug("Continuing with limited history available in shallow clone.")
103
+
104
+ # --reverse makes the oldest commit appear first; %ad is the author date
105
+ first_year_str = (
106
+ git_repo.git.log("--reverse", "--format=%ad", "--date=format:%Y").split("\n")[0].strip()
107
+ )
108
+ if first_year_str and first_year_str.isdigit():
109
+ return int(first_year_str)
110
+ return DEFAULT_START_YEAR
49
111
 
50
112
 
51
113
  def set_lint_args(parser: argparse.ArgumentParser) -> argparse.Namespace:
@@ -89,8 +151,11 @@ def set_lint_args(parser: argparse.ArgumentParser) -> argparse.Namespace:
89
151
  parser.add_argument(
90
152
  "--start_year",
91
153
  type=str,
92
- help="Start year for copyright line in headers.",
93
- default=DEFAULT_START_YEAR,
154
+ help=(
155
+ "Start year for copyright line in headers. "
156
+ "When omitted the year of the first git commit is used automatically."
157
+ ),
158
+ default=None,
94
159
  )
95
160
  # Ignore license check by default is False when action='store_true'
96
161
  parser.add_argument("--ignore_license_check", action="store_true")
@@ -201,22 +266,31 @@ def update_license_file(
201
266
  template_parent_dir = hook_loc / "assets" / "LICENSES"
202
267
  generate_license_file(template_parent_dir, year_span, repo_license_path, license)
203
268
  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
269
  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)
270
+ # Match the year (or year range) specifically in the Copyright line.
271
+ # Searching for the first year in the file is incorrect for licenses like
272
+ # Apache-2.0 whose boilerplate contains "January 2004" before the copyright
273
+ # notice, which would otherwise be overwritten with the current year.
274
+ copyright_year_regex = r"(Copyright(?:\s+\(c\))?\s+)((?:\d{4}\s+-\s+)?\d{4})"
275
+ year_range_match = re.search(copyright_year_regex, content)
276
+
277
+ if year_range_match:
278
+ # Get the group from the year_range_match
279
+ year_range = year_range_match.group(2)
280
+
281
+ # Replace the current year span with the updated year span
282
+ if year_range != year_span:
283
+ # Update the year span in the LICENSE file. "1" is the max number of replacements
284
+ content = re.sub(copyright_year_regex, rf"\g<1>{year_span}", content, 1)
285
+
286
+ with repo_license_path.open(encoding="utf-8", newline="", mode="w") as file:
287
+ file.write(content)
288
+ else:
289
+ # No year found in the Copyright line (e.g. "Copyright [yyyy]" placeholder
290
+ # in a stock Apache-2.0 LICENSE). Regenerate the file from the template.
291
+ hook_loc = Path(__file__).parent.resolve()
292
+ template_parent_dir = hook_loc / "assets" / "LICENSES"
293
+ generate_license_file(template_parent_dir, year_span, repo_license_path, license)
220
294
 
221
295
  # If the file changed, print a message that the LICENSE file was changed
222
296
  if not check_same_content(temp_file, repo_license_path):
@@ -361,7 +435,8 @@ def _has_current_header(file_path: str, copyright: list, years: str) -> bool:
361
435
  file_path: str
362
436
  Path to the file to check.
363
437
  copyright: list
364
- List containing the copyright string. For example, ["ANSYS, Inc. and/or its affiliates."].
438
+ List containing the copyright string. For example,
439
+ ["Synopsys, Inc. and ANSYS, Inc. All rights reserved."].
365
440
  years: str
366
441
  The expected year span. For example, "2023 - 2026" or "2026".
367
442
 
@@ -373,7 +448,7 @@ def _has_current_header(file_path: str, copyright: list, years: str) -> bool:
373
448
  """
374
449
  try:
375
450
  with Path(file_path).open(encoding="utf-8", errors="ignore") as f:
376
- head = f.read(1024)
451
+ head = f.read(HEADER_PEEK_BYTES)
377
452
  except OSError:
378
453
  return False
379
454
 
@@ -400,7 +475,7 @@ def _file_has_license(file_path: str, license: str) -> bool:
400
475
  """
401
476
  try:
402
477
  with Path(file_path).open(encoding="utf-8", errors="ignore") as f:
403
- head = f.read(1024)
478
+ head = f.read(HEADER_PEEK_BYTES)
404
479
  except OSError:
405
480
  return False
406
481
 
@@ -501,13 +576,20 @@ def non_recursive_file_check(
501
576
  add_header(copyright, license, years, file, template, commented, sys.stdout)
502
577
  else:
503
578
  # Check whether the existing SPDX-License-Identifier differs from the
504
- # requested license. If so, strip the old header and write a fresh one
505
- # so that the old identifier is fully replaced rather than merged.
506
- if not existing_license_matches:
579
+ # requested license, or whether the copyright holder phrase has changed.
580
+ # In either case, strip the old header and write a fresh one so that the
581
+ # old lines are fully replaced rather than merged by REUSE's annotate.
582
+ try:
583
+ with Path(file).open(encoding="utf-8", errors="ignore") as _f:
584
+ _head = _f.read(HEADER_PEEK_BYTES)
585
+ except OSError:
586
+ _head = ""
587
+ copyright_holder_changed = copyright[0] not in _head
588
+ if not existing_license_matches or copyright_holder_changed:
507
589
  before_hook = NamedTemporaryFile(mode="w", delete=False).name
508
590
  shutil.copyfile(file, before_hook)
509
591
  _strip_reuse_header(file)
510
- add_header(copyright, license, years, file, template, commented, sys.stdout)
592
+ add_header(copyright, license, years, file, template, commented, io.StringIO())
511
593
  if not check_same_content(before_hook, file):
512
594
  changed_headers = 1
513
595
  print(f"Successfully changed header of {file}")
@@ -575,7 +657,8 @@ def update_header(
575
657
  file: str
576
658
  The file whose header is being updated.
577
659
  copyright: str
578
- The copyright string of the header. For example, "ANSYS, Inc. and/or its affiliates."
660
+ The copyright string of the header. For example,
661
+ "Synopsys, Inc. and ANSYS, Inc. All rights reserved."
579
662
  license: str
580
663
  The license of the header. For example, "MIT".
581
664
  years: str
@@ -662,7 +745,7 @@ def add_header(
662
745
  ----------
663
746
  copyright: str
664
747
  The copyright line for the license header. For example,
665
- "ANSYS, Inc. and/or its affiliates."
748
+ "Synopsys, Inc. and ANSYS, Inc. All rights reserved."
666
749
  license: str
667
750
  The license for the license header. For example, "MIT".
668
751
  years: str
@@ -673,7 +756,7 @@ def add_header(
673
756
  The template to use for the license header. For example, "ansys.jinja2".
674
757
  commented: bool
675
758
  Whether the template is commented or not.
676
- tmp: Union[NamedTemporaryFile, IO[str]]
759
+ out: Union[NamedTemporaryFile, IO[str]]
677
760
  Temporary file to capture the stdout of the add_header_to_file() function or ``sys.stdout``.
678
761
  """
679
762
  from reuse.cli.annotate import add_header_to_file, get_comment_style, get_reuse_info
@@ -932,17 +1015,6 @@ def main():
932
1015
  # Set changed_headers to zero by default
933
1016
  changed_headers = 0
934
1017
 
935
- # Check start_year is valid
936
- if str(args.start_year).isdigit():
937
- # Check the start year is not later than the current year
938
- if int(args.start_year) > dt.today().year:
939
- raise Exception("Please provide a start year less than or equal to the current year.")
940
- # Check the start year isn't earlier than when computers were created :)
941
- elif int(args.start_year) < 1942:
942
- raise Exception("Please provide a start year greater than or equal to 1942.")
943
- else:
944
- raise Exception("Please ensure the start year is a number.")
945
-
946
1018
  import git
947
1019
 
948
1020
  # Get root directory of the git repository.
@@ -950,6 +1022,27 @@ def main():
950
1022
  # Get the root of the git repository and fix the line separators
951
1023
  git_root = Path(git_repo.git.rev_parse("--show-toplevel"))
952
1024
 
1025
+ # Determine the start year.
1026
+ # When --start_year is explicitly provided, validate and use that value.
1027
+ # Otherwise, auto-detect from the year of the first git commit so that the
1028
+ # original copyright year is never accidentally erased.
1029
+ if args.start_year is not None:
1030
+ if str(args.start_year).isdigit():
1031
+ # Check the start year is not later than the current year
1032
+ if int(args.start_year) > dt.today().year:
1033
+ raise Exception(
1034
+ "Please provide a start year less than or equal to the current year."
1035
+ )
1036
+ # Check the start year isn't earlier than when computers were created :)
1037
+ elif int(args.start_year) < 1942:
1038
+ raise Exception("Please provide a start year greater than or equal to 1942.")
1039
+ else:
1040
+ raise Exception("Please ensure the start year is a number.")
1041
+ start_year = int(args.start_year)
1042
+ else:
1043
+ # Auto-detect: use the year of the repository's first commit
1044
+ start_year = get_start_year_from_git(git_repo)
1045
+
953
1046
  # Create dictionary containing the committed files, custom copyright,
954
1047
  # template, license, changed_headers, year, and git_repo
955
1048
  values = {
@@ -957,7 +1050,7 @@ def main():
957
1050
  "copyright": args.custom_copyright,
958
1051
  "template": args.custom_template,
959
1052
  "license": args.custom_license,
960
- "start_year": args.start_year,
1053
+ "start_year": start_year,
961
1054
  "current_year": dt.today().year,
962
1055
  "git_repo": git_repo,
963
1056
  }
@@ -187,7 +187,7 @@
187
187
  same "printed page" as the copyright notice for easier
188
188
  identification within third-party archives.
189
189
 
190
- Copyright {{ year_span }} ANSYS, Inc. and/or its affiliates.
190
+ Copyright {{ year_span }} Synopsys, Inc. and ANSYS, Inc. All rights reserved.
191
191
 
192
192
  Licensed under the Apache License, Version 2.0 (the "License");
193
193
  you may not use this file except in compliance with the License.
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) {{ year_span }} ANSYS, Inc. and/or its affiliates.
3
+ Copyright (c) {{ year_span }} Synopsys, Inc. and ANSYS, Inc. All rights reserved.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of
6
6
  this software and associated documentation files (the "Software"), to deal in
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2023 - 2026 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2023 - 2026 Synopsys, Inc. and ANSYS, Inc. All rights reserved.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -37,10 +37,10 @@ HOOK_PATH = pathlib.Path(__file__).parent.resolve()
37
37
  LICENSES_JSON = HOOK_PATH / "assets" / "licenses.json"
38
38
  """JSON file containing licenses information."""
39
39
 
40
- DEFAULT_AUTHOR_MAINT_NAME = "ANSYS, Inc."
40
+ DEFAULT_AUTHOR_MAINT_NAME = "Synopsys, Inc. and ANSYS, Inc."
41
41
  """Default name of project authors and maintainers."""
42
42
 
43
- DEFAULT_AUTHOR_MAINT_EMAIL = "pyansys.core@ansys.com"
43
+ DEFAULT_AUTHOR_MAINT_EMAIL = "pyansys-core@synopsys.com"
44
44
  """Default email of project authors and maintainers."""
45
45
 
46
46
  DEFAULT_START_YEAR = dt.today().year
@@ -9,4 +9,4 @@
9
9
  # submit a request.
10
10
  #
11
11
  #
12
- ANSYS, Inc.
12
+ Synopsys, Inc. and ANSYS, Inc.
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) {{ year_span }} ANSYS, Inc. and/or its affiliates.
3
+ Copyright (c) {{ year_span }} Synopsys, Inc. and ANSYS, Inc. All rights reserved.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of
6
6
  this software and associated documentation files (the "Software"), to deal in
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ansys-pre-commit-hooks
3
- Version: 0.7.1
3
+ Version: 0.8.0
4
4
  Home-page: https://github.com/ansys/pre-commit-hooks
5
- Author: ANSYS, Inc.
6
- Author-email: "ANSYS, Inc." <pyansys.core@ansys.com>
7
- Maintainer: ANSYS, Inc.
8
- Maintainer-email: "ANSYS, Inc." <pyansys.core@ansys.com>
5
+ Author: Synopsys, Inc. and ANSYS, Inc.
6
+ Author-email: "Synopsys, Inc. and ANSYS, Inc." <pyansys-core@synopsys.com>
7
+ Maintainer: Synopsys, Inc. and ANSYS, Inc.
8
+ Maintainer-email: "Synopsys, Inc. and ANSYS, Inc." <pyansys-core@synopsys.com>
9
9
  License-Expression: MIT
10
10
  Project-URL: Source, https://github.com/ansys/pre-commit-hooks/
11
11
  Project-URL: Issues, https://github.com/ansys/pre-commit-hooks/issues
@@ -24,15 +24,15 @@ 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.50
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
31
- Requires-Dist: requests==2.33.1
31
+ Requires-Dist: requests==2.34.2
32
32
  Requires-Dist: semver==3.0.4
33
33
  Requires-Dist: toml==0.10.2
34
34
  Provides-Extra: doc
35
- Requires-Dist: ansys-sphinx-theme[autoapi]==1.7.2; extra == "doc"
35
+ Requires-Dist: ansys-sphinx-theme[autoapi]==1.8.2; extra == "doc"
36
36
  Requires-Dist: numpydoc==1.10.0; extra == "doc"
37
37
  Requires-Dist: sphinx==8.2.3; extra == "doc"
38
38
  Requires-Dist: sphinx-autodoc-typehints==3.1.0; extra == "doc"
@@ -1,13 +1,13 @@
1
- GitPython==3.1.46
1
+ GitPython==3.1.50
2
2
  importlib-metadata==9.0.0
3
3
  Jinja2==3.1.6
4
4
  reuse==6.2.0
5
- requests==2.33.1
5
+ requests==2.34.2
6
6
  semver==3.0.4
7
7
  toml==0.10.2
8
8
 
9
9
  [doc]
10
- ansys-sphinx-theme[autoapi]==1.7.2
10
+ ansys-sphinx-theme[autoapi]==1.8.2
11
11
  numpydoc==1.10.0
12
12
  sphinx==8.2.3
13
13
  sphinx-autodoc-typehints==3.1.0
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2023 - 2026 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2023 - 2026 Synopsys, Inc. and ANSYS, Inc. All rights reserved.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -37,7 +37,7 @@ import ansys.pre_commit_hooks.add_license_headers as hook
37
37
  git_repo = git.Repo(Path.cwd(), search_parent_directories=True)
38
38
  REPO_PATH = git_repo.git.rev_parse("--show-toplevel")
39
39
  START_YEAR = "2023"
40
- DEFAULT_COPYRIGHT = "ANSYS, Inc. and/or its affiliates."
40
+ DEFAULT_COPYRIGHT = "Synopsys, Inc. and ANSYS, Inc. All rights reserved."
41
41
 
42
42
 
43
43
  def set_up_repo(tmp_path, template_path, template_name, license_path, license_name):
@@ -129,7 +129,7 @@ def check_ansys_header(file_name):
129
129
  for line in file:
130
130
  count += 1
131
131
  if count == 1:
132
- assert "ANSYS, Inc. and/or its affiliates" in line
132
+ assert "Synopsys, Inc. and ANSYS, Inc." in line
133
133
  if count == 2:
134
134
  assert "MIT" in line
135
135
  if count == 5:
@@ -189,7 +189,7 @@ def test_start_year_same_as_current(tmp_path: pytest.TempPathFactory):
189
189
  count += 1
190
190
  # Assert the copyright line's time range is from 2023 to the current year
191
191
  if count == 1:
192
- assert f"Copyright (C) {dt.today().year} ANSYS, Inc." in line
192
+ assert f"Copyright (C) {dt.today().year} Synopsys, Inc. and ANSYS, Inc." in line
193
193
  if count > 1:
194
194
  break
195
195
 
@@ -356,7 +356,7 @@ def test_no_license_check(tmp_path: pytest.TempPathFactory):
356
356
  count += 1
357
357
  # Assert that only the copyright line is in the file
358
358
  if count == 1:
359
- assert "ANSYS, Inc. and/or its affiliates" in line
359
+ assert "Synopsys, Inc. and ANSYS, Inc." in line
360
360
  if count == 2:
361
361
  assert "MIT" not in line
362
362
  if count == 5:
@@ -735,6 +735,81 @@ def test_license_year_update(tmp_path: pytest.TempPathFactory):
735
735
  os.chdir(REPO_PATH)
736
736
 
737
737
 
738
+ @pytest.mark.add_license_headers
739
+ def test_get_start_year_from_git_new_repo(tmp_path: pytest.TempPathFactory):
740
+ """Test that get_start_year_from_git returns the current year for a brand-new repo."""
741
+ os.chdir(tmp_path)
742
+ repo = init_repo(tmp_path)
743
+ year = hook.get_start_year_from_git(repo)
744
+ assert year == dt.today().year
745
+ os.chdir(REPO_PATH)
746
+
747
+
748
+ @pytest.mark.add_license_headers
749
+ def test_get_start_year_from_git_detects_first_commit_year(tmp_path: pytest.TempPathFactory):
750
+ """Test that get_start_year_from_git returns the year of the *first* commit.
751
+
752
+ Creates a repo with a backdated initial commit so the result is deterministic
753
+ regardless of when the test suite is run.
754
+ """
755
+ from datetime import datetime
756
+
757
+ os.chdir(tmp_path)
758
+ git.Repo.init(tmp_path)
759
+ repo = git.Repo(tmp_path)
760
+
761
+ # Back-dated initial commit — gitpython requires timezone-aware datetimes
762
+ from datetime import timezone
763
+
764
+ old_date = datetime(2020, 6, 15, tzinfo=timezone.utc)
765
+ readme = tmp_path / "README.md"
766
+ readme.write_text("initial")
767
+ repo.index.add([str(readme)])
768
+ repo.index.commit("initial commit", author_date=old_date, commit_date=old_date)
769
+
770
+ # A more recent commit — must not affect the result
771
+ readme.write_text("updated")
772
+ repo.index.add([str(readme)])
773
+ repo.index.commit("recent commit")
774
+
775
+ year = hook.get_start_year_from_git(repo)
776
+ assert year == 2020
777
+
778
+ os.chdir(REPO_PATH)
779
+
780
+
781
+ @pytest.mark.add_license_headers
782
+ def test_start_year_autodetected_from_git(tmp_path: pytest.TempPathFactory):
783
+ """End-to-end test: when --start_year is omitted the hook uses the first commit year.
784
+
785
+ A fresh repo is initialised so the first commit year equals the current year.
786
+ Running the hook without ``--start_year`` should therefore produce a copyright
787
+ line that contains only the current year (no range).
788
+ """
789
+ template_name = "ansys.jinja2"
790
+ license_name = "MIT.txt"
791
+ template_path = Path(REPO_PATH) / ".reuse" / "templates" / template_name
792
+ license_path = Path(REPO_PATH) / "LICENSES" / license_name
793
+
794
+ os.chdir(tmp_path)
795
+ repo, tmp_file = set_up_repo(tmp_path, template_path, template_name, license_path, license_name)
796
+
797
+ # Run the hook with NO --start_year argument
798
+ assert add_argv_run(repo, tmp_file, [tmp_file]) == 1
799
+
800
+ with open(tmp_file, "r") as f:
801
+ first_line = f.readline()
802
+
803
+ # New repo: first commit is in the current year, so the copyright should
804
+ # contain only the current year (no multi-year range).
805
+ assert (
806
+ f"Copyright (C) {dt.today().year} Synopsys, Inc. and ANSYS, Inc. All rights reserved."
807
+ in first_line
808
+ )
809
+
810
+ os.chdir(REPO_PATH)
811
+
812
+
738
813
  @pytest.mark.add_license_headers
739
814
  def test_date_update(tmp_path: pytest.TempPathFactory):
740
815
  """Test the date is correctly updated in the license header."""
@@ -755,11 +830,17 @@ def test_date_update(tmp_path: pytest.TempPathFactory):
755
830
  years = ["2022", "2023", str(dt.today().year)]
756
831
 
757
832
  # Check the copyright line has "2023 - {current_year}", "2022 - {current_year}"
758
- # and "{current_year}"
833
+ # and "{current_year}" (contained within the preserved range)
759
834
  for year in years:
760
835
  custom_args = [tmp_file, f"--start_year={year}"]
761
836
  # Git add tmp_file and run hook with custom arguments
762
- assert add_argv_run(repo, tmp_file, custom_args) == 1
837
+ result = add_argv_run(repo, tmp_file, custom_args)
838
+ # When the start year differs from the current year the hook must update the
839
+ # header (return code 1). When start_year equals the current year and files
840
+ # already have the current year as their end year (set during earlier
841
+ # iterations), the hook preserves the existing range and returns 0.
842
+ if str(year) != str(dt.today().year):
843
+ assert result == 1
763
844
  # Check the license year is correctly updated
764
845
  check_license_year(tmp_file, DEFAULT_COPYRIGHT, year, str(dt.today().year))
765
846
  # Add file with updated header
@@ -868,7 +949,7 @@ def check_apache_header(file_name):
868
949
  """Check file contains all Apache-2.0 copyright and license header components."""
869
950
  with open(file_name, "r", encoding="utf8") as file:
870
951
  content = file.read()
871
- assert "ANSYS, Inc. and/or its affiliates" in content
952
+ assert "Synopsys, Inc. and ANSYS, Inc." in content
872
953
  assert "Apache-2.0" in content
873
954
  assert "Apache License, Version 2.0" in content
874
955
  assert "http://www.apache.org/licenses/LICENSE-2.0" in content
@@ -950,6 +1031,46 @@ def test_mit_header_replaced_with_apache(tmp_path: pytest.TempPathFactory):
950
1031
  os.chdir(REPO_PATH)
951
1032
 
952
1033
 
1034
+ @pytest.mark.add_license_headers
1035
+ def test_no_duplicate_prints_on_license_switch(
1036
+ tmp_path: pytest.TempPathFactory, capsys: pytest.CaptureFixture
1037
+ ):
1038
+ """Test that switching from MIT to Apache-2.0 prints each changed file exactly once."""
1039
+ template_name = "ansys.jinja2"
1040
+ license_name = "Apache-2.0.txt"
1041
+ template_path = Path(REPO_PATH) / ".reuse" / "templates" / template_name
1042
+ license_path = (
1043
+ Path(REPO_PATH)
1044
+ / "src"
1045
+ / "ansys"
1046
+ / "pre_commit_hooks"
1047
+ / "assets"
1048
+ / "LICENSES"
1049
+ / license_name
1050
+ )
1051
+
1052
+ repo, tmp_file = set_up_repo(tmp_path, template_path, template_name, license_path, license_name)
1053
+
1054
+ # First run: add the MIT header
1055
+ add_argv_run(repo, tmp_file, [tmp_file])
1056
+ repo.index.add([tmp_file])
1057
+ capsys.readouterr() # discard output from the MIT-header run
1058
+
1059
+ # Second run: switch to Apache-2.0 — triggers the license-switch branch
1060
+ add_argv_run(repo, tmp_file, [tmp_file, "--custom_license=Apache-2.0"])
1061
+
1062
+ captured = capsys.readouterr()
1063
+ file_lines = [
1064
+ line for line in captured.out.splitlines() if "Successfully changed header" in line
1065
+ ]
1066
+ assert len(file_lines) == 1, (
1067
+ f"Expected 'Successfully changed header' to appear exactly once, "
1068
+ f"but got {len(file_lines)} time(s):\n{captured.out}"
1069
+ )
1070
+
1071
+ os.chdir(REPO_PATH)
1072
+
1073
+
953
1074
  @pytest.mark.add_license_headers
954
1075
  def test_mit_license_file_replaced_with_apache(tmp_path: pytest.TempPathFactory):
955
1076
  """Test that LICENSE file is regenerated as Apache-2.0 when it's the custom license."""
@@ -991,6 +1112,34 @@ def test_mit_license_file_replaced_with_apache(tmp_path: pytest.TempPathFactory)
991
1112
  os.chdir(REPO_PATH)
992
1113
 
993
1114
 
1115
+ @pytest.mark.add_license_headers
1116
+ def test_apache_license_year_update_preserves_boilerplate(tmp_path):
1117
+ """Test that updating the year in an Apache-2.0 LICENSE does not corrupt the boilerplate.
1118
+
1119
+ Regression test: the 'January 2004' text in the Apache boilerplate header must not
1120
+ be replaced with the current year when the copyright year is updated.
1121
+ """
1122
+ hook_loc = Path(REPO_PATH) / "src" / "ansys" / "pre_commit_hooks"
1123
+ template_dir = hook_loc / "assets" / "LICENSES"
1124
+ license_file = tmp_path / "LICENSE"
1125
+
1126
+ # Generate an Apache-2.0 LICENSE file with a fixed start year
1127
+ hook.generate_license_file(template_dir, "2023", license_file, "Apache-2.0")
1128
+
1129
+ initial_content = license_file.read_text(encoding="utf-8")
1130
+ assert "January 2004" in initial_content
1131
+ assert "Copyright 2023 Synopsys, Inc. and ANSYS, Inc." in initial_content
1132
+
1133
+ # Simulate a year-span update (e.g., a new calendar year)
1134
+ hook.update_license_file(license_file, "2023 - 2026", "Apache-2.0")
1135
+
1136
+ updated_content = license_file.read_text(encoding="utf-8")
1137
+ assert (
1138
+ "January 2004" in updated_content
1139
+ ), "The Apache boilerplate 'January 2004' must not be overwritten by the year update"
1140
+ assert "Copyright 2023 - 2026 Synopsys, Inc. and ANSYS, Inc." in updated_content
1141
+
1142
+
994
1143
  @pytest.mark.add_license_headers
995
1144
  def test_line_endings(tmp_path: pytest.TempPathFactory):
996
1145
  """Test line endings remain the same before and after running the hook."""
@@ -1023,3 +1172,55 @@ def test_line_endings(tmp_path: pytest.TempPathFactory):
1023
1172
  assert license_line_endings_before == get_line_endings(tmp_license)
1024
1173
 
1025
1174
  os.chdir(REPO_PATH)
1175
+
1176
+
1177
+ @pytest.mark.add_license_headers
1178
+ def test_copyright_holder_change_replaces_not_duplicates(tmp_path: pytest.TempPathFactory):
1179
+ """Test that changing the copyright holder replaces the old line instead of adding a new one.
1180
+
1181
+ Regression test: when a file already has a valid header with the *old* copyright phrase
1182
+ (e.g. 'ANSYS, Inc. and/or its affiliates.') and the hook is re-run with a new phrase
1183
+ (e.g. 'Synopsys, Inc. and ANSYS, Inc. All rights reserved.'), the header must be
1184
+ fully replaced — not duplicated — so only one copyright line exists in the file.
1185
+ """
1186
+ template_name = "ansys.jinja2"
1187
+ license_name = "MIT.txt"
1188
+ template_path = Path(REPO_PATH) / ".reuse" / "templates" / template_name
1189
+ license_path = Path(REPO_PATH) / "LICENSES" / license_name
1190
+
1191
+ repo, tmp_file = set_up_repo(tmp_path, template_path, template_name, license_path, license_name)
1192
+
1193
+ old_copyright = "ANSYS, Inc. and/or its affiliates."
1194
+ new_copyright = "Synopsys, Inc. and ANSYS, Inc. All rights reserved."
1195
+
1196
+ # First run: add header with the *old* copyright phrase
1197
+ old_args = [tmp_file, f"--custom_copyright={old_copyright}"]
1198
+ assert add_argv_run(repo, tmp_file, old_args) == 1
1199
+ repo.index.add([tmp_file])
1200
+
1201
+ with open(tmp_file, "r", encoding="utf-8") as f:
1202
+ content_after_first_run = f.read()
1203
+ assert old_copyright in content_after_first_run
1204
+ assert new_copyright not in content_after_first_run
1205
+
1206
+ # Second run: re-run with the new copyright phrase (default)
1207
+ new_args = [tmp_file, f"--custom_copyright={new_copyright}"]
1208
+ assert add_argv_run(repo, tmp_file, new_args) == 1
1209
+
1210
+ with open(tmp_file, "r", encoding="utf-8") as f:
1211
+ content_after_second_run = f.read()
1212
+
1213
+ # The new phrase must be present
1214
+ assert new_copyright in content_after_second_run
1215
+ # The old phrase must be gone
1216
+ assert old_copyright not in content_after_second_run
1217
+ # Exactly one copyright line (no duplicates)
1218
+ copyright_line_count = sum(
1219
+ 1 for line in content_after_second_run.splitlines() if "Copyright" in line
1220
+ )
1221
+ assert copyright_line_count == 1, (
1222
+ f"Expected exactly 1 copyright line, found {copyright_line_count}:\n"
1223
+ f"{content_after_second_run}"
1224
+ )
1225
+
1226
+ os.chdir(REPO_PATH)
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2023 - 2026 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2023 - 2026 Synopsys, Inc. and ANSYS, Inc. All rights reserved.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -1,4 +1,4 @@
1
- # Copyright (C) 2023 - 2026 ANSYS, Inc. and/or its affiliates.
1
+ # Copyright (C) 2023 - 2026 Synopsys, Inc. and ANSYS, Inc. All rights reserved.
2
2
  # SPDX-License-Identifier: MIT
3
3
  #
4
4
  #
@@ -96,8 +96,8 @@ def run_main(custom_args):
96
96
  @pytest.mark.tech_review
97
97
  def test_pyproject_toml(tmp_path: pytest.TempPathFactory):
98
98
  """Test pyproject.toml retrieves all information."""
99
- author_maint_name = "ANSYS, Inc."
100
- author_maint_email = "pyansys.core@ansys.com"
99
+ author_maint_name = "Synopsys, Inc. and ANSYS, Inc."
100
+ author_maint_email = "pyansys-core@synopsys.com"
101
101
  is_compliant = True
102
102
  non_compliant_name = False
103
103
 
@@ -282,7 +282,7 @@ def test_bad_author_maint_name_email(tmp_path: pytest.TempPathFactory, capsys):
282
282
  setup_repo(tmp_path)
283
283
 
284
284
  # Remove name and email from author and maintainer in pyproject.toml
285
- search = '{name = "ANSYS, Inc.", email = "pyansys.core@ansys.com"},'
285
+ search = '{name = "Synopsys, Inc. and ANSYS, Inc.", email = "pyansys-core@synopsys.com"},'
286
286
  replace = "{},"
287
287
  replace_line(tmp_path, "pyproject.toml", search, replace)
288
288