code-puppy 0.0.336__py3-none-any.whl → 0.0.337__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.
code_puppy/http_utils.py CHANGED
@@ -5,10 +5,10 @@ This module provides functions for creating properly configured HTTP clients.
5
5
  """
6
6
 
7
7
  import asyncio
8
- import logging
9
8
  import os
10
9
  import socket
11
10
  import time
11
+ from dataclasses import dataclass
12
12
  from typing import Any, Dict, Optional, Union
13
13
 
14
14
  import httpx
@@ -16,7 +16,69 @@ import requests
16
16
 
17
17
  from code_puppy.config import get_http2
18
18
 
19
- logger = logging.getLogger(__name__)
19
+
20
+ @dataclass
21
+ class ProxyConfig:
22
+ """Configuration for proxy and SSL settings."""
23
+
24
+ verify: Union[bool, str, None]
25
+ trust_env: bool
26
+ proxy_url: str | None
27
+ disable_retry: bool
28
+ http2_enabled: bool
29
+
30
+
31
+ def _resolve_proxy_config(verify: Union[bool, str, None] = None) -> ProxyConfig:
32
+ """Resolve proxy, SSL, and retry settings from environment.
33
+
34
+ This centralizes the logic for detecting proxies, determining SSL verification,
35
+ and checking if retry transport should be disabled.
36
+ """
37
+ if verify is None:
38
+ verify = get_cert_bundle_path()
39
+
40
+ http2_enabled = get_http2()
41
+
42
+ disable_retry = os.environ.get(
43
+ "CODE_PUPPY_DISABLE_RETRY_TRANSPORT", ""
44
+ ).lower() in ("1", "true", "yes")
45
+
46
+ has_proxy = bool(
47
+ os.environ.get("HTTP_PROXY")
48
+ or os.environ.get("HTTPS_PROXY")
49
+ or os.environ.get("http_proxy")
50
+ or os.environ.get("https_proxy")
51
+ )
52
+
53
+ # Determine trust_env and verify based on proxy/retry settings
54
+ if disable_retry:
55
+ # Test mode: disable SSL verification for proxy testing
56
+ verify = False
57
+ trust_env = True
58
+ elif has_proxy:
59
+ # Production proxy: keep SSL verification enabled
60
+ trust_env = True
61
+ else:
62
+ trust_env = False
63
+
64
+ # Extract proxy URL
65
+ proxy_url = None
66
+ if has_proxy:
67
+ proxy_url = (
68
+ os.environ.get("HTTPS_PROXY")
69
+ or os.environ.get("https_proxy")
70
+ or os.environ.get("HTTP_PROXY")
71
+ or os.environ.get("http_proxy")
72
+ )
73
+
74
+ return ProxyConfig(
75
+ verify=verify,
76
+ trust_env=trust_env,
77
+ proxy_url=proxy_url,
78
+ disable_retry=disable_retry,
79
+ http2_enabled=http2_enabled,
80
+ )
81
+
20
82
 
21
83
  try:
22
84
  from .reopenable_async_client import ReopenableAsyncClient
@@ -58,14 +120,7 @@ class RetryingAsyncClient(httpx.AsyncClient):
58
120
 
59
121
  for attempt in range(self.max_retries + 1):
60
122
  try:
61
- # Clone request for retry (streams might be consumed)
62
- # But only if it's not the first attempt
63
- req_to_send = request
64
- if attempt > 0:
65
- # httpx requests are reusable, but we need to be careful with streams
66
- pass
67
-
68
- response = await super().send(req_to_send, **kwargs)
123
+ response = await super().send(request, **kwargs)
69
124
  last_response = response
70
125
 
71
126
  # Check for retryable status
@@ -128,7 +183,7 @@ class RetryingAsyncClient(httpx.AsyncClient):
128
183
  return last_response
129
184
 
130
185
 
131
- def get_cert_bundle_path() -> str:
186
+ def get_cert_bundle_path() -> str | None:
132
187
  # First check if SSL_CERT_FILE environment variable is set
133
188
  ssl_cert_file = os.environ.get("SSL_CERT_FILE")
134
189
  if ssl_cert_file and os.path.exists(ssl_cert_file):
@@ -164,66 +219,26 @@ def create_async_client(
164
219
  headers: Optional[Dict[str, str]] = None,
165
220
  retry_status_codes: tuple = (429, 502, 503, 504),
166
221
  ) -> httpx.AsyncClient:
167
- if verify is None:
168
- verify = get_cert_bundle_path()
169
-
170
- # Check if HTTP/2 is enabled in config
171
- http2_enabled = get_http2()
172
-
173
- # Check if custom retry transport should be disabled (e.g., for integration tests with proxies)
174
- disable_retry_transport = os.environ.get(
175
- "CODE_PUPPY_DISABLE_RETRY_TRANSPORT", ""
176
- ).lower() in ("1", "true", "yes")
177
-
178
- # Check if proxy environment variables are set
179
- has_proxy = bool(
180
- os.environ.get("HTTP_PROXY")
181
- or os.environ.get("HTTPS_PROXY")
182
- or os.environ.get("http_proxy")
183
- or os.environ.get("https_proxy")
184
- )
185
-
186
- # When retry transport is disabled (test mode), disable SSL verification
187
- # for proxy testing. For production proxies, SSL should still be verified!
188
- if disable_retry_transport:
189
- verify = False
190
- trust_env = True
191
- elif has_proxy:
192
- # Production proxy detected - keep SSL verification enabled for security
193
- trust_env = True
194
- else:
195
- trust_env = False
196
-
197
- # Extract proxy URL if needed
198
- proxy_url = None
199
- if has_proxy:
200
- proxy_url = (
201
- os.environ.get("HTTPS_PROXY")
202
- or os.environ.get("https_proxy")
203
- or os.environ.get("HTTP_PROXY")
204
- or os.environ.get("http_proxy")
205
- )
222
+ config = _resolve_proxy_config(verify)
206
223
 
207
- # Use RetryingAsyncClient if retries are enabled
208
- if not disable_retry_transport:
224
+ if not config.disable_retry:
209
225
  return RetryingAsyncClient(
210
226
  retry_status_codes=retry_status_codes,
211
- proxy=proxy_url,
212
- verify=verify,
227
+ proxy=config.proxy_url,
228
+ verify=config.verify,
213
229
  headers=headers or {},
214
230
  timeout=timeout,
215
- http2=http2_enabled,
216
- trust_env=trust_env,
231
+ http2=config.http2_enabled,
232
+ trust_env=config.trust_env,
217
233
  )
218
234
  else:
219
- # Regular client for testing
220
235
  return httpx.AsyncClient(
221
- proxy=proxy_url,
222
- verify=verify,
236
+ proxy=config.proxy_url,
237
+ verify=config.verify,
223
238
  headers=headers or {},
224
239
  timeout=timeout,
225
- http2=http2_enabled,
226
- trust_env=trust_env,
240
+ http2=config.http2_enabled,
241
+ trust_env=config.trust_env,
227
242
  )
228
243
 
229
244
 
@@ -273,85 +288,33 @@ def create_reopenable_async_client(
273
288
  headers: Optional[Dict[str, str]] = None,
274
289
  retry_status_codes: tuple = (429, 502, 503, 504),
275
290
  ) -> Union[ReopenableAsyncClient, httpx.AsyncClient]:
276
- if verify is None:
277
- verify = get_cert_bundle_path()
278
-
279
- # Check if HTTP/2 is enabled in config
280
- http2_enabled = get_http2()
281
-
282
- # Check if custom retry transport should be disabled (e.g., for integration tests with proxies)
283
- disable_retry_transport = os.environ.get(
284
- "CODE_PUPPY_DISABLE_RETRY_TRANSPORT", ""
285
- ).lower() in ("1", "true", "yes")
286
-
287
- # Check if proxy environment variables are set
288
- has_proxy = bool(
289
- os.environ.get("HTTP_PROXY")
290
- or os.environ.get("HTTPS_PROXY")
291
- or os.environ.get("http_proxy")
292
- or os.environ.get("https_proxy")
293
- )
294
-
295
- # When retry transport is disabled (test mode), disable SSL verification
296
- if disable_retry_transport:
297
- verify = False
298
- trust_env = True
299
- elif has_proxy:
300
- trust_env = True
301
- else:
302
- trust_env = False
291
+ config = _resolve_proxy_config(verify)
303
292
 
304
- # Extract proxy URL if needed
305
- proxy_url = None
306
- if has_proxy:
307
- proxy_url = (
308
- os.environ.get("HTTPS_PROXY")
309
- or os.environ.get("https_proxy")
310
- or os.environ.get("HTTP_PROXY")
311
- or os.environ.get("http_proxy")
312
- )
293
+ base_kwargs = {
294
+ "proxy": config.proxy_url,
295
+ "verify": config.verify,
296
+ "headers": headers or {},
297
+ "timeout": timeout,
298
+ "http2": config.http2_enabled,
299
+ "trust_env": config.trust_env,
300
+ }
313
301
 
314
302
  if ReopenableAsyncClient is not None:
315
- # Use RetryingAsyncClient if retries are enabled
316
303
  client_class = (
317
- RetryingAsyncClient if not disable_retry_transport else httpx.AsyncClient
304
+ RetryingAsyncClient if not config.disable_retry else httpx.AsyncClient
318
305
  )
319
-
320
- # Pass retry config only if using RetryingAsyncClient
321
- kwargs = {
322
- "proxy": proxy_url,
323
- "verify": verify,
324
- "headers": headers or {},
325
- "timeout": timeout,
326
- "http2": http2_enabled,
327
- "trust_env": trust_env,
328
- }
329
-
330
- if not disable_retry_transport:
306
+ kwargs = {**base_kwargs, "client_class": client_class}
307
+ if not config.disable_retry:
331
308
  kwargs["retry_status_codes"] = retry_status_codes
332
-
333
- return ReopenableAsyncClient(client_class=client_class, **kwargs)
309
+ return ReopenableAsyncClient(**kwargs)
334
310
  else:
335
- # Fallback to RetryingAsyncClient
336
- if not disable_retry_transport:
311
+ # Fallback to RetryingAsyncClient or plain AsyncClient
312
+ if not config.disable_retry:
337
313
  return RetryingAsyncClient(
338
- retry_status_codes=retry_status_codes,
339
- proxy=proxy_url,
340
- verify=verify,
341
- headers=headers or {},
342
- timeout=timeout,
343
- http2=http2_enabled,
344
- trust_env=trust_env,
314
+ retry_status_codes=retry_status_codes, **base_kwargs
345
315
  )
346
316
  else:
347
- return httpx.AsyncClient(
348
- proxy=proxy_url,
349
- verify=verify,
350
- headers=headers or {},
351
- timeout=timeout,
352
- http2=http2_enabled,
353
- trust_env=trust_env,
354
- )
317
+ return httpx.AsyncClient(**base_kwargs)
355
318
 
356
319
 
357
320
  def is_cert_bundle_available() -> bool:
@@ -209,6 +209,9 @@ class ShellStartMessage(BaseMessage):
209
209
  default=None, description="Working directory for the command"
210
210
  )
211
211
  timeout: int = Field(default=60, description="Timeout in seconds")
212
+ background: bool = Field(
213
+ default=False, description="Whether command runs in background mode"
214
+ )
212
215
 
213
216
 
214
217
  class ShellLineMessage(BaseMessage):
@@ -620,15 +620,25 @@ class RichConsoleRenderer:
620
620
  safe_command = escape_rich_markup(msg.command)
621
621
  # Header showing command is starting
622
622
  banner = self._format_banner("shell_command", "SHELL COMMAND")
623
- self._console.print(f"\n{banner} 🚀 [dim]$ {safe_command}[/dim]")
623
+
624
+ # Add background indicator if running in background mode
625
+ if msg.background:
626
+ self._console.print(
627
+ f"\n{banner} 🚀 [dim]$ {safe_command}[/dim] [bold magenta][BACKGROUND 🌙][/bold magenta]"
628
+ )
629
+ else:
630
+ self._console.print(f"\n{banner} 🚀 [dim]$ {safe_command}[/dim]")
624
631
 
625
632
  # Show working directory if specified
626
633
  if msg.cwd:
627
634
  safe_cwd = escape_rich_markup(msg.cwd)
628
635
  self._console.print(f"[dim]📂 Working directory: {safe_cwd}[/dim]")
629
636
 
630
- # Show timeout
631
- self._console.print(f"[dim]⏱ Timeout: {msg.timeout}s[/dim]")
637
+ # Show timeout or background status
638
+ if msg.background:
639
+ self._console.print("[dim]⏱ Runs detached (no timeout)[/dim]")
640
+ else:
641
+ self._console.print(f"[dim]⏱ Timeout: {msg.timeout}s[/dim]")
632
642
 
633
643
  def _render_shell_line(self, msg: ShellLineMessage) -> None:
634
644
  """Render shell output line preserving ANSI codes."""
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import base64
3
4
  import json
4
5
  import logging
5
6
  from collections.abc import AsyncIterator
@@ -75,7 +76,16 @@ class AntigravityModel(GoogleModel):
75
76
  system_parts.append({"text": part.content})
76
77
  elif isinstance(part, UserPromptPart):
77
78
  # Use parent's _map_user_prompt
78
- message_parts.extend(await self._map_user_prompt(part))
79
+ mapped_parts = await self._map_user_prompt(part)
80
+ # Sanitize bytes to base64 for JSON serialization
81
+ for mp in mapped_parts:
82
+ if "inline_data" in mp and "data" in mp["inline_data"]:
83
+ data = mp["inline_data"]["data"]
84
+ if isinstance(data, bytes):
85
+ mp["inline_data"]["data"] = base64.b64encode(
86
+ data
87
+ ).decode("utf-8")
88
+ message_parts.extend(mapped_parts)
79
89
  elif isinstance(part, ToolReturnPart):
80
90
  message_parts.append(
81
91
  {
@@ -542,8 +552,13 @@ def _antigravity_content_model_response(
542
552
 
543
553
  elif isinstance(item, FilePart):
544
554
  content = item.content
555
+ # Ensure data is base64 string, not bytes
556
+ data_val = content.data
557
+ if isinstance(data_val, bytes):
558
+ data_val = base64.b64encode(data_val).decode("utf-8")
559
+
545
560
  inline_data_dict: BlobDict = {
546
- "data": content.data,
561
+ "data": data_val,
547
562
  "mime_type": content.media_type,
548
563
  }
549
564
  part["inline_data"] = inline_data_dict
@@ -880,6 +880,7 @@ async def run_shell_command(
880
880
  command=command,
881
881
  cwd=cwd,
882
882
  timeout=0, # No timeout for background processes
883
+ background=True,
883
884
  )
884
885
  )
885
886
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-puppy
3
- Version: 0.0.336
3
+ Version: 0.0.337
4
4
  Summary: Code generation agent
5
5
  Project-URL: repository, https://github.com/mpfaffenberger/code_puppy
6
6
  Project-URL: HomePage, https://github.com/mpfaffenberger/code_puppy
@@ -7,7 +7,7 @@ code_puppy/cli_runner.py,sha256=4iosJ_zXv9WcG4764yFW-VOLjE3B7Og9yclp6Q4kaSQ,3387
7
7
  code_puppy/config.py,sha256=RlnrLkyFXm7h2Htf8rQA7vqoAyzLPMrESle417uLmFw,52373
8
8
  code_puppy/error_logging.py,sha256=a80OILCUtJhexI6a9GM-r5LqIdjvSRzggfgPp2jv1X0,3297
9
9
  code_puppy/gemini_code_assist.py,sha256=KGS7sO5OLc83nDF3xxS-QiU6vxW9vcm6hmzilu79Ef8,13867
10
- code_puppy/http_utils.py,sha256=BV_bf0i5iPh7HC7T1vlsbz3hvlVwdIzwpS2pfBBKPRo,11823
10
+ code_puppy/http_utils.py,sha256=H3N5Qz2B1CcsGUYOycGWAqoNMr2P1NCVluKX3aRwRqI,10358
11
11
  code_puppy/keymap.py,sha256=IvMkTlB_bIqOWpbTpmftkdyjhtD5todXuEIw1zCZ4u0,3584
12
12
  code_puppy/main.py,sha256=82r3vZy_XcyEsenLn82BnUusaoyL3Bpm_Th_jKgqecE,273
13
13
  code_puppy/model_factory.py,sha256=Djhp_ukLTMNi8UdZsodhIU6D2X4DmJXnjZy_bzfce3k,37517
@@ -112,10 +112,10 @@ code_puppy/messaging/bus.py,sha256=TbdltJ0D5tqnaE4irq1fcXllDYm-mQ_SiX1IFm-S4sw,2
112
112
  code_puppy/messaging/commands.py,sha256=77CtKVNaF5KS3Xyzd0ccDAisZWQxL3weVEt3J-SfYxo,5464
113
113
  code_puppy/messaging/markdown_patches.py,sha256=dMIJozzJChuHa8QNMSEz_kC-dyt7kZiDLZ7rjthbcmg,1626
114
114
  code_puppy/messaging/message_queue.py,sha256=e-viZxacBoNSxRJnCJ4hU4vzsSI3oX_rN58RwhJKFfU,11825
115
- code_puppy/messaging/messages.py,sha256=vNenUTgeZLk2clH4-BLcj44vpzDMmAsOrbwn_msaCVw,16351
115
+ code_puppy/messaging/messages.py,sha256=F7RwMHeQrIk-8kuSSBU76wBq1NGuLb2H5cJrSMTC3XM,16464
116
116
  code_puppy/messaging/queue_console.py,sha256=T0U_V1tdN6hd9DLokp-HCk0mhu8Ivpfajha368CBZrU,9983
117
117
  code_puppy/messaging/renderers.py,sha256=GHVtMnxE1pJ-yrcRjacY81JcjlHRz3UVHzp-ohN-CGE,12058
118
- code_puppy/messaging/rich_renderer.py,sha256=YMj5bdZSjufzFL6kNUuNhsoI_NfXUfvWBQ1FDWPw2Ho,37480
118
+ code_puppy/messaging/rich_renderer.py,sha256=FiT1e5S8nNQte0E6CMFQ3KyTixadkgKSjp1hcZXtyOE,37892
119
119
  code_puppy/messaging/spinner/__init__.py,sha256=KpK5tJqq9YnN3wklqvdH0BQmuwYnT83Mp4tPfQa9RqI,1664
120
120
  code_puppy/messaging/spinner/console_spinner.py,sha256=YIReuWPD01YPy58FqWdMDWj2QhauTUxKo675Ub4-eDA,8451
121
121
  code_puppy/messaging/spinner/spinner_base.py,sha256=JiQDAhCfwrWUFunb8Xcj1caEl34JJY7Bcio7mDeckSc,2694
@@ -123,7 +123,7 @@ code_puppy/plugins/__init__.py,sha256=gWgrXWoFpl-3Mxz2DAvxKW6SkCWrOnw-hKsY9O7nHc
123
123
  code_puppy/plugins/oauth_puppy_html.py,sha256=Wpa-V_NlRiBAvo_OXHuR7wvOH_jSt8L9HSFGiab6xI0,13058
124
124
  code_puppy/plugins/antigravity_oauth/__init__.py,sha256=1miHihSqRNXO20Vh_Gn9M3Aa2szh0gtdSCaKKj9nq0Q,362
125
125
  code_puppy/plugins/antigravity_oauth/accounts.py,sha256=GQit2-K24bsopmTZyscFUq3M0cAEO5WutHWnipVdgz8,14304
126
- code_puppy/plugins/antigravity_oauth/antigravity_model.py,sha256=FgZtXHsyTIX0wcJB7ivcdFd5DpRLqDFO_idcvMuDKtc,25336
126
+ code_puppy/plugins/antigravity_oauth/antigravity_model.py,sha256=g0_nXnMg288CvBE48CFgZ-iAqlYbtbi1dcB4Up6cYYc,26115
127
127
  code_puppy/plugins/antigravity_oauth/config.py,sha256=BoQgqf5I2XoHWnBBo9vhCIc_XwPj9Mbp0Z95ygWwt78,1362
128
128
  code_puppy/plugins/antigravity_oauth/constants.py,sha256=qsrA10JJvzNuY0OobvvwCQcoGpILBninllcUUMKkUrQ,4644
129
129
  code_puppy/plugins/antigravity_oauth/oauth.py,sha256=ZHXJtZP63l6brOpX1WdLfuUClIleA79-4y36YUJc6Wo,15137
@@ -159,7 +159,7 @@ code_puppy/plugins/shell_safety/register_callbacks.py,sha256=W3v664RR48Fdbbbltf_
159
159
  code_puppy/prompts/codex_system_prompt.md,sha256=hEFTCziroLqZmqNle5kG34A8kvTteOWezCiVrAEKhE0,24400
160
160
  code_puppy/tools/__init__.py,sha256=BVTZ85jLHgDANwOnUSOz3UDlp8VQDq4DoGF23BRlyWw,6032
161
161
  code_puppy/tools/agent_tools.py,sha256=snBI6FlFtR03CbYKXwu53R48c_fRSuDIwcNdVUruLcA,21020
162
- code_puppy/tools/command_runner.py,sha256=4RlgPWWE2Mk35t69QJWR4Md4etMGLR2rFSZAKrNohU4,44917
162
+ code_puppy/tools/command_runner.py,sha256=3qXVnVTaBPia6y2D29As47_TRKgpyCj82yMFK-8UUYc,44954
163
163
  code_puppy/tools/common.py,sha256=IboS6sbwN4a3FzHdfsZJtEFiyDUCszevI6LpH14ydEk,40561
164
164
  code_puppy/tools/file_modifications.py,sha256=vz9n7R0AGDSdLUArZr_55yJLkyI30M8zreAppxIx02M,29380
165
165
  code_puppy/tools/file_operations.py,sha256=CqhpuBnOFOcQCIYXOujskxq2VMLWYJhibYrH0YcPSfA,35692
@@ -174,10 +174,10 @@ code_puppy/tools/browser/browser_scripts.py,sha256=sNb8eLEyzhasy5hV4B9OjM8yIVMLV
174
174
  code_puppy/tools/browser/browser_workflows.py,sha256=nitW42vCf0ieTX1gLabozTugNQ8phtoFzZbiAhw1V90,6491
175
175
  code_puppy/tools/browser/camoufox_manager.py,sha256=RZjGOEftE5sI_tsercUyXFSZI2wpStXf-q0PdYh2G3I,8680
176
176
  code_puppy/tools/browser/vqa_agent.py,sha256=DBn9HKloILqJSTSdNZzH_PYWT0B2h9VwmY6akFQI_uU,2913
177
- code_puppy-0.0.336.data/data/code_puppy/models.json,sha256=IPABdOrDw2OZJxa0XGBWSWmBRerV6_pIEmKVLRtUbAk,3105
178
- code_puppy-0.0.336.data/data/code_puppy/models_dev_api.json,sha256=wHjkj-IM_fx1oHki6-GqtOoCrRMR0ScK0f-Iz0UEcy8,548187
179
- code_puppy-0.0.336.dist-info/METADATA,sha256=K0YyE2O8F9-nMuMdbs2rAovJHJmtQox98_r4beIjGPA,28854
180
- code_puppy-0.0.336.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
181
- code_puppy-0.0.336.dist-info/entry_points.txt,sha256=Tp4eQC99WY3HOKd3sdvb22vZODRq0XkZVNpXOag_KdI,91
182
- code_puppy-0.0.336.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
183
- code_puppy-0.0.336.dist-info/RECORD,,
177
+ code_puppy-0.0.337.data/data/code_puppy/models.json,sha256=IPABdOrDw2OZJxa0XGBWSWmBRerV6_pIEmKVLRtUbAk,3105
178
+ code_puppy-0.0.337.data/data/code_puppy/models_dev_api.json,sha256=wHjkj-IM_fx1oHki6-GqtOoCrRMR0ScK0f-Iz0UEcy8,548187
179
+ code_puppy-0.0.337.dist-info/METADATA,sha256=F1DCPuk3QS0E2t1o_HRId-DiNTtOs29kcmSueGwHUHk,28854
180
+ code_puppy-0.0.337.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
181
+ code_puppy-0.0.337.dist-info/entry_points.txt,sha256=Tp4eQC99WY3HOKd3sdvb22vZODRq0XkZVNpXOag_KdI,91
182
+ code_puppy-0.0.337.dist-info/licenses/LICENSE,sha256=31u8x0SPgdOq3izJX41kgFazWsM43zPEF9eskzqbJMY,1075
183
+ code_puppy-0.0.337.dist-info/RECORD,,