github-haystack 1.2.1__tar.gz → 2.1.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 (49) hide show
  1. {github_haystack-1.2.1 → github_haystack-2.1.0}/CHANGELOG.md +26 -1
  2. {github_haystack-1.2.1 → github_haystack-2.1.0}/PKG-INFO +4 -4
  3. github_haystack-2.1.0/pydoc/config_docusaurus.yml +18 -0
  4. {github_haystack-1.2.1 → github_haystack-2.1.0}/pyproject.toml +19 -12
  5. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/components/connectors/github/file_editor.py +16 -16
  6. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/components/connectors/github/issue_commenter.py +4 -4
  7. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/components/connectors/github/issue_viewer.py +6 -6
  8. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/components/connectors/github/pr_creator.py +11 -6
  9. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/components/connectors/github/repo_forker.py +5 -5
  10. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/components/connectors/github/repo_viewer.py +10 -10
  11. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/tools/github/file_editor_tool.py +12 -11
  12. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/tools/github/issue_commenter_tool.py +11 -10
  13. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/tools/github/issue_viewer_tool.py +12 -11
  14. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/tools/github/pr_creator_tool.py +11 -10
  15. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/tools/github/repo_forker_tool.py +11 -10
  16. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/tools/github/repo_viewer_tool.py +13 -12
  17. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/tools/github/utils.py +9 -8
  18. {github_haystack-1.2.1 → github_haystack-2.1.0}/tests/test_file_editor.py +91 -0
  19. {github_haystack-1.2.1 → github_haystack-2.1.0}/tests/test_file_editor_tool.py +14 -5
  20. {github_haystack-1.2.1 → github_haystack-2.1.0}/tests/test_issue_commenter_tool.py +8 -8
  21. {github_haystack-1.2.1 → github_haystack-2.1.0}/tests/test_issue_viewer_tool.py +8 -8
  22. {github_haystack-1.2.1 → github_haystack-2.1.0}/tests/test_pr_creator.py +79 -0
  23. {github_haystack-1.2.1 → github_haystack-2.1.0}/tests/test_pr_creator_tool.py +8 -8
  24. {github_haystack-1.2.1 → github_haystack-2.1.0}/tests/test_repo_forker.py +54 -0
  25. {github_haystack-1.2.1 → github_haystack-2.1.0}/tests/test_repo_forker_tool.py +9 -9
  26. {github_haystack-1.2.1 → github_haystack-2.1.0}/tests/test_repo_viewer.py +49 -0
  27. {github_haystack-1.2.1 → github_haystack-2.1.0}/tests/test_repo_viewer_tool.py +4 -4
  28. github_haystack-2.1.0/tests/test_utils.py +63 -0
  29. github_haystack-1.2.1/pydoc/config.yml +0 -34
  30. {github_haystack-1.2.1 → github_haystack-2.1.0}/.gitignore +0 -0
  31. {github_haystack-1.2.1 → github_haystack-2.1.0}/LICENSE.txt +0 -0
  32. {github_haystack-1.2.1 → github_haystack-2.1.0}/README.md +0 -0
  33. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/components/connectors/github/__init__.py +0 -0
  34. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/components/connectors/py.typed +0 -0
  35. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/prompts/github/__init__.py +0 -0
  36. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/prompts/github/context_prompt.py +0 -0
  37. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/prompts/github/file_editor_prompt.py +0 -0
  38. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/prompts/github/issue_commenter_prompt.py +0 -0
  39. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/prompts/github/issue_viewer_prompt.py +0 -0
  40. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/prompts/github/pr_creator_prompt.py +0 -0
  41. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/prompts/github/repo_forker_prompt.py +0 -0
  42. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/prompts/github/repo_viewer_prompt.py +0 -0
  43. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/prompts/github/system_prompt.py +0 -0
  44. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/prompts/py.typed +0 -0
  45. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/tools/github/__init__.py +0 -0
  46. {github_haystack-1.2.1 → github_haystack-2.1.0}/src/haystack_integrations/tools/py.typed +0 -0
  47. {github_haystack-1.2.1 → github_haystack-2.1.0}/tests/__init__.py +0 -0
  48. {github_haystack-1.2.1 → github_haystack-2.1.0}/tests/test_issue_commenter.py +0 -0
  49. {github_haystack-1.2.1 → github_haystack-2.1.0}/tests/test_issue_viewer.py +0 -0
