ultralytics-actions 0.0.44__py3-none-any.whl → 0.0.46__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.
actions/__init__.py CHANGED
@@ -22,4 +22,4 @@
22
22
  # ├── test_summarize_pr.py
23
23
  # └── ...
24
24
 
25
- __version__ = "0.0.44"
25
+ __version__ = "0.0.46"
@@ -298,7 +298,7 @@ def get_first_interaction_response(event, issue_type: str, title: str, body: str
298
298
  3. For questions:
299
299
  - Provide as much context as possible about your question
300
300
  - Include any research you've already done on the topic
301
- - Specify which parts of the [documentation](https://docs.ultralytics.com), if any, you've already consulted
301
+ - Specify which parts of the [documentation](https://docs.ultralytics.com/), if any, you've already consulted
302
302
 
303
303
  Please make sure you've searched existing {issue_type}s to avoid duplicates. If you need to add any additional information, please comment on this {issue_type}.
304
304
 
@@ -311,12 +311,12 @@ Thank you for your contribution to improving our project!
311
311
  - ✅ **Define a Purpose**: Clearly explain the purpose of your fix or feature in your PR description, and link to any [relevant issues](https://github.com/{event.repository}/issues). Ensure your commit messages are clear, concise, and adhere to the project's conventions.
312
312
  - ✅ **Synchronize with Source**: Confirm your PR is synchronized with the `{event.repository}` `main` branch. If it's behind, update it by clicking the 'Update branch' button or by running `git pull` and `git merge main` locally.
313
313
  - ✅ **Ensure CI Checks Pass**: Verify all Ultralytics [Continuous Integration (CI)](https://docs.ultralytics.com/help/CI/) checks are passing. If any checks fail, please address the issues.
314
- - ✅ **Update Documentation**: Update the relevant [documentation](https://docs.ultralytics.com) for any new or modified features.
314
+ - ✅ **Update Documentation**: Update the relevant [documentation](https://docs.ultralytics.com/) for any new or modified features.
315
315
  - ✅ **Add Tests**: If applicable, include or update tests to cover your changes, and confirm that all tests are passing.
316
316
  - ✅ **Sign the CLA**: Please ensure you have signed our [Contributor License Agreement](https://docs.ultralytics.com/help/CLA/) if this is your first Ultralytics PR by writing "I have read the CLA Document and I sign the CLA" in a new message.
317
317
  - ✅ **Minimize Changes**: Limit your changes to the **minimum** necessary for your bug fix or feature addition. _"It is not daily increase but daily decrease, hack away the unessential. The closer to the source, the less wastage there is."_ — Bruce Lee
318
318
 
319
- For more guidance, please refer to our [Contributing Guide](https://docs.ultralytics.com/help/contributing). Don’t hesitate to leave a comment if you have any questions. Thank you for contributing to Ultralytics! 🚀
319
+ For more guidance, please refer to our [Contributing Guide](https://docs.ultralytics.com/help/contributing/). Don’t hesitate to leave a comment if you have any questions. Thank you for contributing to Ultralytics! 🚀
320
320
  """
321
321
 
322
322
  if issue_type == "pull request":
actions/utils/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  # Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license
2
2
 
3
- from .common_utils import remove_html_comments
3
+ from .common_utils import REQUESTS_HEADERS, remove_html_comments
4
4
  from .github_utils import (
5
5
  GITHUB_API_URL,
6
6
  Action,
@@ -11,6 +11,7 @@ from .openai_utils import get_completion
11
11
 
12
12
  __all__ = (
13
13
  "GITHUB_API_URL",
14
+ "REQUESTS_HEADERS",
14
15
  "Action",
15
16
  "check_pypi_version",
16
17
  "get_completion",
@@ -7,22 +7,24 @@ from urllib import parse
7
7
 
8
8
  import requests
9
9
 
10
-
11
- def remove_html_comments(body: str) -> str:
12
- """Removes HTML comments from a string using regex pattern matching."""
13
- return re.sub(r"<!--.*?-->", "", body, flags=re.DOTALL).strip()
14
-
15
-
16
- def clean_url(url):
17
- """Remove extra characters from URL strings."""
18
- for _ in range(3):
19
- url = str(url).strip('"').strip("'").rstrip(".,:;!?`\\").replace(".git@main", "").replace("git+", "")
20
- return url
21
-
22
-
23
- def is_url(url, check=True, max_attempts=3, timeout=2):
24
- """Check if string is URL and optionally verify it exists."""
25
- allow_list = (
10
+ REQUESTS_HEADERS = {
11
+ "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36",
12
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
13
+ "Accept-Language": "en-US,en;q=0.9,es;q=0.8,zh-CN;q=0.7,zh;q=0.6",
14
+ "Accept-Encoding": "gzip, deflate, br, zstd",
15
+ "sec-ch-ua": '"Chromium";v="132", "Google Chrome";v="132", "Not_A Brand";v="99"',
16
+ "sec-ch-ua-mobile": "?0",
17
+ "sec-ch-ua-platform": '"macOS"',
18
+ "Sec-Fetch-Site": "none",
19
+ "Sec-Fetch-Mode": "navigate",
20
+ "Sec-Fetch-User": "?1",
21
+ "Sec-Fetch-Dest": "document",
22
+ "Referer": "https://www.google.com/",
23
+ "Origin": "https://www.google.com/",
24
+ }
25
+
26
+ URL_IGNORE_LIST = frozenset(
27
+ {
26
28
  "localhost",
27
29
  "127.0.0",
28
30
  ":5000",
@@ -36,16 +38,43 @@ def is_url(url, check=True, max_attempts=3, timeout=2):
36
38
  "example",
37
39
  "mailto:",
38
40
  "github.com", # ignore GitHub links that may be private repos
39
- "kaggle.com", # blocks automated header requests
40
- "reddit.com", # blocks automated header requests
41
41
  "linkedin.com",
42
42
  "twitter.com",
43
43
  "x.com",
44
44
  "storage.googleapis.com", # private GCS buckets
45
- )
45
+ }
46
+ )
47
+
48
+ URL_PATTERN = re.compile(
49
+ r"\[([^]]+)]\((.*?)(?=\)(?:\s|$))\)" # Markdown links with lookahead for space/end
50
+ r"|"
51
+ r"(" # Start capturing group for plaintext URLs
52
+ r"(?:https?://)?" # Optional http:// or https://
53
+ r"(?:www\.)?" # Optional www.
54
+ r"(?:[\w.-]+)?" # Optional domain name and subdomains
55
+ r"\.[a-zA-Z]{2,}" # TLD
56
+ r"(?:/[^\s\"'\]]*)?" # Optional path
57
+ r")"
58
+ )
59
+
60
+
61
+ def remove_html_comments(body: str) -> str:
62
+ """Removes HTML comments from a string using regex pattern matching."""
63
+ return re.sub(r"<!--.*?-->", "", body, flags=re.DOTALL).strip()
64
+
65
+
66
+ def clean_url(url):
67
+ """Remove extra characters from URL strings."""
68
+ for _ in range(3):
69
+ url = str(url).strip('"').strip("'").rstrip(".,:;!?`\\").replace(".git@main", "").replace("git+", "")
70
+ return url
71
+
72
+
73
+ def is_url(url, session=None, check=True, max_attempts=3, timeout=2):
74
+ """Check if string is URL and optionally verify it exists."""
46
75
  try:
47
76
  # Check allow list
48
- if any(x in url for x in allow_list):
77
+ if any(x in url for x in URL_IGNORE_LIST):
49
78
  return True
50
79
 
51
80
  # Check structure
@@ -54,31 +83,20 @@ def is_url(url, check=True, max_attempts=3, timeout=2):
54
83
  if not result.scheme or not partition[0] or not partition[2]:
55
84
  return False
56
85
 
57
- # Check response
58
86
  if check:
59
- headers = {
60
- "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36",
61
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
62
- "Accept-Language": "en-US,en;q=0.9,es;q=0.8,zh-CN;q=0.7,zh;q=0.6",
63
- "Accept-Encoding": "gzip, deflate, br, zstd",
64
- "sec-ch-ua": '"Chromium";v="132", "Google Chrome";v="132", "Not_A Brand";v="99"',
65
- "sec-ch-ua-mobile": "?0",
66
- "sec-ch-ua-platform": '"macOS"',
67
- "Sec-Fetch-Site": "none",
68
- "Sec-Fetch-Mode": "navigate",
69
- "Sec-Fetch-User": "?1",
70
- "Sec-Fetch-Dest": "document",
71
- "Referer": "https://www.google.com/",
72
- "Origin": "https://www.google.com/",
73
- }
87
+ requester = session or requests
74
88
  bad_codes = {404, 410, 500, 502, 503, 504}
89
+ kwargs = {"timeout": timeout, "allow_redirects": True}
90
+ if not session:
91
+ kwargs["headers"] = REQUESTS_HEADERS
92
+
75
93
  for attempt in range(max_attempts):
76
94
  try:
77
- response = requests.head(url, headers=headers, timeout=timeout, allow_redirects=True)
78
- if response.status_code not in bad_codes:
79
- return True
80
- response = requests.get(url, headers=headers, timeout=timeout, allow_redirects=True, stream=True)
81
- return response.status_code not in bad_codes # Try GET if HEAD fails
95
+ # Try HEAD first, then GET if needed
96
+ for method in (requester.head, requester.get):
97
+ if method(url, stream=method == requester.get, **kwargs).status_code not in bad_codes:
98
+ return True
99
+ return False
82
100
  except Exception:
83
101
  if attempt == max_attempts - 1: # last attempt
84
102
  return False
@@ -91,28 +109,16 @@ def is_url(url, check=True, max_attempts=3, timeout=2):
91
109
 
92
110
  def check_links_in_string(text, verbose=True, return_bad=False):
93
111
  """Process a given text, find unique URLs within it, and check for any 404 errors."""
94
- pattern = (
95
- r"\[([^\]]+)\]\(([^)]+)\)" # Matches Markdown links [text](url)
96
- r"|"
97
- r"(" # Start capturing group for plaintext URLs
98
- r"(?:https?://)?" # Optional http:// or https://
99
- r"(?:www\.)?" # Optional www.
100
- r"(?:[\w.-]+)?" # Optional domain name and subdomains
101
- r"\.[a-zA-Z]{2,}" # TLD
102
- r"(?:/[^\s\"')\]]*)?" # Optional path
103
- r")"
104
- )
105
- # all_urls.extend([url for url in match if url and parse.urlparse(url).scheme])
106
112
  all_urls = []
107
- for md_text, md_url, plain_url in re.findall(pattern, text):
113
+ for md_text, md_url, plain_url in URL_PATTERN.findall(text):
108
114
  url = md_url or plain_url
109
115
  if url and parse.urlparse(url).scheme:
110
116
  all_urls.append(url)
111
117
 
112
118
  urls = set(map(clean_url, all_urls)) # remove extra characters and make unique
113
- # bad_urls = [x for x in urls if not is_url(x, check=True)] # single-thread
114
- with ThreadPoolExecutor(max_workers=16) as executor: # multi-thread
115
- bad_urls = [url for url, valid in zip(urls, executor.map(lambda x: not is_url(x, check=True), urls)) if valid]
119
+ with requests.Session() as session, ThreadPoolExecutor(max_workers=16) as executor:
120
+ session.headers.update(REQUESTS_HEADERS)
121
+ bad_urls = [url for url, valid in zip(urls, executor.map(lambda x: not is_url(x, session), urls)) if valid]
116
122
 
117
123
  passing = not bad_urls
118
124
  if verbose and not passing:
@@ -122,4 +128,8 @@ def check_links_in_string(text, verbose=True, return_bad=False):
122
128
 
123
129
 
124
130
  if __name__ == "__main__":
125
- print(is_url("https://ultralytics.com/images/bus.jpg"))
131
+ url = "https://ultralytics.com/images/bus.jpg"
132
+ string = f"This is a string with a [Markdown link]({url}) inside it."
133
+
134
+ print(f"is_url(): {is_url(url)}")
135
+ print(f"check_links_in_string(): {check_links_in_string(string)}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ultralytics-actions
3
- Version: 0.0.44
3
+ Version: 0.0.46
4
4
  Summary: Ultralytics Actions for GitHub automation and PR management.
5
5
  Author-email: Glenn Jocher <glenn.jocher@ultralytics.com>
6
6
  Maintainer-email: Ultralytics <hello@ultralytics.com>
@@ -0,0 +1,15 @@
1
+ actions/__init__.py,sha256=ayOOJ0aHxao_KGb0rwJcpBCECN5nzyxr-Y8lg-s1OwE,742
2
+ actions/first_interaction.py,sha256=Oosw3GlXObF4RxYJG8haIjKXSV4MAx_uPXfMdRKY5qA,17851
3
+ actions/summarize_pr.py,sha256=Pfcm6ArfZfcMme48FcCGNmMwrFFlsG0czifhXHDKAlY,11166
4
+ actions/summarize_release.py,sha256=2D1IIeS4xrQNEJER3HItm5u9XvTL8hwGX_jWD2S8q1Y,8455
5
+ actions/update_markdown_code_blocks.py,sha256=DN6rrDw2VHXUTetrrg1SHlYDco9iaGOfQBKFORqbCBI,6362
6
+ actions/utils/__init__.py,sha256=WStdEAYROVnF0nubEOmrFLrejkRiMXIefA5O1ckfcFs,476
7
+ actions/utils/common_utils.py,sha256=2HFUz3bCMvzr9X0zqkOwJKWKddNdtYFEILsAMUrLHGI,4846
8
+ actions/utils/github_utils.py,sha256=0h0Hz2tgUta61Ymn9YggRXBZ7aZdF5krKnX7Tj9jqRU,7068
9
+ actions/utils/openai_utils.py,sha256=U7DjxTdFGdhmWSE4_KIg1yPQdtrfG4GkbNZCgMw4_1Q,1822
10
+ ultralytics_actions-0.0.46.dist-info/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
11
+ ultralytics_actions-0.0.46.dist-info/METADATA,sha256=hpvH9Ch2NhuhcTcLvUv6GOmr-pQFL0w6qSKAUhRGW5g,10561
12
+ ultralytics_actions-0.0.46.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
13
+ ultralytics_actions-0.0.46.dist-info/entry_points.txt,sha256=GowvOFplj0C7JmsjbKcbpgLpdf2r921pcaOQkAHWZRA,378
14
+ ultralytics_actions-0.0.46.dist-info/top_level.txt,sha256=5apM5x80QlJcGbACn1v3fkmIuL1-XQCKcItJre7w7Tw,8
15
+ ultralytics_actions-0.0.46.dist-info/RECORD,,
@@ -1,15 +0,0 @@
1
- actions/__init__.py,sha256=hIhJBdHAJFF5RjLVqpEhHB5ahmlGCV4aqLSqkdqr4NA,742
2
- actions/first_interaction.py,sha256=YKW7pPFrG-IxzvRoR4UYe0i8ehQdavwNSf7TzuQEAlA,17848
3
- actions/summarize_pr.py,sha256=Pfcm6ArfZfcMme48FcCGNmMwrFFlsG0czifhXHDKAlY,11166
4
- actions/summarize_release.py,sha256=2D1IIeS4xrQNEJER3HItm5u9XvTL8hwGX_jWD2S8q1Y,8455
5
- actions/update_markdown_code_blocks.py,sha256=DN6rrDw2VHXUTetrrg1SHlYDco9iaGOfQBKFORqbCBI,6362
6
- actions/utils/__init__.py,sha256=Jc--odEZWBrQmgI9C9rPdKIJNj8YW-mCJV71VWQyMCA,434
7
- actions/utils/common_utils.py,sha256=jcMtuFERmZXvDOUW6YclFNclIssxw3w7E7ilI68RpxU,4970
8
- actions/utils/github_utils.py,sha256=0h0Hz2tgUta61Ymn9YggRXBZ7aZdF5krKnX7Tj9jqRU,7068
9
- actions/utils/openai_utils.py,sha256=U7DjxTdFGdhmWSE4_KIg1yPQdtrfG4GkbNZCgMw4_1Q,1822
10
- ultralytics_actions-0.0.44.dist-info/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
11
- ultralytics_actions-0.0.44.dist-info/METADATA,sha256=hgyNZCI6KfkpzkSVh5O77x9P7CdLMZT2DSIjBTD0Gp4,10561
12
- ultralytics_actions-0.0.44.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
13
- ultralytics_actions-0.0.44.dist-info/entry_points.txt,sha256=GowvOFplj0C7JmsjbKcbpgLpdf2r921pcaOQkAHWZRA,378
14
- ultralytics_actions-0.0.44.dist-info/top_level.txt,sha256=5apM5x80QlJcGbACn1v3fkmIuL1-XQCKcItJre7w7Tw,8
15
- ultralytics_actions-0.0.44.dist-info/RECORD,,