indent 0.1.26__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.
Files changed (55) hide show
  1. exponent/__init__.py +34 -0
  2. exponent/cli.py +110 -0
  3. exponent/commands/cloud_commands.py +585 -0
  4. exponent/commands/common.py +411 -0
  5. exponent/commands/config_commands.py +334 -0
  6. exponent/commands/run_commands.py +222 -0
  7. exponent/commands/settings.py +56 -0
  8. exponent/commands/types.py +111 -0
  9. exponent/commands/upgrade.py +29 -0
  10. exponent/commands/utils.py +146 -0
  11. exponent/core/config.py +180 -0
  12. exponent/core/graphql/__init__.py +0 -0
  13. exponent/core/graphql/client.py +61 -0
  14. exponent/core/graphql/get_chats_query.py +47 -0
  15. exponent/core/graphql/mutations.py +160 -0
  16. exponent/core/graphql/queries.py +146 -0
  17. exponent/core/graphql/subscriptions.py +16 -0
  18. exponent/core/remote_execution/checkpoints.py +212 -0
  19. exponent/core/remote_execution/cli_rpc_types.py +499 -0
  20. exponent/core/remote_execution/client.py +999 -0
  21. exponent/core/remote_execution/code_execution.py +77 -0
  22. exponent/core/remote_execution/default_env.py +31 -0
  23. exponent/core/remote_execution/error_info.py +45 -0
  24. exponent/core/remote_execution/exceptions.py +10 -0
  25. exponent/core/remote_execution/file_write.py +35 -0
  26. exponent/core/remote_execution/files.py +330 -0
  27. exponent/core/remote_execution/git.py +268 -0
  28. exponent/core/remote_execution/http_fetch.py +94 -0
  29. exponent/core/remote_execution/languages/python_execution.py +239 -0
  30. exponent/core/remote_execution/languages/shell_streaming.py +226 -0
  31. exponent/core/remote_execution/languages/types.py +20 -0
  32. exponent/core/remote_execution/port_utils.py +73 -0
  33. exponent/core/remote_execution/session.py +128 -0
  34. exponent/core/remote_execution/system_context.py +26 -0
  35. exponent/core/remote_execution/terminal_session.py +375 -0
  36. exponent/core/remote_execution/terminal_types.py +29 -0
  37. exponent/core/remote_execution/tool_execution.py +595 -0
  38. exponent/core/remote_execution/tool_type_utils.py +39 -0
  39. exponent/core/remote_execution/truncation.py +296 -0
  40. exponent/core/remote_execution/types.py +635 -0
  41. exponent/core/remote_execution/utils.py +477 -0
  42. exponent/core/types/__init__.py +0 -0
  43. exponent/core/types/command_data.py +206 -0
  44. exponent/core/types/event_types.py +89 -0
  45. exponent/core/types/generated/__init__.py +0 -0
  46. exponent/core/types/generated/strategy_info.py +213 -0
  47. exponent/migration-docs/login.md +112 -0
  48. exponent/py.typed +4 -0
  49. exponent/utils/__init__.py +0 -0
  50. exponent/utils/colors.py +92 -0
  51. exponent/utils/version.py +289 -0
  52. indent-0.1.26.dist-info/METADATA +38 -0
  53. indent-0.1.26.dist-info/RECORD +55 -0
  54. indent-0.1.26.dist-info/WHEEL +4 -0
  55. indent-0.1.26.dist-info/entry_points.txt +2 -0