@@ -1,11 +1,35 @@
1
1
  # Changelog
2
2
 
3
- ## [integrations/github-v1.2.0] - 2025-10-13
3
+ ## [integrations/github-v2.0.0] - 2026-01-12
4
+
5
+ ### 📚 Documentation
6
+
7
+ - Add pydoc configurations for Docusaurus (#2411)
8
+
9
+ ### ⚙️ CI
10
+
11
+ - Change pytest command (#2475)
12
+
13
+ ### 🧹 Chores
14
+
15
+ - Remove Readme API CI workflow and configs (#2573)
16
+ - Fix nightly test (#2580)
17
+ - Make fmt command more forgiving (#2671)
18
+ - [**breaking**] Github - drop Python 3.9 and use X|Y typing (#2705)
19
+
20
+ ### 🌀 Miscellaneous
21
+
22
+ - Adopt PEP 585 type hinting (part 3) (#2510)
23
+ - Chore: Fix tool validation test failures in github integration (#2659)
24
+ - Fix: Fix github integration unit tests (#2703)
25
+
26
+ ## [integrations/github-v1.2.1] - 2025-10-20
4
27
 
5
28
  ### 🚀 Features
6
29
 
7
30
  - Add support for GitHubRepoForkerTool (#1968)
8
31
 
32
+
9
33
  ### 🧪 Testing
10
34
 
11
35
  - Fix GitHub test (#2119)
@@ -17,6 +41,7 @@
17
41
  ### 🌀 Miscellaneous
18
42
 
19
43
  - Chore: Fix linting github (#2255)
44
+ - Fix: handle empty GitHub tokens in authentication headers (#2400)
20
45
 
21
46
  ## [integrations/github-v1.1.0] - 2025-07-01
22
47
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github-haystack
3
- Version: 1.2.1
3
+ Version: 2.1.0
4
4
  Summary: Haystack components for interacting with GitHub repositories
5
5
  Project-URL: Source, https://github.com/deepset-ai/haystack-core-integrations/github
6
6
  Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/blob/main/integrations/github/README.md
@@ -11,15 +11,15 @@ License-File: LICENSE.txt
11
11
  Classifier: Development Status :: 4 - Beta
12
12
  Classifier: License :: OSI Approved :: Apache Software License
13
13
  Classifier: Programming Language :: Python
14
- Classifier: Programming Language :: Python :: 3.9
15
14
  Classifier: Programming Language :: Python :: 3.10
16
15
  Classifier: Programming Language :: Python :: 3.11
17
16
  Classifier: Programming Language :: Python :: 3.12
18
17
  Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
19
  Classifier: Programming Language :: Python :: Implementation :: CPython
20
20
  Classifier: Programming Language :: Python :: Implementation :: PyPy
21
- Requires-Python: >=3.9
22
- Requires-Dist: haystack-ai>=2.12.0
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: haystack-ai>=2.22.0
23
23
  Description-Content-Type: text/markdown
24
24
 
25
25
  # github-haystack
@@ -0,0 +1,18 @@
1
+ loaders:
2
+ - modules:
3
+ - haystack_integrations.components.connectors.github.file_editor
4
+ - haystack_integrations.components.connectors.github.issue_commenter
5
+ - haystack_integrations.components.connectors.github.issue_viewer
6
+ - haystack_integrations.components.connectors.github.pr_creator
7
+ - haystack_integrations.components.connectors.github.repo_viewer
8
+ - haystack_integrations.components.connectors.github.repo_forker
9
+ search_path: [../src]
10
+ processors:
11
+ - type: filter
12
+ documented_only: true
13
+ skip_empty_modules: true
14
+ renderer:
15
+ description: GitHub integration for Haystack
16
+ id: integrations-github
17
+ filename: github.md
18
+ title: GitHub
@@ -7,7 +7,7 @@ name = "github-haystack"
7
7
  dynamic = ["version"]
8
8
  description = 'Haystack components for interacting with GitHub repositories'
9
9
  readme = "README.md"
10
- requires-python = ">=3.9"
10
+ requires-python = ">=3.10"
11
11
  license = "Apache-2.0"
12
12
  keywords = []
13
13
  authors = [{ name = "deepset GmbH", email = "info@deepset.ai" }]
@@ -15,15 +15,15 @@ classifiers = [
15
15
  "License :: OSI Approved :: Apache Software License",
16
16
  "Development Status :: 4 - Beta",
17
17
  "Programming Language :: Python",
18
- "Programming Language :: Python :: 3.9",
19
18
  "Programming Language :: Python :: 3.10",
20
19
  "Programming Language :: Python :: 3.11",
21
20
  "Programming Language :: Python :: 3.12",
22
21
  "Programming Language :: Python :: 3.13",
22
+ "Programming Language :: Python :: 3.14",
23
23
  "Programming Language :: Python :: Implementation :: CPython",
24
24
  "Programming Language :: Python :: Implementation :: PyPy",
25
25
  ]
26
- dependencies = ["haystack-ai>=2.12.0"]
26
+ dependencies = ["haystack-ai>=2.22.0"]
27
27
 
28
28
  [project.urls]
29
29
  Source = "https://github.com/deepset-ai/haystack-core-integrations/github"
@@ -46,8 +46,8 @@ installer = "uv"
46
46
  dependencies = ["haystack-pydoc-tools", "ruff"]
47
47
 
48
48
  [tool.hatch.envs.default.scripts]
49
- docs = ["pydoc-markdown pydoc/config.yml"]
50
- fmt = "ruff check --fix {args} && ruff format {args}"
49
+ docs = ["haystack-pydoc pydoc/config_docusaurus.yml"]
50
+ fmt = "ruff check --fix {args}; ruff format {args}"
51
51
  fmt-check = "ruff check {args} && ruff format --check {args}"
52
52
 
53
53
  [tool.hatch.envs.test]
@@ -64,7 +64,8 @@ dependencies = [
64
64
  unit = 'pytest -m "not integration" {args:tests}'
65
65
  integration = 'pytest -m "integration" {args:tests}'
66
66
  all = 'pytest {args:tests}'
67
- cov-retry = 'all --cov=haystack_integrations --reruns 3 --reruns-delay 30 -x'
67
+ unit-cov-retry = 'pytest --cov=haystack_integrations --reruns 3 --reruns-delay 30 -x -m "not integration" {args:tests}'
68
+ integration-cov-append-retry = 'pytest --cov=haystack_integrations --cov-append --reruns 3 --reruns-delay 30 -x -m "integration" {args:tests}'
68
69
 
69
70
  types = """mypy -p haystack_integrations.components.connectors.github \
70
71
  -p haystack_integrations.prompts.github \
@@ -77,15 +78,22 @@ check_untyped_defs = true
77
78
  disallow_incomplete_defs = true
78
79
 
79
80
  [tool.ruff]
80
- target-version = "py38"
81
81
  line-length = 120
82
82
 
83
83
  [tool.ruff.lint]
84
84
  select = [
85
85
  "A",
86
+ "ANN",
86
87
  "ARG",
87
88
  "B",
88
89
  "C",
90
+ "D102", # Missing docstring in public method
91
+ "D103", # Missing docstring in public function
92
+ "D205", # 1 blank line required between summary line and description
93
+ "D209", # Closing triple quotes go to new line
94
+ "D213", # summary lines must be positioned on the second physical line of the docstring
95
+ "D417", # Missing argument descriptions in the docstring
96
+ "D419", # Docstring is empty
89
97
  "DTZ",
90
98
  "E",
91
99
  "EM",
@@ -123,10 +131,8 @@ ignore = [
123
131
  # Misc
124
132
  "B008",
125
133
  "S101",
126
- ]
127
- unfixable = [
128
- # Don't touch unused imports
129
- "F401",
134
+ # Allow `Any` - used legitimately for dynamic types and SDK boundaries
135
+ "ANN401",
130
136
  ]
131
137
 
132
138
  [tool.ruff.lint.isort]
@@ -137,13 +143,14 @@ ban-relative-imports = "parents"
137
143
 
138
144
  [tool.ruff.lint.per-file-ignores]
139
145
  # Tests can use magic values, assertions, and relative imports
140
- "tests/**/*" = ["PLR2004", "S101", "TID252"]
146
+ "tests/**/*" = ["D", "PLR2004", "S101", "TID252", "ANN"]
141
147
  # Ignore RUF001 for all files in the prompts directory
142
148
  "src/haystack_integrations/components/prompts/**/*" = ["RUF001"]
143
149
 
144
150
  [tool.coverage.run]
145
151
  source = ["haystack_integrations"]
146
152
  branch = true
153
+ relative_files = true
147
154
  parallel = false
148
155
 
149
156
 
@@ -3,7 +3,7 @@
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
  from base64 import b64decode, b64encode
5
5
  from enum import Enum
6
- from typing import Any, Dict, Optional, Union
6
+ from typing import Any
7
7
 
8
8
  import requests
9
9
  from haystack import component, default_from_dict, default_to_dict, logging
@@ -79,10 +79,10 @@ class GitHubFileEditor:
79
79
  self,
80
80
  *,
81
81
  github_token: Secret = Secret.from_env_var("GITHUB_TOKEN"),
82
- repo: Optional[str] = None,
82
+ repo: str | None = None,
83
83
  branch: str = "main",
84
84
  raise_on_failure: bool = True,
85
- ):
85
+ ) -> None:
86
86
  """
87
87
  Initialize the component.
88
88
 
@@ -145,7 +145,7 @@ class GitHubFileEditor:
145
145
  def _check_last_commit(self, owner: str, repo: str, branch: str) -> bool:
146
146
  """Check if last commit was made by the current token user."""
147
147
  url = f"https://api.github.com/repos/{owner}/{repo}/commits"
148
- params: Dict[str, Union[str, int]] = {"per_page": 1, "sha": branch}
148
+ params: dict[str, str | int] = {"per_page": 1, "sha": branch}
149
149
  response = requests.get(url, headers=self._get_request_headers(), params=params, timeout=10)
150
150
  response.raise_for_status()
151
151
  last_commit = response.json()[0]
@@ -158,7 +158,7 @@ class GitHubFileEditor:
158
158
 
159
159
  return commit_author == current_user
160
160
 
161
- def _edit_file(self, owner: str, repo: str, payload: Dict[str, str], branch: str) -> str:
161
+ def _edit_file(self, owner: str, repo: str, payload: dict[str, str], branch: str) -> str:
162
162
  """Handle file editing."""
163
163
  try:
164
164
  content, sha = self._get_file_content(owner, repo, payload["path"], branch)
@@ -180,7 +180,7 @@ class GitHubFileEditor:
180
180
  raise
181
181
  return f"Error: {e!s}"
182
182
 
183
- def _undo_changes(self, owner: str, repo: str, payload: Dict[str, Any], branch: str) -> str:
183
+ def _undo_changes(self, owner: str, repo: str, payload: dict[str, Any], branch: str) -> str:
184
184
  """Handle undoing changes."""
185
185
  try:
186
186
  if not self._check_last_commit(owner, repo, branch):
@@ -191,7 +191,7 @@ class GitHubFileEditor:
191
191
  commits_url = f"https://api.github.com/repos/{owner}/{repo}/commits"
192
192
 
193
193
  # Get the previous commit SHA
194
- params: Dict[str, Union[str, int]] = {"per_page": 2, "sha": branch}
194
+ params: dict[str, str | int] = {"per_page": 2, "sha": branch}
195
195
  commits = requests.get(commits_url, headers=self._get_request_headers(), params=params, timeout=10).json()
196
196
  previous_sha = commits[1]["sha"]
197
197
 
@@ -207,7 +207,7 @@ class GitHubFileEditor:
207
207
  raise
208
208
  return f"Error: {e!s}"
209
209
 
210
- def _create_file(self, owner: str, repo: str, payload: Dict[str, str], branch: str) -> str:
210
+ def _create_file(self, owner: str, repo: str, payload: dict[str, str], branch: str) -> str:
211
211
  """Handle file creation."""
212
212
  try:
213
213
  url = f"https://api.github.com/repos/{owner}/{repo}/contents/{payload['path']}"
@@ -224,7 +224,7 @@ class GitHubFileEditor:
224
224
  raise
225
225
  return f"Error: {e!s}"
226
226
 
227
- def _delete_file(self, owner: str, repo: str, payload: Dict[str, str], branch: str) -> str:
227
+ def _delete_file(self, owner: str, repo: str, payload: dict[str, str], branch: str) -> str:
228
228
  """Handle file deletion."""
229
229
  try:
230
230
  _, sha = self._get_file_content(owner, repo, payload["path"], branch)
@@ -244,11 +244,11 @@ class GitHubFileEditor:
244
244
  @component.output_types(result=str)
245
245
  def run(
246
246
  self,
247
- command: Union[Command, str],
248
- payload: Dict[str, Any],
249
- repo: Optional[str] = None,
250
- branch: Optional[str] = None,
251
- ) -> Dict[str, str]:
247
+ command: Command | str,
248
+ payload: dict[str, Any],
249
+ repo: str | None = None,
250
+ branch: str | None = None,
251
+ ) -> dict[str, str]:
252
252
  """
253
253
  Process GitHub file operations.
254
254
 
@@ -287,7 +287,7 @@ class GitHubFileEditor:
287
287
  result = command_handlers[command](owner, repo_name, payload, working_branch)
288
288
  return {"result": result}
289
289
 
290
- def to_dict(self) -> Dict[str, Any]:
290
+ def to_dict(self) -> dict[str, Any]:
291
291
  """Serialize the component to a dictionary."""
292
292
  return default_to_dict(
293
293
  self,
@@ -298,7 +298,7 @@ class GitHubFileEditor:
298
298
  )
299
299
 
300
300
  @classmethod
301
- def from_dict(cls, data: Dict[str, Any]) -> "GitHubFileEditor":
301
+ def from_dict(cls, data: dict[str, Any]) -> "GitHubFileEditor":
302
302
  """Deserialize the component from a dictionary."""
303
303
  init_params = data["init_parameters"]
304
304
  deserialize_secrets_inplace(init_params, keys=["github_token"])
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
  import re
5
- from typing import Any, Dict
5
+ from typing import Any
6
6
 
7
7
  import requests
8
8
  from haystack import component, default_from_dict, default_to_dict, logging
@@ -41,7 +41,7 @@ class GitHubIssueCommenter:
41
41
  github_token: Secret = Secret.from_env_var("GITHUB_TOKEN"),
42
42
  raise_on_failure: bool = True,
43
43
  retry_attempts: int = 2,
44
- ):
44
+ ) -> None:
45
45
  """
46
46
  Initialize the component.
47
47
 
@@ -115,7 +115,7 @@ class GitHubIssueCommenter:
115
115
 
116
116
  return False
117
117
 
118
- def to_dict(self) -> Dict[str, Any]:
118
+ def to_dict(self) -> dict[str, Any]:
119
119
  """
120
120
  Serialize the component to a dictionary.
121
121
 
@@ -129,7 +129,7 @@ class GitHubIssueCommenter:
129
129
  )
130
130
 
131
131
  @classmethod
132
- def from_dict(cls, data: Dict[str, Any]) -> "GitHubIssueCommenter":
132
+ def from_dict(cls, data: dict[str, Any]) -> "GitHubIssueCommenter":
133
133
  """
134
134
  Deserialize the component from a dictionary.
135
135
 
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
  import re
5
- from typing import Any, Dict, List, Optional
5
+ from typing import Any
6
6
 
7
7
  import requests
8
8
  from haystack import Document, component, default_from_dict, default_to_dict, logging
@@ -37,10 +37,10 @@ class GitHubIssueViewer:
37
37
  def __init__(
38
38
  self,
39
39
  *,
40
- github_token: Optional[Secret] = None,
40
+ github_token: Secret | None = None,
41
41
  raise_on_failure: bool = True,
42
42
  retry_attempts: int = 2,
43
- ):
43
+ ) -> None:
44
44
  """
45
45
  Initialize the component.
46
46
 
@@ -154,7 +154,7 @@ class GitHubIssueViewer:
154
154
  },
155
155
  )
156
156
 
157
- def to_dict(self) -> Dict[str, Any]:
157
+ def to_dict(self) -> dict[str, Any]:
158
158
  """
159
159
  Serialize the component to a dictionary.
160
160
 
@@ -168,7 +168,7 @@ class GitHubIssueViewer:
168
168
  )
169
169
 
170
170
  @classmethod
171
- def from_dict(cls, data: Dict[str, Any]) -> "GitHubIssueViewer":
171
+ def from_dict(cls, data: dict[str, Any]) -> "GitHubIssueViewer":
172
172
  """
173
173
  Deserialize the component from a dictionary.
174
174
 
@@ -179,7 +179,7 @@ class GitHubIssueViewer:
179
179
  deserialize_secrets_inplace(init_params, keys=["github_token"])
180
180
  return default_from_dict(cls, data)
181
181
 
182
- @component.output_types(documents=List[Document])
182
+ @component.output_types(documents=list[Document])
183
183
  def run(self, url: str) -> dict:
184
184
  """
185
185
  Process a GitHub issue URL and return documents.
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
  import re
5
- from typing import Any, Dict, Optional
5
+ from typing import Any
6
6
 
7
7
  import requests
8
8
  from haystack import component, default_from_dict, default_to_dict, logging
@@ -38,7 +38,12 @@ class GitHubPRCreator:
38
38
  ```
39
39
  """
40
40
 
41
- def __init__(self, *, github_token: Secret = Secret.from_env_var("GITHUB_TOKEN"), raise_on_failure: bool = True):
41
+ def __init__(
42
+ self,
43
+ *,
44
+ github_token: Secret = Secret.from_env_var("GITHUB_TOKEN"),
45
+ raise_on_failure: bool = True,
46
+ ) -> None:
42
47
  """
43
48
  Initialize the component.
44
49
 
@@ -102,7 +107,7 @@ class GitHubPRCreator:
102
107
  except requests.RequestException:
103
108
  return False
104
109
 
105
- def _create_fork(self, owner: str, repo: str) -> Optional[str]:
110
+ def _create_fork(self, owner: str, repo: str) -> str | None:
106
111
  """Create a fork of the repository."""
107
112
  url = f"https://api.github.com/repos/{owner}/{repo}/forks"
108
113
  try:
@@ -215,7 +220,7 @@ class GitHubPRCreator:
215
220
  @component.output_types(result=str)
216
221
  def run(
217
222
  self, issue_url: str, title: str, branch: str, base: str, body: str = "", draft: bool = False
218
- ) -> Dict[str, str]:
223
+ ) -> dict[str, str]:
219
224
  """
220
225
  Create a new pull request from your fork to the original repository, linked to the specified issue.
221
226
 
@@ -263,7 +268,7 @@ class GitHubPRCreator:
263
268
  raise
264
269
  return {"result": f"Error: {e!s}"}
265
270
 
266
- def to_dict(self) -> Dict[str, Any]:
271
+ def to_dict(self) -> dict[str, Any]:
267
272
  """Serialize the component to a dictionary."""
268
273
  return default_to_dict(
269
274
  self,
@@ -272,7 +277,7 @@ class GitHubPRCreator:
272
277
  )
273
278
 
274
279
  @classmethod
275
- def from_dict(cls, data: Dict[str, Any]) -> "GitHubPRCreator":
280
+ def from_dict(cls, data: dict[str, Any]) -> "GitHubPRCreator":
276
281
  """Deserialize the component from a dictionary."""
277
282
  init_params = data["init_parameters"]
278
283
  deserialize_secrets_inplace(init_params, keys=["github_token"])
@@ -3,7 +3,7 @@
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
  import re
5
5
  import time
6
- from typing import Any, Dict, Optional
6
+ from typing import Any
7
7
 
8
8
  import requests
9
9
  from haystack import component, default_from_dict, default_to_dict, logging
@@ -48,7 +48,7 @@ class GitHubRepoForker:
48
48
  poll_interval: int = 2,
49
49
  auto_sync: bool = True,
50
50
  create_branch: bool = True,
51
- ):
51
+ ) -> None:
52
52
  """
53
53
  Initialize the component.
54
54
 
@@ -137,7 +137,7 @@ class GitHubRepoForker:
137
137
  response.raise_for_status()
138
138
  return response.json()["login"]
139
139
 
140
- def _get_existing_repository(self, repo_name: str) -> Optional[str]:
140
+ def _get_existing_repository(self, repo_name: str) -> str | None:
141
141
  """
142
142
  Check if a repository with the given name already exists in the authenticated user's account.
143
143
 
@@ -221,7 +221,7 @@ class GitHubRepoForker:
221
221
  fork_data = response.json()
222
222
  return f"{fork_data['owner']['login']}/{fork_data['name']}"
223
223
 
224
- def to_dict(self) -> Dict[str, Any]:
224
+ def to_dict(self) -> dict[str, Any]:
225
225
  """
226
226
  Serialize the component to a dictionary.
227
227
 
@@ -239,7 +239,7 @@ class GitHubRepoForker:
239
239
  )
240
240
 
241
241
  @classmethod
242
- def from_dict(cls, data: Dict[str, Any]) -> "GitHubRepoForker":
242
+ def from_dict(cls, data: dict[str, Any]) -> "GitHubRepoForker":
243
243
  """
244
244
  Deserialize the component from a dictionary.
245
245
 
@@ -3,7 +3,7 @@
3
3
  # SPDX-License-Identifier: Apache-2.0
4
4
  import base64
5
5
  from dataclasses import dataclass
6
- from typing import Any, Dict, List, Optional
6
+ from typing import Any
7
7
 
8
8
  import requests
9
9
  from haystack import Document, component, default_from_dict, default_to_dict, logging
@@ -21,7 +21,7 @@ class GitHubItem:
21
21
  path: str
22
22
  size: int
23
23
  url: str
24
- content: Optional[str] = None
24
+ content: str | None = None
25
25
 
26
26
 
27
27
  @component
@@ -71,12 +71,12 @@ class GitHubRepoViewer:
71
71
  def __init__(
72
72
  self,
73
73
  *,
74
- github_token: Optional[Secret] = None,
74
+ github_token: Secret | None = None,
75
75
  raise_on_failure: bool = True,
76
76
  max_file_size: int = 1_000_000, # 1MB default limit
77
- repo: Optional[str] = None,
77
+ repo: str | None = None,
78
78
  branch: str = "main",
79
- ):
79
+ ) -> None:
80
80
  """
81
81
  Initialize the component.
82
82
 
@@ -114,7 +114,7 @@ class GitHubRepoViewer:
114
114
  headers["Authorization"] = f"Bearer {token_value}"
115
115
  return headers
116
116
 
117
- def to_dict(self) -> Dict[str, Any]:
117
+ def to_dict(self) -> dict[str, Any]:
118
118
  """
119
119
  Serialize the component to a dictionary.
120
120
 
@@ -130,7 +130,7 @@ class GitHubRepoViewer:
130
130
  )
131
131
 
132
132
  @classmethod
133
- def from_dict(cls, data: Dict[str, Any]) -> "GitHubRepoViewer":
133
+ def from_dict(cls, data: dict[str, Any]) -> "GitHubRepoViewer":
134
134
  """
135
135
  Deserialize the component from a dictionary.
136
136
 
@@ -181,7 +181,7 @@ class GitHubRepoViewer:
181
181
  },
182
182
  )
183
183
 
184
- def _create_directory_documents(self, items: List[GitHubItem]) -> List[Document]:
184
+ def _create_directory_documents(self, items: list[GitHubItem]) -> list[Document]:
185
185
  """Create a list of Documents from directory contents"""
186
186
  return [
187
187
  Document(
@@ -206,8 +206,8 @@ class GitHubRepoViewer:
206
206
  },
207
207
  )
208
208
 
209
- @component.output_types(documents=List[Document])
210
- def run(self, path: str, repo: Optional[str] = None, branch: Optional[str] = None) -> Dict[str, List[Document]]:
209
+ @component.output_types(documents=list[Document])
210
+ def run(self, path: str, repo: str | None = None, branch: str | None = None) -> dict[str, list[Document]]:
211
211
  """
212
212
  Process a GitHub repository path and return documents.
213
213
 
@@ -1,7 +1,8 @@
1
1
  # SPDX-FileCopyrightText: 2023-present deepset GmbH <info@deepset.ai>
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
- from typing import Any, Callable, Dict, Optional, Union
4
+ from collections.abc import Callable
5
+ from typing import Any
5
6
 
6
7
  from haystack.core.serialization import generate_qualified_class_name
7
8
  from haystack.tools import ComponentTool
@@ -20,17 +21,17 @@ class GitHubFileEditorTool(ComponentTool):
20
21
  def __init__(
21
22
  self,
22
23
  *,
23
- name: Optional[str] = "file_editor",
24
- description: Optional[str] = FILE_EDITOR_PROMPT,
25
- parameters: Optional[Dict[str, Any]] = FILE_EDITOR_SCHEMA,
24
+ name: str | None = "file_editor",
25
+ description: str | None = FILE_EDITOR_PROMPT,
26
+ parameters: dict[str, Any] | None = FILE_EDITOR_SCHEMA,
26
27
  github_token: Secret = Secret.from_env_var("GITHUB_TOKEN"),
27
- repo: Optional[str] = None,
28
+ repo: str | None = None,
28
29
  branch: str = "main",
29
30
  raise_on_failure: bool = True,
30
- outputs_to_string: Optional[Dict[str, Union[str, Callable[[Any], str]]]] = None,
31
- inputs_from_state: Optional[Dict[str, str]] = None,
32
- outputs_to_state: Optional[Dict[str, Dict[str, Union[str, Callable]]]] = None,
33
- ):
31
+ outputs_to_string: dict[str, str | Callable[[Any], str]] | None = None,
32
+ inputs_from_state: dict[str, str] | None = None,
33
+ outputs_to_state: dict[str, dict[str, str | Callable]] | None = None,
34
+ ) -> None:
34
35
  """
35
36
  Initialize the GitHub file editor tool.
36
37
 
@@ -86,7 +87,7 @@ class GitHubFileEditorTool(ComponentTool):
86
87
  outputs_to_state=outputs_to_state,
87
88
  )
88
89
 
89
- def to_dict(self) -> Dict[str, Any]:
90
+ def to_dict(self) -> dict[str, Any]:
90
91
  """
91
92
  Serializes the tool to a dictionary.
92
93
 
@@ -110,7 +111,7 @@ class GitHubFileEditorTool(ComponentTool):
110
111
  return {"type": generate_qualified_class_name(type(self)), "data": serialized}
111
112
 
112
113
  @classmethod
113
- def from_dict(cls, data: Dict[str, Any]) -> "GitHubFileEditorTool":
114
+ def from_dict(cls, data: dict[str, Any]) -> "GitHubFileEditorTool":
114
115
  """
115
116
  Deserializes the tool from a dictionary.
116
117
 
@@ -1,7 +1,8 @@
1
1
  # SPDX-FileCopyrightText: 2023-present deepset GmbH <info@deepset.ai>
2
2
  #
3
3
  # SPDX-License-Identifier: Apache-2.0
4
- from typing import Any, Callable, Dict, Optional, Union
4
+ from collections.abc import Callable
5
+ from typing import Any
5
6
 
6
7
  from haystack.core.serialization import generate_qualified_class_name
7
8
  from haystack.tools import ComponentTool
@@ -20,16 +21,16 @@ class GitHubIssueCommenterTool(ComponentTool):
20
21
  def __init__(
21
22
  self,
22
23
  *,
23
- name: Optional[str] = "issue_commenter",
24
- description: Optional[str] = ISSUE_COMMENTER_PROMPT,
25
- parameters: Optional[Dict[str, Any]] = ISSUE_COMMENTER_SCHEMA,
24
+ name: str | None = "issue_commenter",
25
+ description: str | None = ISSUE_COMMENTER_PROMPT,
26
+ parameters: dict[str, Any] | None = ISSUE_COMMENTER_SCHEMA,
26
27
  github_token: Secret = Secret.from_env_var("GITHUB_TOKEN"),
27
28
  raise_on_failure: bool = True,
28
29
  retry_attempts: int = 2,
29
- outputs_to_string: Optional[Dict[str, Union[str, Callable[[Any], str]]]] = None,
30
- inputs_from_state: Optional[Dict[str, str]] = None,
31
- outputs_to_state: Optional[Dict[str, Dict[str, Union[str, Callable]]]] = None,
32
- ):
30
+ outputs_to_string: dict[str, str | Callable[[Any], str]] | None = None,
31
+ inputs_from_state: dict[str, str] | None = None,
32
+ outputs_to_state: dict[str, dict[str, str | Callable]] | None = None,
33
+ ) -> None:
33
34
  """
34
35
  Initialize the GitHub issue commenter tool.
35
36
 
@@ -82,7 +83,7 @@ class GitHubIssueCommenterTool(ComponentTool):
82
83
  outputs_to_state=outputs_to_state,
83
84
  )
84
85
 
85
- def to_dict(self) -> Dict[str, Any]:
86
+ def to_dict(self) -> dict[str, Any]:
86
87
  """
87
88
  Serializes the tool to a dictionary.
88
89
 
@@ -105,7 +106,7 @@ class GitHubIssueCommenterTool(ComponentTool):
105
106
  return {"type": generate_qualified_class_name(type(self)), "data": serialized}
106
107
 
107
108
  @classmethod
108
- def from_dict(cls, data: Dict[str, Any]) -> "GitHubIssueCommenterTool":
109
+ def from_dict(cls, data: dict[str, Any]) -> "GitHubIssueCommenterTool":
109
110
  """
110
111
  Deserializes the tool from a dictionary.
111
112