@@ -0,0 +1,289 @@
1
+ import asyncio
2
+ import os
3
+ import platform
4
+ import subprocess
5
+ import sys
6
+ import threading
7
+ from importlib.metadata import Distribution, PackageNotFoundError
8
+ from json import JSONDecodeError
9
+ from typing import Any, Literal, cast
10
+
11
+ import click
12
+ from httpx import Client, HTTPError
13
+ from packaging.version import Version
14
+
15
+ from exponent import __version__ # Import the new version constant
16
+ from exponent.core.config import Settings, is_editable_install
17
+
18
+
19
+ def get_python_path() -> str:
20
+ """Get the path to the Python interpreter."""
21
+ try:
22
+ return (
23
+ subprocess.check_output(["which", "python"])
24
+ .decode(errors="replace")
25
+ .strip()
26
+ )
27
+ except Exception:
28
+ return "unknown"
29
+
30
+
31
+ def get_sys_executable() -> str:
32
+ """Get the path to the Python interpreter."""
33
+ return str(sys.executable)
34
+
35
+
36
+ def get_installed_version() -> str | Literal["unknown"]:
37
+ """Get the running version of exponent-run. Note this may be different from
38
+ importlib version, if a new version is installed but we're running the old version."""
39
+ return __version__
40
+
41
+
42
+ def get_installed_metadata() -> Any | Literal["unknown"]:
43
+ """Get the installed metadata of exponent-run.
44
+
45
+ Returns:
46
+ The installed metadata of exponent-run if it can be determined, otherwise "unknown"
47
+ """
48
+ try:
49
+ return Distribution.from_name("indent").metadata
50
+ except PackageNotFoundError as e:
51
+ click.echo(f"Error reading metadata: {e}", err=True)
52
+ return "unknown"
53
+
54
+
55
+ def get_installer() -> str | Literal["unknown"]:
56
+ """Get the installer of exponent-run.
57
+
58
+ Returns:
59
+ The installer of exponent-run if it can be determined, otherwise "unknown"
60
+ """
61
+ try:
62
+ dist = Distribution.from_name("indent")
63
+ # Try to read the INSTALLER file from the distribution
64
+ installer_files = dist.read_text("INSTALLER")
65
+ if installer_files:
66
+ return installer_files.strip()
67
+ return "unknown"
68
+ except Exception:
69
+ return "unknown"
70
+
71
+
72
+ def get_latest_pypi_exponent_version() -> str | None:
73
+ """Get the latest version of Exponent available on PyPI.
74
+
75
+ Returns:
76
+ The newest version of Exponent available on PyPI, or None if an error occurred.
77
+ """
78
+ try:
79
+ return cast(
80
+ str,
81
+ (
82
+ Client()
83
+ .get("https://pypi.org/pypi/indent/json")
84
+ .json()["info"]["version"]
85
+ ),
86
+ )
87
+ except (HTTPError, JSONDecodeError, KeyError):
88
+ click.secho(
89
+ "An unexpected error occurred communicating with PyPi, please check your network and try again.",
90
+ fg="red",
91
+ )
92
+ return None
93
+
94
+
95
+ def check_exponent_version() -> tuple[str, str] | None:
96
+ """Check if there is a newer version of Exponent available on PyPI .
97
+
98
+ Returns:
99
+ None
100
+ """
101
+
102
+ if os.getenv("EXPONENT_TEST_AUTO_UPGRADE"):
103
+ return "1.0.0", "1.0.1"
104
+ installed_version = get_installed_version()
105
+ if installed_version == "unknown":
106
+ click.secho("Unable to determine current Exponent version.", fg="yellow")
107
+ return None
108
+
109
+ if (latest_version := get_latest_pypi_exponent_version()) and Version(
110
+ latest_version
111
+ ) > Version(installed_version):
112
+ return installed_version, latest_version
113
+
114
+ return None
115
+
116
+
117
+ def _get_upgrade_command(version: str) -> list[str]:
118
+ """Get the install command for exponent."""
119
+
120
+ return [
121
+ sys.executable,
122
+ "-m",
123
+ "pip",
124
+ "install",
125
+ "--upgrade",
126
+ f"indent=={version}",
127
+ ]
128
+
129
+
130
+ def _get_upgrade_command_str(version: str) -> str:
131
+ """Get the install command for exponent."""
132
+
133
+ return f'{sys.executable} -m pip install --upgrade "indent=={version}"'
134
+
135
+
136
+ def _new_version_str(current_version: str, new_version: str) -> str:
137
+ return (
138
+ f"\n{click.style('A new Indent version is available:', fg='cyan')} {new_version} (current: {current_version})\n"
139
+ f"See {click.style('https://docs.indent.com/help_and_resources/troubleshooting#installation-methods', underline=True)} for details.\n"
140
+ )
141
+
142
+
143
+ def _windows_new_version_str(current_version: str, new_version: str) -> str:
144
+ return f"{_new_version_str(current_version, new_version)}\n{click.style('Run this command to upgrade:', fg='cyan')}\n{click.style(_get_upgrade_command_str(new_version), fg='yellow')}\n"
145
+
146
+
147
+ def _ask_continue_without_upgrading() -> None:
148
+ if click.confirm("Continue without upgrading?", default=False):
149
+ click.secho("Using outdated version.", fg="red")
150
+ else:
151
+ sys.exit(1)
152
+
153
+
154
+ def upgrade_exponent(
155
+ *,
156
+ current_version: str,
157
+ new_version: str,
158
+ force: bool,
159
+ ) -> None:
160
+ """Upgrade Exponent to the passed in version.
161
+
162
+ Args:
163
+ current_version: The current version of Exponent.
164
+ new_version: The new version of Exponent.
165
+ force: Whether to force the upgrade without prompting for confirmation.
166
+
167
+ Returns:
168
+ None
169
+ """
170
+ new_version_str = _new_version_str(current_version, new_version)
171
+ upgrade_command = _get_upgrade_command(new_version)
172
+ upgrade_command_str = _get_upgrade_command_str(new_version)
173
+
174
+ if platform.system() == "Windows":
175
+ click.echo(_windows_new_version_str(current_version, new_version))
176
+ return
177
+
178
+ if not force:
179
+ click.echo(
180
+ f"{new_version_str}\n{click.style('Upgrade command:', fg='cyan')}\n{upgrade_command_str}\n",
181
+ )
182
+
183
+ if not click.confirm("Upgrade now?", default=True):
184
+ return
185
+ else:
186
+ click.echo(f"Current version: {current_version}")
187
+ click.echo(f"New version available: {new_version}")
188
+
189
+ click.secho("Upgrading...", bold=True, fg="yellow")
190
+ result = subprocess.run(
191
+ upgrade_command, capture_output=True, text=True, check=False
192
+ )
193
+
194
+ click.echo(result.stdout)
195
+ click.echo(result.stderr)
196
+
197
+ if result.returncode != 0:
198
+ click.secho(
199
+ "\nFailed to upgrade Indent. See https://docs.indent.com/help_and_resources/troubleshooting#installation-methods for help, or reach out to team@indent.com",
200
+ fg="red",
201
+ )
202
+ sys.exit(2)
203
+
204
+ click.secho(f"Successfully upgraded Indent to version {new_version}!", fg="green")
205
+
206
+ click.echo("Re-run indent to use the latest version.")
207
+ sys.exit(0)
208
+
209
+
210
+ def _upgrade_thread_worker(
211
+ upgrade_command: list[str],
212
+ current_version: str,
213
+ new_version: str,
214
+ settings: Settings,
215
+ ) -> None:
216
+ """Execute the upgrade command in a background thread and log completion status.
217
+
218
+ Args:
219
+ upgrade_command: The upgrade command to execute
220
+ current_version: The current version of Exponent
221
+ new_version: The target version to upgrade to
222
+ """
223
+ from exponent.core.remote_execution.session import send_exception_log
224
+
225
+ try:
226
+ result = subprocess.run(
227
+ upgrade_command,
228
+ capture_output=True,
229
+ text=True,
230
+ check=True,
231
+ )
232
+
233
+ if result.returncode != 0:
234
+ raise Exception(
235
+ f"Background upgrade from {current_version} to {new_version} failed with code {result.returncode}\nstdout: {result.stdout}\nstderr: {result.stderr}"
236
+ )
237
+ except Exception as e:
238
+ asyncio.run(send_exception_log(e, session=None, settings=settings))
239
+
240
+
241
+ def upgrade_exponent_in_background(
242
+ current_version: str,
243
+ new_version: str,
244
+ settings: Settings,
245
+ ) -> None:
246
+ """Upgrade Exponent to the passed in version in a background thread."""
247
+
248
+ if not settings.options.auto_upgrade:
249
+ click.secho(
250
+ "A new version of Exponent is available, but automatic upgrades are disabled. Please upgrade manually using `exponent upgrade`.\n",
251
+ fg="yellow",
252
+ )
253
+ return
254
+
255
+ if platform.system() == "Windows":
256
+ click.echo(
257
+ _windows_new_version_str(current_version, new_version),
258
+ )
259
+ _ask_continue_without_upgrading()
260
+ return
261
+
262
+ click.secho(
263
+ f"\nUpgrading Indent from {current_version} to {new_version} (this will take effect next time)\n",
264
+ fg="cyan",
265
+ bold=True,
266
+ )
267
+
268
+ # Start a background thread for the upgrade
269
+ upgrade_thread = threading.Thread(
270
+ target=_upgrade_thread_worker,
271
+ args=(
272
+ _get_upgrade_command(new_version),
273
+ current_version,
274
+ new_version,
275
+ settings,
276
+ ),
277
+ daemon=True, # Make thread a daemon so it doesn't prevent program exit
278
+ )
279
+ upgrade_thread.start()
280
+
281
+
282
+ def check_exponent_version_and_upgrade(settings: Settings) -> None:
283
+ if not is_editable_install() and (result := check_exponent_version()):
284
+ installed_version, latest_version = result
285
+ upgrade_exponent_in_background(
286
+ current_version=installed_version,
287
+ new_version=latest_version,
288
+ settings=settings,
289
+ )
@@ -0,0 +1,38 @@
1
+ Metadata-Version: 2.4
2
+ Name: indent
3
+ Version: 0.1.26
4
+ Summary: Indent is an AI Pair Programmer
5
+ Author-email: Sashank Thupukari <sashank@exponent.run>
6
+ Requires-Python: <3.13,>=3.10
7
+ Requires-Dist: aiohttp>=3.13.2
8
+ Requires-Dist: anyio<5,>=4.6.0
9
+ Requires-Dist: async-timeout<5,>=4.0.3; python_version < '3.11'
10
+ Requires-Dist: beautifulsoup4[chardet]<5,>=4.13.4
11
+ Requires-Dist: certifi<2025,>=2024.8.30
12
+ Requires-Dist: click<9,>=8.1.7
13
+ Requires-Dist: colour<0.2,>=0.1.5
14
+ Requires-Dist: diff-match-patch<20230431,>=20230430
15
+ Requires-Dist: eval-type-backport<0.3,>=0.2.0
16
+ Requires-Dist: git-python>=1.0.3
17
+ Requires-Dist: gitignore-parser<0.2,>=0.1.11
18
+ Requires-Dist: gql[httpx,websockets]~=4.0
19
+ Requires-Dist: httpx>=0.28.1
20
+ Requires-Dist: ipykernel<7,>=6.29.4
21
+ Requires-Dist: jupyter-client<9,>=8.6.1
22
+ Requires-Dist: msgspec>=0.19.0
23
+ Requires-Dist: packaging~=24.1
24
+ Requires-Dist: pip<26,>=25.0.1
25
+ Requires-Dist: prompt-toolkit<4,>=3.0.36
26
+ Requires-Dist: psutil<7,>=5.9.0
27
+ Requires-Dist: pydantic-ai==0.0.30
28
+ Requires-Dist: pydantic-settings<3,>=2.2.1
29
+ Requires-Dist: pydantic[email]<3,>=2.6.4
30
+ Requires-Dist: pygit2<2,>=1.15.0
31
+ Requires-Dist: python-ripgrep==0.0.9
32
+ Requires-Dist: pyyaml>=6.0.2
33
+ Requires-Dist: questionary<3,>=2.0.1
34
+ Requires-Dist: rapidfuzz<4,>=3.9.0
35
+ Requires-Dist: rich<14,>=13.7.1
36
+ Requires-Dist: sentry-sdk<3,>=2.1.1
37
+ Requires-Dist: toml<0.11,>=0.10.2
38
+ Requires-Dist: websockets~=15.0
@@ -0,0 +1,55 @@
1
+ exponent/__init__.py,sha256=Y9o7KiJWiG6n9XbSpMICgNgajFRbL4an-gN1BQc-jwM,706
2
+ exponent/cli.py,sha256=QnIeDTgWaQJrRs5WESCkQpVEQiJiAO4qWgB0rYlkd78,3344
3
+ exponent/py.typed,sha256=9XZl5avs8yHp89XP_1Fjtbeg_2rjYorCC9I0k_j-h2c,334
4
+ exponent/commands/cloud_commands.py,sha256=yd0d7l8AaFZIgrFPRYspsKlmcyFqkK_ovSQKhK-YpVU,16773
5
+ exponent/commands/common.py,sha256=M2KI9yKjB8fecPoDBphMa123c35-iNeaE9q4DxhkaFU,12817
6
+ exponent/commands/config_commands.py,sha256=mmQYuyRosODgawoHWsn9xnWnV37GiQaxJjMv-_xreAU,8902
7
+ exponent/commands/run_commands.py,sha256=xn0SJX0PPrmHu8Nh-kG-lJBhGC4qFCc04aLIzdVyFho,6389
8
+ exponent/commands/settings.py,sha256=UwwwoCgCY5hzAFD9slOBbA9Gr1hNfoyJ2blsFDC6V8w,1559
9
+ exponent/commands/types.py,sha256=iDJL3hdwhO1PrhsJTJBioNYSKo0CWV8Nv-ONcDaWIRs,3670
10
+ exponent/commands/upgrade.py,sha256=JZr0sNazziuLByQHdT8GZb-lDbRG1YpHW8VB94q-r8w,803
11
+ exponent/commands/utils.py,sha256=Z3eu3mvYwBh7J_hq17lyt7_MwMG8KcsP7AnsCgOnTNc,4638
12
+ exponent/core/config.py,sha256=TNFLUgLnfSocRMVSav_7E4VcaNHXZ_3Mg5Lp1smP46U,5731
13
+ exponent/core/graphql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ exponent/core/graphql/client.py,sha256=SRagD3YPyoYZSO1RtfO-OXD7b5dm1NvgoL6CTbN380o,2009
15
+ exponent/core/graphql/get_chats_query.py,sha256=9-2N1VfapXUZB3IFIKw5U_gKdmfyviJp5JSUntB_Yyk,1177
16
+ exponent/core/graphql/mutations.py,sha256=Szs8wS_5EpVuZdt09QbstIm_8i-_-EGT4Z17pou5714,2971
17
+ exponent/core/graphql/queries.py,sha256=RYsk8bub0esspqgakilhzX07yJf2652Ey9tBZK1l_lY,3297
18
+ exponent/core/graphql/subscriptions.py,sha256=SQngv_nYVNJjiZ_P2k0UcLIu1pzc4vi7q7lhH89NCZM,393
19
+ exponent/core/remote_execution/checkpoints.py,sha256=3QGYMLa8vT7XmxMYTRcGrW8kNGHwRC0AkUfULribJWg,6354
20
+ exponent/core/remote_execution/cli_rpc_types.py,sha256=dYeE2yNdcHLhWZLxHrKgkYL05xf8X7yMsOnunxejYH8,12772
21
+ exponent/core/remote_execution/client.py,sha256=bUl2w28c_okWndW9jEreVyYKeFNyL8h8OMZNBb4lf3g,40307
22
+ exponent/core/remote_execution/code_execution.py,sha256=QL78v2yHMrIcbNWIczAICWRceziXgG4pzw7gvhUOLxs,3328
23
+ exponent/core/remote_execution/default_env.py,sha256=s44A1Cz9EgYuhF17WO3ESVNSLQw57EoOLyi9k6qliIo,911
24
+ exponent/core/remote_execution/error_info.py,sha256=Rd7OA3ps06qYejPVcOaMBB9AtftP3wqQoOfiILFASnc,1378
25
+ exponent/core/remote_execution/exceptions.py,sha256=eT57lBnBhvh-KJ5lsKWcfgGA5-WisAxhjZx-Z6OupZY,135
26
+ exponent/core/remote_execution/file_write.py,sha256=8Sa70ANIDHGxIAq4_Uy2Qoo55K7-cSzU3282zyu7hG8,978
27
+ exponent/core/remote_execution/files.py,sha256=mIVjhStaEKETW6y3pCVeV8eJKNaPtroWGP_kBK1x8uA,8776
28
+ exponent/core/remote_execution/git.py,sha256=dGjBpeoKJZsYgRwctSq29GmbsNIN9tbSA3VwBnRD0IQ,7810
29
+ exponent/core/remote_execution/http_fetch.py,sha256=aFEyXd0S-MRfisSMuIFiEyc1AEAj9nUZ9Rj_P_YRows,2827
30
+ exponent/core/remote_execution/port_utils.py,sha256=kWje8ikCzBXMeS7qr6NZZOzQOMoMuacgPUDYyloYgwM,2183
31
+ exponent/core/remote_execution/session.py,sha256=jlQIdeUj0f7uOk3BgzlJtBJ_GyTIjCchBp5ApQuF2-I,3847
32
+ exponent/core/remote_execution/system_context.py,sha256=I4RNuM60isS-529EuRrrEPPwJssNFC2TZ_7MhBTWEd0,754
33
+ exponent/core/remote_execution/terminal_session.py,sha256=HQBmyJUvReXxu9z1iPhPHgNotSnCZrP8Tv5iZgUZkzQ,12247
34
+ exponent/core/remote_execution/terminal_types.py,sha256=t4snBiTtidAEJZTvy789x-5HFqjkV9rlonjDO30PfAY,731
35
+ exponent/core/remote_execution/tool_execution.py,sha256=wwKS7GiCsK_I0Na-Vo1xuzUR5wgbZ9bapck2iEuWmQo,20819
36
+ exponent/core/remote_execution/tool_type_utils.py,sha256=7qi6Qd8fvHts019ZSLPbtiy17BUqgqBg3P_gdfvFf7w,1301
37
+ exponent/core/remote_execution/truncation.py,sha256=0zFnmqXES2vtQCSpfXIQn5hgg6bZK4Sad_Cfh27xTZU,9849
38
+ exponent/core/remote_execution/types.py,sha256=2tp73g6WLhL3x-5FyP9jhadcRHIswt4wfJJlEvNwlvk,15782
39
+ exponent/core/remote_execution/utils.py,sha256=6PlBqYJ3OQwZ0dgXiIu3br04a-d-glDeDZpD0XGGPAE,14793
40
+ exponent/core/remote_execution/languages/python_execution.py,sha256=nsX_LsXcUcHhiEHpSTjOTVNd7CxM146al0kw_iQX5OU,7724
41
+ exponent/core/remote_execution/languages/shell_streaming.py,sha256=MpE1XQiu18xWUGp1wD_Hb1nuPCQE-i5-_XO6FnkcNvo,7675
42
+ exponent/core/remote_execution/languages/types.py,sha256=f7FjSRNRSga-ZaE3LddDhxCirUVjlSYMEdoskG6Pta4,314
43
+ exponent/core/types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
+ exponent/core/types/command_data.py,sha256=_HqQsnamRZeVoVaTpeO3ecVUzNBdG62WXlFy6Q7rtUM,5294
45
+ exponent/core/types/event_types.py,sha256=Hi9OMlLwB8f0TwPsKMThkXLFVzvOyJfMWk2urjPD1Uo,2468
46
+ exponent/core/types/generated/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
+ exponent/core/types/generated/strategy_info.py,sha256=LN6_ykFMszb21Qc3yw77xEKUtd7m4e-zzhPS1HZjvzE,6641
48
+ exponent/migration-docs/login.md,sha256=KIeXy3m2nzSUgw-4PW1XzXfHael1D4Zu93CplLMb3hI,4252
49
+ exponent/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
+ exponent/utils/colors.py,sha256=HBkqe_ZmhJ9YiL2Fpulqek4KvLS5mwBTY4LQSM5N8SM,2762
51
+ exponent/utils/version.py,sha256=GHZ9ET1kMyDubJZU3w2sah5Pw8XpiEakS5IOlt3wUnQ,8888
52
+ indent-0.1.26.dist-info/METADATA,sha256=yrbInVUlb5HN1DbhPe7p9ocp5FQR6JC0cHXMrguNzgM,1371
53
+ indent-0.1.26.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
54
+ indent-0.1.26.dist-info/entry_points.txt,sha256=q8q1t1sbl4NULGOR0OV5RmSG4KEjkpEQRU_RUXEGzcs,44
55
+ indent-0.1.26.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ indent = exponent.cli:cli